Bài 47: Xử lý tin nhắn SMS bằng BroadCastReceiver

[polldaddy poll=9764234]

Để hỗ trợ cho dự án nêu trong bài tập số 43(Đăng Ký Học 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 vào làm bài tập 43.

Ở bài tập 47 này, Tui muốn hướng dẫn các bạn cách sử dụng BroadCastReceiver được đăng ký chạy background trong Android Manifest, để nó có thể tự động “bắt” được tin nhắn SMS bất kỳ nào nhắn tới cho dù chúng ta không mở ứng dụng.

Tui muốn ghi chú các bạn là:

1) Để nhận biết được đâu là Tin Nhắn đăng ký học phần thì bắt buộc các bạn phải có một CÚ PHÁP gửi tin nhắn riêng, giống như hàng ngày trên TIVI đều có hướng dẫn cú pháp đăng ký hay bỏ phiếu cho ai đó. Tương tự như vậy để nhận biết được tin nhắn đăng ký học phần thì hệ thống Website trường đại học cũng phải cung cấp CÚ PHÁP đăng ký 1 học phần như thế nào đúng không?

3) Khi 1 tin nhắn gửi tới mà ta phân tích được nó chính là tin nhắn CÚ PHÁP đăng ký học phần thì mới tiến hành xử lý đăng ký, việc xử lý đăng ký là vô cùng phức tạp vì đòi hỏi bạn phải hiểu biết cặn kẽ về quy trình xử lý học vụ, đối với trường hợp ở bài tập 43 thì bạn có thể làm ví dụ sơ sơ cũng được, nhưng theo TUI muốn làm thực tế và bán được lại cho các trường đại học muốn áp dụng công nghệ thì bạn phải đến trực tiếp trường học, liên hệ (tốt nhất là có mối quan hệ sâu sắc) để hiểu được quy trình xử lý học vụ, như vậy may ra dự án của bạn mới áp dựng thực tế còn không chỉ là làm sương sương chơi cho vui.

4) Với bài tập 47 này thì Tui chỉ làm 1 phần nhỏ: Nhận 1 tin nhắn theo cú pháp, trả lời tin nhắn có sự kiểm tra là tin nhắn đã được gửi thành công hay thất bại (dùng PendingIntent).

Công việc còn lại của bạn là sau khi nhận được tin nhắn theo cú pháp rồi, tiến hành phân tích  đưa thông tin lên  Server thông qua Webservice, kiểm tra kết quả trả về của Webservice, rồi trả lời SMS ngược lại cho người đăng ký–>có thể tự làm bài 43.

Tui có thể phác thảo mô hình phù hợp để các bạn test hệ thống này dễ dàng như sau:

3h47_0

– Dựa vào mô hình trên thì bạn có thể kiểm tra hệ thống như sau:

+ Bạn có thể biến máy tính cá nhân của bạn làm máy SERVER, CSDL + webservice được cài đặt tại máy Server này.

+ Bạn sử dụng 2 điện thoại: 1 điện thoại cài đặt phần mềm xử lý tin nhắn (gọi là Điện thoại chủ), 1 điện thoại bạn mượn đại của đứa bạn thân nhắn tin theo cú pháp vào điện thoại chủ đó. Điện thoại chủ có nhiệm vụ bắt tin nhắn và xử lý rồi gửi lên PC Server (hoặc dùng máy ảo nếu như bạn không có máy thật để test, nhưng cố gắng dùng máy thật).

– Trước khi vào ứng dụng thì tui nói CÚ PHÁP tin nhắn Tui dùng trong bài tập này để đăng ký học phần như sau:

Cú pháp:  DRTHANH MSSV MMH HK

Giải thích cú pháp:

DRTHANH là keyword đầu tiên của tin nhắn

MSSV là mã số sinh viên

MMH là mã môn học

HK là học kỳ

VÍ DỤ, nếu sinh viên gửi tin nhắn “DRTHANH 113114115 ANDROID 9”
Thì mã sinh viên =113114115
Mã môn học: ANDROID
Học kỳ 9

– Khi tin nhắn gửi tới thì ta phải phân tích nội dung tin nhắn để tiến hành xử lý cho phù hợp.

– Bạn tạo Project đơn giản như hình Tui chụp dưới đây:

3h47_1

– Bạn chú ý là thư viện KSOAP để tương tác với Webservice là bạn tự làm, Tui chủ ý không làm phần này để bạn tự tổng hợp kiến thức đưa vào đây như vậy thì mới nâng cao được kỹ năng lập trình cũng như tư duy logic cho bạn.

– Tui chỉ tiến hành làm phần BroadCastReceiver, dĩ nhiên trong này Tui có để sẵn 1 hàm Trống để bạn điền coding cập nhật vào cho dễ dàng hơn.

– Chương trình này không liên quan gì tới giao diện, vì Tui đăng ký BroadCastReceiver trong Manifest để hệ thống tự động nhận, xử lý và gửi tin nhắn (cho dù không mở ứng dụng), Nên giao diện bạn thích làm kiểu gì cũng được (tốt nhất là đừng quan tâm).

– Tui nói phần Manifest, bạn cấu hình như dưới đây:

[code language=”xml”]

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="tranduythanh.com"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="tranduythanh.com.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="MyBroadCast" >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>

</manifest>

[/code]

– Dòng lệnh 9 ->12 là đăng ký permission cho việc Nhận tin nhắn, gửi tin nhắn, ghi tin nhắn, đọc tin nhắn.

– Dòng lệnh 29- 33 là đăng ký BroadCastReceiver trong Manifest, giúp chương trình hoạt động như service chạy nền.

– Xử lý coding MyBroadCast:

[code language=”java”]

package tranduythanh.com;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.widget.Toast;

public class MyBroadCast extends BroadcastReceiver {

// All available column names in SMS table
// [_id, thread_id, address,
// person, date, protocol, read,
// status, type, reply_path_present,
// subject, body, service_center,
// locked, error_code, seen]
public static final String SMS_EXTRA_NAME = "pdus";
public static final String SMS_URI = "content://sms";

public static final String ADDRESS = "address";
public static final String PERSON = "person";
public static final String DATE = "date";
public static final String READ = "read";
public static final String STATUS = "status";
public static final String TYPE = "type";
public static final String BODY = "body";
public static final String SEEN = "seen";

public static final int MESSAGE_TYPE_INBOX = 1;
public static final int MESSAGE_TYPE_SENT = 2;

public static final int MESSAGE_IS_NOT_READ = 0;
public static final int MESSAGE_IS_READ = 1;

public static final int MESSAGE_IS_NOT_SEEN = 0;
public static final int MESSAGE_IS_SEEN = 1;
private Context context=null;
@Override
public void onReceive(Context context, Intent intent) {
this.context=context;
processSMS(intent);
}
public void processSMS(Intent intent)
{
// Get the SMS map from Intent
Bundle extras = intent.getExtras();

String messages = "";

if ( extras != null )
{
// Get received SMS array
Object[] smsExtra = (Object[]) extras.get( SMS_EXTRA_NAME );
for ( int i = 0; i < smsExtra.length; ++i )
{
SmsMessage sms = SmsMessage.createFromPdu((byte[])smsExtra[i]);
String body = sms.getMessageBody().toString();
String address = sms.getOriginatingAddress();

messages += "SMS from " + address + " :\n";
messages += body + "\n";
//gọi hàm xử lý nội dung và gửi kết quả trả về
doSending(address,body);
}
// Display SMS message từ các điện thoại khác gửi tới
Toast.makeText( context, messages, Toast.LENGTH_SHORT ).show();
}
}
public void doSending(String phoneNumber,String body)
{
try
{
//đặng ký Pending Intent để kiểm soát kết quả gửi tin nhắn trả về thành công hay không?
final SmsManager sms = SmsManager.getDefault();
Intent msgSent = new Intent("ACTION_MSG_SENT");
final PendingIntent pendingMsgSent =
PendingIntent.getBroadcast(context, 0, msgSent, 0);
context.getApplicationContext().registerReceiver(new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
int result = getResultCode();
String msg="Gửi tin nhắn trả lời thành công";
if (result != Activity.RESULT_OK) {
msg="Gửi tin nhắn trả lời thất bại";
}
Toast.makeText(context, msg,
Toast.LENGTH_LONG).show();
}
}, new IntentFilter("ACTION_MSG_SENT"));
//nếu đúng là cú pháp đăng ký học phần.
if(isSyntaxForRegisterCourse(body))
{
processRegisterCourse(body);
sms.sendTextMessage(phoneNumber, null, "Hệ thống đã nhận được tin đăng ký học phần của bạn! chờ giây lát!",
pendingMsgSent, null);
}
else
{
//chỉ là tin nhắn thường
//tự động trả lời — coi chừng tốn tiền khi dùng máy thật nhá
sms.sendTextMessage(phoneNumber, null, "DrThanh tự động trả lời bạn! Củm ơn!",
pendingMsgSent, null);
}

}
catch(Exception ex)
{
Toast.makeText(context, ex.getMessage(),Toast.LENGTH_LONG).show();
}
}
//Giả sử cú pháp bạn quy định là:
//DRTHANH MSSV MMH HK
//DRTHANH là keyword đầu tiên của tin nhắn
//MSSV là mã số sinh viên
//MMH là mã môn học
//HK là học kỳ

//VÍ DỤ body= DRTHANH 113114115 ANDROID 9
//Thì mã sinh viên =113114115
//mã môn học: ANDROID
//học kỳ 9
public boolean isSyntaxForRegisterCourse(String body)
{
String arr[]=body.split(" ");
if(arr.length!=4)
return false;
if(!arr[0].equalsIgnoreCase("DRTHANH"))
return false;
return true;
}
/**
* Các bạn xử lý đăng ký học phần tại đây
* Phân tích và gửi dữ liệu lên Server thông qua Webservice
* Vậy trên Server bạn viết 1 Webservice xử lý đăng ký học phần là OKÊ
* @param body
*/
public void processRegisterCourse(String body)
{
//tự viết lệnh chỗ này
//xem lại các bài tập mà Tui hướng dẫn trước đó để làm
//chúc bạn may mắn.
}
}

[/code]

– Bạn kiểm tra dòng lệnh 13, ta tạo 1 lớp tên là MyBroadCast kế thừa từ BroadCastReceiver.

– Dòng lệnh 43, onReceive dùng để tự động bắt tin nhắn khi có bất kỳ tin nhắn nào gửi tới. Tại một thời điểm thì có thể có nhiều tin nhắn gửi tới cùng 1 lúc nên ta dùng vòng lặp để lặp qua toàn bộ tin nhắn và xử lý.

– Dòng lệnh 73 là hàm doSending, ở đây Tui viết hàm này chủ ý xử lý tin nhắn gửi tới có đúng cú pháp đăng ký hay không, tùy loại tin nhắn mà ta xử lý khác nhau.

– Dòng lệnh 140, hàm processRegisterCourse, Tui để trông để bạn tự viết coding vào đây, sử dụng KSOAP API để gửi thông tin lên cho Webservice xử lý học vụ.

– Bây giờ bạn có thể test thử: Cài phần mềm này vào 1 điện thoại, lấy 1 điện thoại khác nhắn tin theo đúng cú pháp vào điện thoại cài phần mềm, thì sẽ có kết quả như mong muốn.

– Tui đã test thử trên các thiết bị điện thoại thật và đã thành công, bạn cũng thử cài đặt vào để Test cho hiệu quả.

– Bạn có thể tải source code mẫu ở đây: http://www.mediafire.com/download/k12pl9ccqu85dgn/LearnBroadCastReceiver_SMS_With_Manifest.rar

– Bài này có rất nhiều ứng dụng thực tế để kiếm tiền, và bạn cũng chú ý là rất nhiều phần mềm trên Google Play tải về có chức năng tự động gửi tin nhắn nên bạn phải cẩn thận kẻo bị trừ hết ráo không còn xu nào, khi cài đặt thì làm ơn đọc kỹ trước khi bấm Next hay OK. Thường thì nếu phần mềm có dùng SMS thì khi cài vào máy thật nó sẽ Cảnh báo, ta phải đọc kỹ, hãy bỏ thói quen tỏ vẻ nguy hiểm là không thèm đọc cứ bấm Next, OK… rất nguy hiểm.

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

7 thoughts on “Bài 47: Xử lý tin nhắn SMS bằng BroadCastReceiver”

  1. Thưa thầy, cho em hỏi làm thế nào để get data object khi click lên từng item của custom listview và sau khi dùng editText để search trong listview với ạ.

  2. thầy ơi? bài này e muốn biến tấu thành như thế này:
    – cú pháp có nhiều cú pháp lưu trong database
    – viết câu truy vấn coi cú pháp đó có tồn tại trong database ko?

  3. public static final String ADDRESS = “address”;
    public static final String PERSON = “person”;
    public static final String DATE = “date”;
    public static final String READ = “read”;
    public static final String STATUS = “status”;
    public static final String TYPE = “type”;
    public static final String BODY = “body”;
    public static final String SEEN = “seen”;
    Thầy có thể cho biết những biến này để làm gì không? Và cơ sở dữ liệu gồm những table nào a?

  4. Thầy ơi cho em hỏi hàm public void processRegisterCourse(String body) em muốn Start 1 activity mới có được không. Em thử mà nó cứ báo lỗi:
    Intent in=new Intent(MyBroadCast.this, Add.class);
    in.putExtra(“body”, body);
    startActivity(in);

  5. Thầy ơi cho em hỏi , em copy source của thầy rồi import vào android studio chạy đc bình thường nhưng sao em lấy diện thoại gửi tin nhắn đến ko nhận đc lại gì hết là sao thầy , xin thầy giải đáp hộ em , em cám ơn thầy!

Leave a Reply