Ở 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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="utf-8"?>
 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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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.

Nguồn: http://duythanhcse.wordpress.com/category/l%E1%BA%ADp-trinh-android/