Bài 41: Phần mềm xử lý tin nhắn rắc


Ở bài tập 40 Tui đã trình bày cách đăng ký BroadCast Receiver để lắng nghe tin nhắn gửi tới trong Coding, Ở  bài tập này Tui sẽ trình bày cách đăng ký và xử lý BroadCast Receiver bằng Manifest. Ứng dụng này là thực tế, các bạn có thể cài đặt vào thiết bị thật để kiểm tra.

Bài này Tui sẽ lấy kết quả bài làm của Sinh viên học lớp Tui để demo cho các bạn xem, các bạn có thể liên hệ với bạn này để trao đổi học thuật. Tên của bạn là Nguyễn Tấn Nhân, email Nhan.NguyenTan@uni.dntu.edu.vn

Bài Tui yêu cầu các bạn làm bài như sau:

–          Viết ứng dụng Android xử lý tin nhắn rác.

–          Hiện nay rất nhiều tin nhắn quẳng cáo gửi vô tội vạ, cái Alô của bạn phải nhận rất nhiều tin nhắn như thế gây phiền hà và mất thời gian cho bạn.

–          Hãy viết chương trình để giải quyết vấn đề này, yêu cầu như sau:

  • Chương trình có giao diện thêm, sửa, xóa các đầu số mà bạn cho là đầu số rác. Như vậy nên dùng SQLite hoặc XML để lưu các đầu số rác.
  • Chương trình phải tự động nhận tin nhắn và phát hiện ra được tin nhắn nào là gửi đi từ các đầu số rác đó.
  • Nếu phát hiện ra đó là đầu số rác  thì xóa nó khỏi inbox của messaging đồng thời phát ra Audio là “đây là tin nhắn rác, đã bị xử” để người sử dụng không phải mở điện thoại lên xem.

–          Yêu cầu viết theo 2 cách (tức là bài tập này làm thành 2 Project khác nhau):

  • Đăng ký Broadcast Receiver để nhận tin nhắn tới trong coding
  • Đăng ký Broadcast Receiver để nhận tin nhắn tới trong Manifest XML

–          Sau khi làm xong theo 2 cách trên, hãy so sánh sự khác biệt giữa chúng. Và kết luận chúng ta nên chọn cách nào?

–          Chương trình phải cài đặt và chạy được trên điện thoại Android thiệt.

rac1

–          Khi nhấn thật lâu vào 1 đầu số trong ListView thì số này sẽ tự động Remove khỏi CSDL

– Dưới đây là kết quả bài làm mà sinh viên trên đã tự thực hiện:

– Tôi sẽ để nguyễn mẫu và không giải thích, các bạn nếu không hiểu thì hãy email trực tiếp để hỏi sinh viên này:

s0

XML Layout của màn hình chính:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="2dp"
    android:paddingLeft="2dp"
    android:paddingRight="2dp"
    android:paddingTop="2dp"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#008000"
        android:gravity="center_horizontal"
        android:text="Quản lý tin nhắn rác"
        android:textColor="#FFF"
        android:textSize="26sp" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#FFFF00"
        android:text="Nhập vào số rác:"
        android:textSize="18sp" />

    <EditText
        android:id="@+id/editPrefixPhoneNum"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10" >

        <requestFocus />
    </EditText>

    <Button
        android:id="@+id/btnSave"
        style="?android:attr/buttonStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="Lưu số rác này"
        android:textSize="18sp" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#FFFF00"
        android:gravity="center_horizontal"
        android:text="Danh sách số phone rác"
        android:textSize="18sp" />

    <ListView
        android:id="@+id/lstviewList"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

</LinearLayout>

Để tương tác với SMS thì ta cấu hình trong Manifest như sau:


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 package="vn.edu.it.nguyentannhan.id1200911"
 android:versionCode="1"
 android:versionName="1.0" >

<uses-sdk
 android:minSdkVersion="8"
 android:targetSdkVersion="17" />
 <uses-permission android:name="android.permission.RECEIVE_SMS"/>
 <uses-permission android:name="android.permission.WRITE_SMS"/>
 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<application
 android:allowBackup="true"
 android:icon="@drawable/ic_launcher"
 android:label="@string/app_name"
 android:theme="@style/AppTheme" >
 <activity
 android:name="vn.edu.it.nguyentannhan.id1200911.MainActivity"
 android:label="@string/app_name" >
 <intent-filter>
 <action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
 </intent-filter>
 </activity>
 <receiver android:name="MySmsReceive">
 <intent-filter>
 <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
 </intent-filter>
 </receiver>
 </application>

</manifest>

Xử lý coding:

MainActivity:


package vn.edu.it.nguyentannhan.id1200911;
import java.util.ArrayList;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends Activity {

SQLiteDatabase sqlite;
 Button btnSave;
 EditText editFrefixNum;
 ListView lstPreNum;
 //
 //String idUpdate="";
 //
 ArrayList<String>arrPreNum;
 ArrayAdapter<String>adapter = null;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

 //deleteDatabase();
 createDatabase();
 init();
 event();
 loaddata();
 }
 void loaddata()
 {
 try {
 arrPreNum = new ArrayList<String>();
 sqlite = openOrCreateDatabase("smsgarbage.db", MODE_PRIVATE, null);
 final String []columns ={"id","prefixNum"};
 //Cursor cusor = sqlite.query("tblGarbage", columns , "id,prefixNum", null, null, null, "prefixNum");
 Cursor cusor = sqlite.query("tblGarbage", columns , null, null, null, null, null);
 cusor.moveToFirst();
 String data="";
 while(cusor.isAfterLast()==false)
 {
 data= (String) cusor.getString(0).toString();//+" - " + (String)cusor.getString(1).toString();
 arrPreNum.add(data);
 cusor.moveToNext();
 }
 adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_expandable_list_item_1, arrPreNum);
 lstPreNum.setAdapter(adapter);
 //adapter.notifyDataSetChanged();

 } catch (Exception e)
 {
 // TODO: handle exception
 Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_SHORT).show();
 }

 }
 void cleartext()
 {
 editFrefixNum.setText("");
 }
 void init()
 {
 btnSave = (Button) findViewById(R.id.btnSave);
 editFrefixNum = (EditText) findViewById(R.id.editPrefixPhoneNum);
 lstPreNum = (ListView) findViewById(R.id.lstviewList);
 }
 void event()
 {
 btnSave.setOnClickListener(new OnClickListener() {

 @Override
 public void onClick(View v) {
 // TODO Auto-generated method stub
 insertData(editFrefixNum.getText().toString());
 loaddata();
 }
 });

 lstPreNum.setOnItemClickListener(new OnItemClickListener()
 {

@Override
 public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
 // TODO Auto-generated method stub
 editFrefixNum.setText((String)arrPreNum.get(arg2).toString());
 //idUpdate =(String)arrPreNum.get(arg2).toString();
 }
 });

 lstPreNum.setOnItemLongClickListener(new OnItemLongClickListener()
 {
 @Override
 public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
 // TODO Auto-generated method stub
 AlertDialog.Builder bui = new AlertDialog.Builder(MainActivity.this);
 bui.setTitle("Cảnh báo !");
 //final int index = arg2;
 final String id= (String)arrPreNum.get(arg2).toString().trim();
 bui.setPositiveButton("OK", new AlertDialog.OnClickListener() {

 @Override
 public void onClick(DialogInterface dialog, int which) {
 // TODO Auto-generated method stub
 //arrPreNum.remove(index);
 sqlite = openOrCreateDatabase("smsgarbage.db", MODE_PRIVATE, null);
 if(sqlite.delete("tblGarbage", "id=?", new String []{id}) != -1)
 {
 loaddata();
 cleartext();
 Toast.makeText(MainActivity.this, "Xóa thành công !", Toast.LENGTH_SHORT).show();
 }
 else
 Toast.makeText(MainActivity.this, "Xóa thất bại !", Toast.LENGTH_SHORT).show();
 }
 });
 bui.setNegativeButton("Cancel", new AlertDialog.OnClickListener() {

 @Override
 public void onClick(DialogInterface dialog, int which) {
 // TODO Auto-generated method stub
 dialog.cancel();
 }
 });

 bui.create().show();

 return false;
 }

 });
 }
 void createDatabase()
 {
 String path= Environment.getExternalStorageDirectory().getAbsolutePath()+"/smsgarbage.db";
 sqlite = openOrCreateDatabase(path, MODE_PRIVATE, null);

 try
 {
 String query = "Create table tblGarbage(id text primary key , prefixNum text)";
 sqlite.execSQL(query);
 } catch (Exception e) {
 // TODO: handle exception
 }
 }

 void insertData(String PrefixNum)
 {
 try {
 //sqlite = openOrCreateDatabase("qlsach.db", MODE_PRIVATE, null);
 ContentValues _values = new ContentValues();
 _values.put("id", PrefixNum);
 _values.put("prefixNum", PrefixNum);
 if(sqlite.insert("tblGarbage", null, _values) != -1)
 {
 Toast.makeText(MainActivity.this, "Thêm thành công !", Toast.LENGTH_SHORT).show();
 cleartext();
 }
 else
 Toast.makeText(MainActivity.this, "Thất bại !", Toast.LENGTH_SHORT).show();
 } catch (Exception e) {
 // TODO: handle exception
 Toast.makeText(MainActivity.this, "Thất bại hoàn toàn !", Toast.LENGTH_SHORT).show();
 }

 }

 void update(String idUpdate)
 {
 sqlite = openOrCreateDatabase("smsgarbage.db", MODE_PRIVATE, null);
 ContentValues values = new ContentValues();
 //values.put("id", idUpdate);
 values.put("prefixNum", editFrefixNum.getText().toString());
 if(sqlite.update("tblGarbage", values, "id=?", new String[]{idUpdate}) != -1)
 {
 loaddata();
 Toast.makeText(MainActivity.this, "Cập nhật thành công !", Toast.LENGTH_SHORT).show();
 }
 else
 Toast.makeText(MainActivity.this, "Cập nhật thất bại !", Toast.LENGTH_SHORT).show();
 }
 void deleteDatabase()
 {
 if(deleteDatabase("smsgarbage.db") == true)
 Toast.makeText(MainActivity.this, "Xóa database [smsgarbage] thành công !", Toast.LENGTH_LONG).show();
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
 // Inflate the menu; this adds items to the action bar if it is present.
 getMenuInflater().inflate(R.menu.main, menu);
 return true;
 }

/*************************************************************************************************************************/
 MediaRecorder audioRecorder = null;
 public void doStartRecord()
 {
 try
 {
 if(audioRecorder == null)
 audioRecorder = new MediaRecorder();//step1
 String saveto=Environment.getDataDirectory().getAbsolutePath()+"/myrecord.mp5";
 audioRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//step 2
 audioRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);//step3
 audioRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);//step4
 audioRecorder.setOutputFile(saveto);
 audioRecorder.prepare();//step 6
 audioRecorder.start();//step 7
 } catch (Exception e)
 {
 // TODO: handle exception
 }
 }
 public void doStopRecording()
 {
 if(audioRecorder != null)
 {
 audioRecorder.stop();//step 8
 audioRecorder.release();
 audioRecorder = null;
 }
 }

 void doPlayMusic()
 {
 MediaPlayer player = new MediaPlayer();
 try
 {
 String saveto= Environment.getDataDirectory().getAbsolutePath()+"/myaudio.mp3";
 player.setDataSource(saveto);
 player.prepare();
 player.start();

 /*
 * player.stop();
 * player.release();
 * player = null;
 * */

 } catch (Exception e)
 {
 // TODO: handle exception
 }
 }

 /*************************************************************************************************************************/

}

Broadcast Receiver:


package vn.edu.it.nguyentannhan.id1200911;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.telephony.SmsMessage;
import android.widget.Toast;
import android.database.sqlite.SQLiteDatabase;

&nbsp;

&nbsp;

public class MySmsReceive extends BroadcastReceiver {
 public static final String SMS_URI= "content://sms/inbox";
 public static final String BODY= "body";
 public static final String ADDRESS= "address";
 //BroadcastReceiver receive =null;
 void BroadCastReceive()
 {
 //IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
 /*receive = new BroadcastReceiver()
 {

@Override
 public void onReceive(Context context, Intent intent) {
 // TODO Auto-generated method stub

 }

 };*/
 //receive = new BroadcastReceiver();
 }
 @Override
 public void onReceive(Context context, Intent intent)
 {
 // TODO Auto-generated method stub
 processReceive(context, intent);

}
 void processReceive(Context context, Intent intent)
 {
 Bundle extras = intent.getExtras();
 String message ="";
 if(extras != null)
 {
 Object []smsExtra = (Object[])extras.get("pdus");
 for (int i = 0; i < smsExtra.length; i++)
 {
 SmsMessage sms = SmsMessage.createFromPdu((byte[])smsExtra[i]);
 String body = sms.getMessageBody();
 String address = sms.getOriginatingAddress();
 message +="SMS From: "+ address +" :\n"+body+"\n";
 XoaToanBoSms(context, address);
 }
 Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
 }
 }

public boolean checkDumpNumber(String f)
 {
 SQLiteDatabase sqlite;
 String path= Environment.getExternalStorageDirectory().getAbsolutePath()+"/smsgarbage.db";
 sqlite= SQLiteDatabase.openOrCreateDatabase(path, null);
 Cursor c = sqlite.query("tblGarbage", null, "prefixNum=?", new String[]{f}, null, null, null, null);
 c.moveToFirst();
 return c.isAfterLast();
 }
 void XoaToanBoSms(Context con, String phoneNumber)
 {
 try {
 /*for (int i = 0; i < msgs.length; i++)
 {
 if(msgs.getOriginatingAddress().equals(phoneNumber)==false)
 {
 continue;
 }*/
 if(checkDumpNumber(phoneNumber))
 {
 con.getContentResolver().delete(Uri.parse("content://sms"), "address=?", new String[]{phoneNumber});
 Toast.makeText(con, "Xóa rồi đó " + phoneNumber, Toast.LENGTH_SHORT).show();
 }
 else
 {
 Toast.makeText(con, "Khong tìm thấy !" + phoneNumber, Toast.LENGTH_SHORT).show();
 }
 //}
 } catch (Exception e) {
 // TODO: handle exception
 Toast.makeText(con, "Xóa rồi đó " + e, Toast.LENGTH_SHORT).show();
 }
 }

 void XoaSmsMoiNhat(Context con, SmsMessage[]msgs, String phoneNumber)
 {
 try {
 for (int i = 0; i < msgs.length; i++) {
 if(msgs[i].getOriginatingAddress().equals(phoneNumber)==false)
 {
 continue;
 }
 con.getContentResolver().delete(Uri.parse("content://sms"), "address=? and date=?",
 new String []{phoneNumber,String.valueOf(msgs[i].getTimestampMillis())});
 Toast.makeText(con, "Xóa rồi đó "+msgs[i].getOriginatingAddress(), Toast.LENGTH_SHORT).show();
 }
 } catch (Exception e) {
 // TODO: handle exception
 Toast.makeText(con, "Xóa rồi đó "+e, Toast.LENGTH_SHORT).show();
 }
 }

}

Chương trình này sẽ chạy giống như Services nếu như nó bị tắt.

Khi lưu dữ liệu thì nó sẽ được lưu vào SDCARD, bất cứ khi nào có tin nhắn gửi tới thì Broadcast Receiver sẽ bắt lệnh và tiến hành xử lý.

Bạn có thể tải source code đầy đủ ở đây: https://www.mediafire.com/download/ulycc5263nvle1d/Broadcast_recieve_message_garbage.rar

Chúc bạn thành công.

15 responses

  1. Thầy ơi sắp đến bài về Service chưa ạ. Em học trên lớp không được học về lý thuyết, thầy giáo toàn cho làm bài tập thôi, chẳng biết làm thế nào. Lại sắp có bài tập lớn nữa chứ :(((

  2. em mong thầy hướng dẫn thêm về Fragment, Service, Json và API nữa ạ, cảm ơn thầy rất nhiều

    1. Tự học đi bạn đến lúc thầy giảng mình sẽ nhớ lâu hơn . ngộ ra được những thứ mình chưa hiểu .

  3. Cám ơn thầy, dù không phải là sinh viên trường nhưng em theo dõi đầy đủ các bài viết, của thầy. Thật sự rất hửu ích. Em mong chờ bài viết về Service của thầy lắm ạ. Em cám ơn vì sự nhiệt tình của thầy

  4. Thầy xem giúp lại em bài trên web với , em không nghĩ với cái Broadcast bị comment kia nó có thể chạy được đâu ạ

  5. […] Phần Bằng SMS cho các Trường Đại Học) Tui đã cung cấp hàng loạt các bài 40, 41, 44, 45, 46, 47 các bạn cần đọc kỹ lại những bài tập này trước khi bắt tay […]

  6. e chào thầy. thầy cho em hỏi vấn đề này tí ạ. e làm 1 ứng dụng có kèm theo database , e đã copy nó vào muc assets nhưng khi cài đặt thì nó không có trong thiết bị. mong thầy giúp đỡ. e xin chân thành cảm ơn.

    1. Trương Khoan | Reply

      bạn tham khảo trang này nhé. Mong là không quá muộn.

      http://www.tutsmodel.info/2015/05/copy-file-database-tu-thu-muc-asset.html

  7. Code không chạy thầy ơi! 😦

  8. cái trên o chạy vì sms nó thua quyền các phần mềm khác , VD như sms 360 , muốn pass qua được sms 360 thì phải viết cách khác

  9. […] Phần Bằng SMS cho các Trường Đại Học) Tui đã cung cấp hàng loạt các bài 40, 41, 44, 45, 46, 47 các bạn cần đọc kỹ lại những bài tập này trước khi bắt […]

  10. Cái này muốn chạy được thì phải viết phần Broadcast Receiver ở trong MainAcitivity

  11. Code trên của bạn chỉ có thể xóa được những tin nhắn cũ của phone rác còn tin mới nhất vẫn chưa xóa được.Mình vẫn chưa xử lý được cái này bạn nào biết thì share nhé

  12. Code này chỉ chạy được phiên bản thấp hơn android 4.4, phiên bản lớn hơn là ko xóa được 😦
    Debug không lỗi nhưng nó chạy qua dòng delete luôn nhưng không thực thi được

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s