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

[polldaddy poll=9764234]

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

[code language=”xml”]
<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>

[/code]

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

[code]

<?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>

[/code]

Xử lý coding:

MainActivity:

[code language=”java”]

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
}
}

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

}

[/code]

Broadcast Receiver:

[code language=”java”]

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();
}
}

}

[/code]

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 thoughts on “Bài 41: Phần mềm xử lý tin nhắn rắc”

  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. 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

  3. 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 ạ

  4. 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.

  5. 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é

  6. 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