最近有需求做个一手机开机后,监听手机短信(指定短信内容)通知客户。下面将实现代码写出来
短信通知广播拦截BootReceiver
package com.msi.manning; import java.util.ArrayList; import android.app.NotificationManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.telephony.gsm.SmsMessage; import android.util.Log; /** * 2011-4-18 下午01:43:17 BootReceiver.java author:zhouhui * E-mail:[email protected] */ public class BootReceiver extends BroadcastReceiver { static final String ACTION = "android.provider.Telephony.SMS_RECEIVED"; private static final String LOG_TAG = "SMSReceiver"; public static final int NOTIFICATION_ID_RECEIVED = 0x1221; @Override public void onReceive(Context context, Intent intent) { NotificationManager nm = (NotificationManager) context .getSystemService(Context.NOTIFICATION_SERVICE); ArrayList<String> list = new ArrayList<String>(); if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { // Intent in = new Intent(context, SMSNotifyActivity.class); // // 这是你的activity // in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // context.startActivity(in); } if (intent.getAction().equals(BootReceiver.ACTION)) { Bundle bundle = intent.getExtras(); StringBuilder sb = new StringBuilder(); if (bundle != null) { Object messages[] = (Object[]) bundle.get("pdus"); SmsMessage[] smsMessage = new SmsMessage[messages.length]; for (int n = 0; n < messages.length; n++) { smsMessage[n] = SmsMessage .createFromPdu((byte[]) messages[n]); sb.append("From:"); sb.append(smsMessage[n].getDisplayOriginatingAddress()); sb.append("\n"); sb.append(smsMessage[n].getDisplayMessageBody()); list.add(sb.toString()); } } Log.i(BootReceiver.LOG_TAG, "[SMSApp] onReceiveIntent0: " + sb); abortBroadcast(); Intent in = new Intent(context, SMSNotifyActivity.class); Bundle bundle2 = new Bundle(); bundle2.putStringArrayList("message", list); in.putExtras(bundle2); in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(in); Log.i(BootReceiver.LOG_TAG, "[SMSApp] onReceiveIntent0over: " ); } } }
手机发送短信广播后会给android.provider.Telephony.SMS_RECEIVED 拦截 取得短信内容后面通知需要显示拦截展现的Activity
显示短信拦截内容的SMSNotifyActivity
package com.msi.manning;
import java.util.ArrayList; import java.util.HashMap; import android.app.Activity; import android.database.Cursor; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ListView; public class SMSNotifyActivity extends Activity { private static final String LOG_TAG = "SMSReceiver"; Button closeBtn; Button clearBtn; Button deleteBtn; ListView list; ListViewButtonAdapter listItemAdapter; private DiaryDbAdapter mDbHelper; private Cursor mDiaryCursor; public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); initLayout(); } /** * 查詢最新全部短信通知數據 */ private void renderListView() { mDiaryCursor = mDbHelper.getAllMessage(); ArrayList<HashMap<String, Object>> listItem = new ArrayList<HashMap<String, Object>>(); mDiaryCursor.moveToFirst(); while (!mDiaryCursor.isAfterLast()) { HashMap<String, Object> map = new HashMap<String, Object>(); String status = mDiaryCursor.getString(5); if (status.equals("0")) { status = "未查看"; } else { status = "已查看"; } map.put("ItemTitle", mDiaryCursor.getLong(0)); map.put("ItemType", mDiaryCursor.getString(3)); map.put("ItemTime", mDiaryCursor.getString(4)); map.put("ItemStatus", status); map.put("ItemText", mDiaryCursor.getString(1)); listItem.add(map); mDiaryCursor.moveToNext(); } mDiaryCursor.close(); // 生成适配器的Item和动态数组对应的元素 listItemAdapter = new ListViewButtonAdapter(this, listItem,// 数据源 R.layout.list,// ListItem的XML实现 // 动态数组与ImageItem对应的子项 new String[] { "ItemTitle", "ItemType", "ItemTime", "ItemStatus", "ItemText", "ItemTitle", "ItemTitle" }, // ImageItem的XML文件里面的一个ImageView,两个TextView ID new int[] { R.id.ItemTitle, R.id.ItemType, R.id.ItemTime, R.id.ItemStatus, R.id.ItemText, R.id.btn_config_delete, R.id.btn_config_view }, mDbHelper); // 添加并且显示 list.setAdapter(listItemAdapter); } /** * 初始化組件 */ private void initLayout() { // 绑定Layout里面的ListView list = (ListView) findViewById(R.id.MyListView); this.closeBtn = (Button) findViewById(R.id.btn_config_close); this.clearBtn = (Button) findViewById(R.id.btn_config_clear); closeBtn.setOnClickListener(new closeBtn_Click()); clearBtn.setOnClickListener(new clearBtn_Click()); } @Override protected void onStart() { super.onStart(); mDbHelper = new DiaryDbAdapter(this); mDbHelper.open(); Bundle extras = getIntent().getExtras(); ArrayList<String> data = null; if (extras != null) { data = extras.getStringArrayList("message"); for (int j = 0; j < data.size(); j++) { String[] array = data.get(j).split("\n"); String[] message = array[1].split("#"); mDbHelper.createDiary(message[4], message[1], message[2], "0", message[3]); } } Log.i(SMSNotifyActivity.LOG_TAG, "[SMSApp] onReceiveIntent1: " + data); renderListView(); } /** * 關閉短信通知 * * @author dell * */ public class closeBtn_Click implements OnClickListener { public void onClick(View arg0) { SMSNotifyActivity.this.finish(); } } /** * 清除所有短信通知 * * @author dell * */ public class clearBtn_Click implements OnClickListener { public void onClick(View arg0) { boolean flag = mDbHelper.deleteAll(); Log.i(SMSNotifyActivity.LOG_TAG, "[SMSApp] clearBtn_Click: " + flag); listItemAdapter.notifyDataSetChanged(); // 刷新頁面 renderListView(); } } protected void onRestart() { super.onRestart(); Log.e(LOG_TAG, "start onRestart~~~"); } @Override protected void onResume() { super.onResume(); Log.e(LOG_TAG, "start onResume~~~"); } @Override protected void onPause() { super.onPause(); Log.e(LOG_TAG, "start onPause~~~"); } @Override protected void onStop() { super.onStop(); Log.e(LOG_TAG, "start onStop~~~"); } @Override protected void onDestroy() { super.onDestroy(); Log.e(LOG_TAG, "start onDestroy~~~"); } }
短信拦截后的记录插入到数据库中,这里有个SQLlite辅助类DiaryDbAdapter
package com.msi.manning;
import java.util.Calendar; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; public class DiaryDbAdapter { private static final String PUSH_ID = "push_id"; //邮件等类型的主键 private static final String CONTENT = "content"; //邮件等类型的简略内容 private static final String SMS_FUNC_CODE = "sms_func_code"; //通知类型代码 private static final String SMS_FUNC_CODE_CN = "sms_func_code_cn"; //通知类型中文名 private static final String CREATE_TIME = "create_time"; //该记录创建的时间 private static final String STATUS = "status"; //通知状态 private static final String REQID = "reqid"; //通知状态 private static final String DATABASE_NAME = "dbForMessage"; private static final String DATABASE_TABLE = "iuc_push_record"; private static final int DATABASE_VERSION = 1; private static final String TAG = "DiaryDbAdapter"; private DatabaseHelper mDbHelper; private SQLiteDatabase mDb; private static final String DATABASE_CREATE = "CREATE TABLE " + DATABASE_TABLE + " (" + PUSH_ID + " INTEGER PRIMARY KEY autoincrement, " + CONTENT + " text not null, " +SMS_FUNC_CODE + " text," + SMS_FUNC_CODE_CN + " text," +CREATE_TIME + " text," +STATUS + " text, "+REQID + " text "+ ");"; // private static final String DATABASE_CREATE = "create table diary (_id integer primary key autoincrement, " // + "title text not null, body text not null, created text not null);"; private final Context mCtx; private static class DatabaseHelper extends SQLiteOpenHelper { DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { Log.i(TAG, "[SMSApp] createDatabase: " +DATABASE_CREATE); db.execSQL(DATABASE_CREATE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.i(TAG, "[SMSApp] updatgeDatabase: " +DATABASE_CREATE); db.execSQL("DROP TABLE IF EXISTS"+DATABASE_TABLE); onCreate(db); } } public DiaryDbAdapter(Context ctx) { this.mCtx = ctx; } public DiaryDbAdapter open() throws SQLException { mDbHelper = new DatabaseHelper(mCtx); mDb = mDbHelper.getWritableDatabase(); return this; } public void closeclose() { mDbHelper.close(); } public long createDiary(String content, String sms_func_code,String sms_func_code_cn,String status,String reqid) { ContentValues initialValues = new ContentValues(); initialValues.put(CONTENT, content); initialValues.put(SMS_FUNC_CODE, sms_func_code); initialValues.put(SMS_FUNC_CODE_CN, sms_func_code_cn); initialValues.put(STATUS, status); initialValues.put(REQID, reqid); Calendar calendar = Calendar.getInstance(); String created = calendar.get(Calendar.YEAR) + "年" + calendar.get(Calendar.MONTH) + "月" + calendar.get(Calendar.DAY_OF_MONTH) + "日" + calendar.get(Calendar.HOUR_OF_DAY) + "时" + calendar.get(Calendar.MINUTE) + "分"; initialValues.put(CREATE_TIME, created); Log.i(TAG, "[SMSApp] insertsql: "); return mDb.insert(DATABASE_TABLE, null, initialValues); } public boolean deleteDiary(long rowId) { Log.i(TAG, "[SMSApp] deletesql: "+rowId); return mDb.delete(DATABASE_TABLE, PUSH_ID + "=" + rowId, null) > 0; } public boolean deleteAll() { Log.i(TAG, "[SMSApp] deleteallsql: "); return mDb.delete(DATABASE_TABLE, null, null) > 0; } public Cursor getAllMessage() { Log.i(TAG, "[SMSApp] getallsql: "); return mDb.query(DATABASE_TABLE, new String[] { PUSH_ID, CONTENT, SMS_FUNC_CODE, SMS_FUNC_CODE_CN,CREATE_TIME,STATUS,REQID }, null, null, null, null, null); } public Cursor getDiary(long rowId) throws SQLException { Cursor mCursor = mDb.query(true, DATABASE_TABLE, new String[] { PUSH_ID, CONTENT, SMS_FUNC_CODE, SMS_FUNC_CODE_CN,CREATE_TIME,STATUS,REQID }, PUSH_ID + "=" + rowId, null, null, null, null, null); Log.i(TAG, "[SMSApp] getDiarysql: "); if (mCursor != null) { mCursor.moveToFirst(); } return mCursor; } public boolean updateDiary(long rowId, String content, String sms_func_code,String sms_func_code_cn,String status,String reqid) { ContentValues args = new ContentValues(); args.put(CONTENT, content); args.put(SMS_FUNC_CODE, sms_func_code); args.put(SMS_FUNC_CODE_CN, sms_func_code_cn); args.put(STATUS, status); args.put(REQID, reqid); Calendar calendar = Calendar.getInstance(); String created = calendar.get(Calendar.YEAR) + "年" + calendar.get(Calendar.MONTH) + "月" + calendar.get(Calendar.DAY_OF_MONTH) + "日" + calendar.get(Calendar.HOUR_OF_DAY) + "时" + calendar.get(Calendar.MINUTE) + "分"; args.put(CREATE_TIME, created); Log.i(TAG, "[SMSApp] updatesql: "); return mDb.update(DATABASE_TABLE, args, PUSH_ID + "=" + rowId, null) > 0; } }
由于SMSNotifyActivity 方法中listview中有按钮提交事件普通的listview不能响应事件,ListViewButtonAdapter
扩展BaseAdapter 方法重写getView 方法,添加BUTTON 并添加按钮响应事件
package com.msi.manning;
import java.util.ArrayList; import java.util.HashMap; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.TextView; /** * 2011-4-20 上午10:56:21 lvButtonAdapter.java author:zhouhui * E-mail:[email protected] */ public class ListViewButtonAdapter extends BaseAdapter { private DiaryDbAdapter mDbHelper; private static final String TAG = "lvButtonAdapter"; public static final String ACTION_INTENT_TASKRECEIVER= "com.gift.android.TaskReceiver"; private class buttonViewHolder { // ImageView appIcon; TextView appName1; TextView appName2; TextView appName3; TextView appName4; TextView appName5; Button buttonClose; Button buttonView; } private ArrayList<HashMap<String, Object>> mAppList; private LayoutInflater mInflater; private Context mContext; private String[] keyString; private int[] valueViewID; private buttonViewHolder holder; public ListViewButtonAdapter(Context c, ArrayList<HashMap<String, Object>> appList, int resource, String[] from, int[] to, DiaryDbAdapter mDbHelper) { mAppList = appList; mContext = c; mInflater = (LayoutInflater) mContext .getSystemService(Context.LAYOUT_INFLATER_SERVICE); keyString = new String[from.length]; valueViewID = new int[to.length]; System.arraycopy(from, 0, keyString, 0, from.length); System.arraycopy(to, 0, valueViewID, 0, to.length); this.mDbHelper = mDbHelper; } @Override public int getCount() { return mAppList.size(); } @Override public Object getItem(int position) { return mAppList.get(position); } @Override public long getItemId(int position) { return position; } public void removeItem(int position) { mAppList.remove(position); this.notifyDataSetChanged(); } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView != null) { holder = (buttonViewHolder) convertView.getTag(); } else { convertView = mInflater.inflate(R.layout.list, null); holder = new buttonViewHolder(); holder.appName1 = (TextView) convertView .findViewById(valueViewID[0]); holder.appName2 = (TextView) convertView .findViewById(valueViewID[1]); holder.appName3 = (TextView) convertView .findViewById(valueViewID[2]); holder.appName4 = (TextView) convertView .findViewById(valueViewID[3]); holder.appName5 = (TextView) convertView .findViewById(valueViewID[4]); holder.buttonClose = (Button) convertView .findViewById(valueViewID[5]); holder.buttonView = (Button) convertView .findViewById(valueViewID[6]); convertView.setTag(holder); } HashMap<String, Object> appInfo = mAppList.get(position); if (appInfo != null) { Long aname1 = (Long) appInfo.get(keyString[0]); String aname2 = (String) appInfo.get(keyString[1]); String aname3 = (String) appInfo.get(keyString[2]); String aname4 = (String) appInfo.get(keyString[3]); String aname5 = (String) appInfo.get(keyString[4]); holder.appName1.setText(String.valueOf(aname1)); holder.appName2.setText(aname2); holder.appName3.setText(aname3); holder.appName4.setText(aname4); holder.appName5.setText(aname5); holder.buttonClose .setOnClickListener(new lvButtonListener(position)); holder.buttonView .setOnClickListener(new lvButtonListener(position)); } return convertView; } class lvButtonListener implements OnClickListener { private int position; lvButtonListener(int pos) { position = pos; } @Override public void onClick(View v) { int vid = v.getId(); if (vid == holder.buttonClose.getId()) { boolean flag = mDbHelper.deleteDiary(Long .parseLong((holder.appName1.getText().toString()))); Log.i(TAG, "[SMSApp] deletesql: " + flag); removeItem(position); } if (vid == holder.buttonView.getId()) { // 查看短信详细 ShowView(Long.parseLong((holder.appName1.getText().toString()))); } } private void ShowView(long id) { Cursor mDiaryCursor = mDbHelper.getDiary(id); if (mDiaryCursor != null) { boolean flag = mDbHelper.updateDiary(id, mDiaryCursor.getString(1), mDiaryCursor.getString(2), mDiaryCursor.getString(3), "1",mDiaryCursor.getString(6)); Log.i(TAG, "[SMSApp] updatesql: " + flag); // 广播消息 Intent intent = new Intent(ACTION_INTENT_TASKRECEIVER); intent.putExtra("TaskContent", mDiaryCursor.getString(2)+"#"+mDiaryCursor.getString(6)); mContext.sendBroadcast(intent); } } } }
layout 文件的布局管理文件
main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/RelativeLayout01" android:layout_width="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="wrap_content" android:paddingBottom="4dip" android:paddingLeft="12dip" android:paddingRight="12dip" android:descendantFocusability="blocksDescendants" > <ListView android:layout_width="wrap_content" android:layout_height="400dip" android:id="@+id/MyListView"> </ListView> <LinearLayout android:id="@+id/bottom_panel" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_horizontal" android:layout_alignParentBottom="true" > <Button android:id="@+id/btn_config_clear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:width="100dip" android:text="清空" /> <Button android:id="@+id/btn_config_close" android:layout_width="wrap_content" android:layout_height="wrap_content" android:width="100dip" android:text="退出" /> </LinearLayout> </RelativeLayout>
list.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- 此布局文件用来定义listview 的显示方式 --> <RelativeLayout android:id="@+id/RelativeLayout01" android:layout_width="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="wrap_content" android:paddingBottom="4dip" android:paddingLeft="12dip" android:paddingRight="12dip" android:descendantFocusability="blocksDescendants" > <TextView android:layout_height="wrap_content" android:textSize="20dip" android:layout_width="fill_parent" android:id="@+id/ItemTitle" /> <TextView android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_below="@+id/ItemTitle" android:id="@+id/ItemType" /> <TextView android:layout_height="wrap_content" android:layout_below="@+id/ItemType" android:layout_width="fill_parent" android:id="@+id/ItemTime" /> <TextView android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_below="@+id/ItemTime" android:id="@+id/ItemStatus" /> <TextView android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_below="@+id/ItemStatus" android:id="@+id/ItemText" /> <Button android:id="@+id/btn_config_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/ItemText" android:layout_alignParentRight="true" android:focusable="false" android:width="50dip" android:text="查看" /> <Button android:id="@+id/btn_config_delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toLeftOf="@+id/btn_config_view" android:layout_alignTop="@+id/btn_config_view" android:focusable="false" android:width="50dip" android:text="删除" /> </RelativeLayout>
AndroidManifest.xml
中 添加手机自启动注册信息android.permission.RECEIVE_BOOT_COMPLETED
添加广播监听
<receiver android:name=".BootReceiver">
<intent-filter android:priority="100">
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</receiver>
这里添加短信监听广播接收android.provider.Telephony.SMS_RECEIVED
完整的AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.msi.manning"> <application android:icon="@drawable/chat"> <activity android:name="com.msi.manning.SMSNotifyActivity" android:label="@string/app_name" android:clearTaskOnLaunch="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name=".BootReceiver"> <intent-filter android:priority="100"> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.provider.Telephony.SMS_RECEIVED" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </receiver> </application> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission> <!-- 程序接收短信权限 --> <uses-permission android:name="android.permission.READ_SMS"></uses-permission> <!-- 读短信权限 --> </manifest>