package lab.sodino.broadcastaction; import lab.sodino.util.DatabaseOpenHelper; import lab.sodino.util.SodinoOut; import android.app.Activity; import android.content.ContentResolver; import android.database.ContentObserver; import android.database.Cursor; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.widget.Button; import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.TextView; /** * 本例子将记录可静态注册的广播被监听到的频度。<br/> * 1.建立一表{ACTION_NAME广播名称,LAST_TIME最近一次发生时间,COUNT总共记录到的次数}<br/> * 2.在ActionReceiver中监听广播,并记录。 <br/> * 3.在DBContentProvider中更新数据库记录<br/> * 4.在BroadcastActionRecordAct.ActionDBObserver中监听数据库的变化, * 并使用Handler机制将最新情况显示在txtInfo上。<br/> * 5.DatabaseOpenHelper将实现基本的数据库操作。 * * @author Sodino */ public class BroadcastActionRecordAct extends Activity implements Button.OnClickListener { private TextView txtInfo; private DatabaseOpenHelper dbHelper; private Button btnRefresh; /** clear功能未完善。 */ private Button btnClear; private Handler handler = new Handler() { public void handleMessage(Message msg) { String info = (String) msg.obj; txtInfo.setText(info); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LayoutParams lpPC = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT); LayoutParams lpCC = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); btnRefresh = new Button(this); btnRefresh.setLayoutParams(lpCC); btnRefresh.setText("Refresh"); btnRefresh.setOnClickListener(this); btnClear = new Button(this); btnClear.setLayoutParams(lpCC); btnClear.setText("ClearTable"); btnClear.setOnClickListener(this); LinearLayout subLayout = new LinearLayout(this); subLayout.setLayoutParams(lpPC); subLayout.setOrientation(LinearLayout.HORIZONTAL); subLayout.addView(btnRefresh); subLayout.addView(btnClear); txtInfo = new TextView(this); txtInfo.setLayoutParams(lpPC); txtInfo.setTextColor(0xff0000ff); txtInfo.setBackgroundColor(0xffffffff); txtInfo.setText("Starting..."); txtInfo.setTextSize(15); ScrollView scrollView = new ScrollView(this); scrollView.setLayoutParams(lpPC); scrollView.addView(txtInfo); LinearLayout mainLayout = new LinearLayout(this); mainLayout.setLayoutParams(lpPC); mainLayout.setOrientation(LinearLayout.VERTICAL); mainLayout.addView(subLayout); mainLayout.addView(scrollView); setContentView(mainLayout); dbHelper = new DatabaseOpenHelper(this); ContentResolver contentResolver = getContentResolver(); contentResolver.registerContentObserver(DBContentProvider.CONTENT_URI, false, new ActionDBObserver(handler)); } public void onClick(View view) { if (view == btnRefresh) { refreshRecord(); } else if (view == btnClear) { clearRecord(); } } public void refreshRecord() { dbHelper.openReadableDatabase(); String info = dbHelper.getAllOrderedList(DatabaseOpenHelper.DESC); dbHelper.close(); if (info != null) { txtInfo.setText(info); } else { txtInfo.setText("<NULL/>"); } dbHelper.close(); } public void clearRecord() { dbHelper.openWritableDatabase(); dbHelper.clearRecord(); dbHelper.close(); } private class ActionDBObserver extends ContentObserver { private Handler handler; public ActionDBObserver(Handler handler) { super(handler); this.handler = handler; } public void onChange(boolean selfChange) { super.onChange(selfChange); String[] projection = { "ACTION_NAME", "LAST_TIME", "COUNT" }; // String selection = "select * from ActionTable"; String sortOrder = "COUNT DESC"; // dbHelper.openReadableDatabase(); // Cursor cursor = dbHelper.query(projection, null, null, // sortOrder); Cursor cursor = managedQuery(DBContentProvider.CONTENT_URI, projection, null, null, sortOrder); String info = ""; String line = ""; int actionIdx = 0; int timeIdx = 1; int countIdx = 2; while (cursor.moveToNext()) { line += cursor.getString(actionIdx) + " "; line += cursor.getString(timeIdx) + " "; line += cursor.getString(countIdx) + "/n"; info += line; line = ""; } Message msg = new Message(); msg.obj = info; handler.sendMessage(msg); cursor.close(); // dbHelper.close(); SodinoOut.out("Database does changed!!!"); } public boolean deliverSelfNotifications() { return super.deliverSelfNotifications(); } } } package lab.sodino.broadcastaction; import lab.sodino.util.DatabaseOpenHelper; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.Intent; public class ActionReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); /** * "android.intent.extra.KEY_EVENT"的用法:<br/> * KeyEvent keyEvent = (KeyEvent) intent.getExtras().get( * "android.intent.extra.KEY_EVENT");<br/> */ // DatabaseOpenHelper dbUtil = new DatabaseOpenHelper(context); // dbUtil.openWritableDatabase(); // dbUtil.upgradeAction(action); // dbUtil.close(); ContentResolver contentResolver = context.getContentResolver(); ContentValues values = new ContentValues(); values.put("ACTION_NAME", action); values.put("LAST_TIME", System.currentTimeMillis()); // 默认赋值为1 values.put("COUNT", 1); String where = DatabaseOpenHelper.COLUMN_ACTION + "='" + action + "'"; contentResolver.update(DBContentProvider.CONTENT_URI, values, where, null); } } package lab.sodino.broadcastaction; import lab.sodino.util.DatabaseOpenHelper; import lab.sodino.util.SodinoOut; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.text.TextUtils; public class DBContentProvider extends ContentProvider { public static final String PROVIDER_NAME = "lab.sodino.db"; public static final Uri CONTENT_URI = Uri.parse("content://" + PROVIDER_NAME + "/broadcastactions"); public static final int DB = 0; /** 代表 PRIMARY KEY */ public static final int DB_KEY = 1; private DatabaseOpenHelper dbHelper; private static final UriMatcher uriMatcher; static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(PROVIDER_NAME, "broadcastactions", DB); uriMatcher.addURI(PROVIDER_NAME, "broadcastactions#", DB_KEY); } public int delete(Uri uri, String selection, String[] selectionArgs) { int row = -1; dbHelper = new DatabaseOpenHelper(getContext()); dbHelper.openWritableDatabase(); switch (uriMatcher.match(uri)) { case DB: row = dbHelper.deleteFromOnlyTable(selection, selectionArgs); break; case DB_KEY: /*** * get(1)将获取DB_KEY数字<br/> * 如content://browser//main//2<br/> * 执行后将获取2.<br/> * 如果get(0)将获取"main"参数. */ String key = uri.getPathSegments().get(1); row = dbHelper.deleteFromOnlyTable(key, selection, selectionArgs); break; } getContext().getContentResolver().notifyChange(uri, null); dbHelper.close(); return row; } @Override public String getType(Uri uri) { switch (uriMatcher.match(uri)) { case DB: return "vnd.sodino.cursor.dir/db"; case DB_KEY: return "vnd.sodino.cursor.dir/db_key"; } return null; } public Uri insert(Uri uri, ContentValues values) { SodinoOut.out("ContentProvider.insert..."); dbHelper.openWritableDatabase(); int row = dbHelper.insertToOnlyTable(values); SodinoOut.out("ContentProvider|insert row = " + row); // if added successfully if (row > 0) { String pathSegment = values.getAsString("ACTION_NAME"); Uri notifyUri = Uri.withAppendedPath(uri, pathSegment); getContext().getContentResolver().notifyChange(notifyUri, null); return notifyUri; } dbHelper.close(); throw new SQLException("Failed to insert row into " + uri); } public boolean onCreate() { dbHelper = new DatabaseOpenHelper(getContext()); SodinoOut.out("ContentProvider dbHelper:" + dbHelper.toString()); return (dbHelper != null ? true : false); } public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { dbHelper.openReadableDatabase(); Cursor cursor = dbHelper.query(projection, selection, selectionArgs, sortOrder); cursor.setNotificationUri(getContext().getContentResolver(), uri); SodinoOut.out("ContentProvider.query() :cursor=" + cursor.toString()); /** * 注释掉close():dbHelper.query()的返回值cursor还将在本方法结束时被推出到其调用者处,<br/> * dbHelper.close()之后, cursor也将随之关闭。如果LogCat出现:<br/> * Cursor Invalid statement in fillWindow(),应该排查不适时的close()情况。 */ // dbHelper.close(); return cursor; } public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int row = -1; dbHelper.openWritableDatabase(); switch (uriMatcher.match(uri)) { case DB: row = dbHelper.updateToOnlyTable(values, selection, selectionArgs); break; case DB_KEY: String sql = DatabaseOpenHelper.COLUMN_ACTION + "=" + uri.getPathSegments().get(1) + (TextUtils.isEmpty(selection) ? " AND (" + selection + ")" : ""); row = dbHelper.updateToOnlyTable(values, sql, selectionArgs); break; } getContext().getContentResolver().notifyChange(uri, null); dbHelper.close(); return row; } } package lab.sodino.util; import java.io.File; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteOpenHelper; import android.text.TextUtils; public class DatabaseOpenHelper extends SQLiteOpenHelper { private SQLiteDatabase sqlDb; public static final String DB_NAME = "BroadcastActionBox.db"; public static final int DB_VERSION = 1; public static final String TABLE_NAME = "ActionTable"; public static final String COLUMN_ACTION = "ACTION_NAME"; public static final String COLUMN_TIME = "LAST_TIME"; public static final String COLUMN_COUNT = "COUNT"; public static final String DESC = "DESC"; public static final String ASC = "ASC"; public DatabaseOpenHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); File dbFile = context.getDatabasePath(DatabaseOpenHelper.DB_NAME); if (dbFile.exists() == false) { SodinoOut.out("DBFile does not exist."); openWritableDatabase(); // initAllDBItem(); close(); SodinoOut.out("InitDB finished!!!"); } else { SodinoOut.out("DBFile does exist."); } } private void initAllDBItem() { insertItem(Intent.ACTION_AIRPLANE_MODE_CHANGED, 0, 0); insertItem(Intent.ACTION_BATTERY_CHANGED, 0, 0); insertItem(Intent.ACTION_BATTERY_LOW, 0, 0); insertItem(Intent.ACTION_BATTERY_OKAY, 0, 0); insertItem(Intent.ACTION_BOOT_COMPLETED, 0, 0); insertItem(Intent.ACTION_CALL, 0, 0); insertItem(Intent.ACTION_CALL_BUTTON, 0, 0); insertItem(Intent.ACTION_CAMERA_BUTTON, 0, 0); insertItem(Intent.ACTION_CLOSE_SYSTEM_DIALOGS, 0, 0); insertItem(Intent.ACTION_CREATE_SHORTCUT, 0, 0); insertItem(Intent.ACTION_DATE_CHANGED, 0, 0); insertItem(Intent.ACTION_DEVICE_STORAGE_LOW, 0, 0); insertItem(Intent.ACTION_DEVICE_STORAGE_OK, 0, 0); insertItem(Intent.ACTION_GTALK_SERVICE_CONNECTED, 0, 0); insertItem(Intent.ACTION_GTALK_SERVICE_DISCONNECTED, 0, 0); insertItem(Intent.ACTION_GET_CONTENT, 0, 0); insertItem(Intent.ACTION_HEADSET_PLUG, 0, 0); insertItem(Intent.ACTION_MANAGE_PACKAGE_STORAGE, 0, 0); insertItem(Intent.ACTION_MEDIA_BAD_REMOVAL, 0, 0); insertItem(Intent.ACTION_MEDIA_BUTTON, 0, 0); insertItem(Intent.ACTION_MEDIA_CHECKING, 0, 0); insertItem(Intent.ACTION_MEDIA_MOUNTED, 0, 0); insertItem(Intent.ACTION_MEDIA_REMOVED, 0, 0); insertItem(Intent.ACTION_MEDIA_SCANNER_FINISHED, 0, 0); insertItem(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, 0, 0); insertItem(Intent.ACTION_MEDIA_SCANNER_STARTED, 0, 0); insertItem(Intent.ACTION_MEDIA_SHARED, 0, 0); insertItem(Intent.ACTION_MEDIA_UNMOUNTABLE, 0, 0); insertItem(Intent.ACTION_MEDIA_UNMOUNTED, 0, 0); insertItem(Intent.ACTION_NEW_OUTGOING_CALL, 0, 0); insertItem(Intent.ACTION_PACKAGE_ADDED, 0, 0); insertItem(Intent.ACTION_PACKAGE_CHANGED, 0, 0); insertItem(Intent.ACTION_PACKAGE_DATA_CLEARED, 0, 0); insertItem(Intent.ACTION_PACKAGE_INSTALL, 0, 0); insertItem(Intent.ACTION_PACKAGE_REMOVED, 0, 0); insertItem(Intent.ACTION_PACKAGE_REPLACED, 0, 0); insertItem(Intent.ACTION_PACKAGE_RESTARTED, 0, 0); insertItem(Intent.ACTION_POWER_CONNECTED, 0, 0); insertItem(Intent.ACTION_POWER_DISCONNECTED, 0, 0); insertItem(Intent.ACTION_POWER_USAGE_SUMMARY, 0, 0); insertItem(Intent.ACTION_REBOOT, 0, 0); insertItem(Intent.ACTION_SHUTDOWN, 0, 0); insertItem(Intent.ACTION_TIME_CHANGED, 0, 0); insertItem(Intent.ACTION_TIMEZONE_CHANGED, 0, 0); insertItem(Intent.ACTION_UID_REMOVED, 0, 0); insertItem(Intent.ACTION_UMS_CONNECTED, 0, 0); insertItem(Intent.ACTION_UMS_DISCONNECTED, 0, 0); insertItem(Intent.ACTION_USER_PRESENT, 0, 0); insertItem(Intent.ACTION_VOICE_COMMAND, 0, 0); insertItem(Intent.ACTION_WALLPAPER_CHANGED, 0, 0); insertItem("android.provider.Telephony.SIM_FULL", 0, 0); insertItem("android.provider.Telephony.SMS_REJECTED", 0, 0); insertItem("android.provider.Telephony.SMS_RECEIVED", 0, 0); insertItem("android.provider.Telephony.WAP_PUSH_RECEIVED", 0, 0); insertItem("android.intent.action.SIG_STR", 0, 0); } /** * 是你在调用getWritableDatabase()或者getReadableDatabase()时,<br/> * 如果没有创建数据库,则会调用这个方法, 在这个方法里一般写你创建表的语句等等。 */ public void onCreate(SQLiteDatabase db) { SodinoOut.out("DatabaseOpenHelper onCreate() Run"); String sql = "create table if not exists " + TABLE_NAME // <br/> + " (" + COLUMN_ACTION + " TEXT PRIMARY KEY,"// <br/> + COLUMN_TIME + " LONG,"// <br/> + COLUMN_COUNT + " INTEGER"// <br/> + ");"; db.execSQL(sql); } /** * 在第一次创建数据库时,会设定一个Database Version,<br/> * 当你应用程序发布到market后需要更新时,如果你需要修改数据库时,你再设定一个不同的DatabaseVersion,<br/> * 这样系统会调用onUpgrade()方法,你可以在这个方法里写你对数据库的修改的方法。如增加、删除表、在某个表里增加一个字段,等等。 */ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { String sql = "drop table if exists" + TABLE_NAME; sqlDb.execSQL(sql); } public void openWritableDatabase() { this.close(); sqlDb = this.getWritableDatabase(); } public void openReadableDatabase() { this.close(); sqlDb = this.getReadableDatabase(); } public long insertItem(String action, long time, int count) { long row = 0; ContentValues values = new ContentValues(); values.put(COLUMN_ACTION, action); values.put(COLUMN_TIME, time); values.put(COLUMN_COUNT, count); row = insertItem(values); return row; } public long insertItem(ContentValues values) { long row = sqlDb.insert(TABLE_NAME, "NULL", values); SodinoOut.out(values.getAsString(COLUMN_ACTION) + " id=" + String.valueOf(row)); return row; } /** * 以action为关键字,查询column列的数据。 * * @return 无相关记录则返回null. */ public String queryItem(String action, String column) { String result = null; // 方法一: // select column form table where ACTION_NAME='action' // String sql = "select " + column + " from " + TABLE_NAME // + " where ACTION_NAME='" + action + "'"; // Cursor cursor = sqlDb.rawQuery(sql, null); // 方法二: String sql = "select " + column + " from " + TABLE_NAME + " where ACTION_NAME=?"; String[] args = { action }; Cursor cursor = sqlDb.rawQuery(sql, args); if (cursor.getCount() == 0) { return result; } while (cursor.moveToNext()) { result = cursor.getString(cursor.getColumnIndex(column)); } cursor.close(); return result; } public int upgradeItem(String action, int count) { int row = 0; // 方法一:代码更新 // ContentValues cv = new ContentValues(); // cv.put(COLUMN_ACTION, action); // cv.put(COLUMN_TIME, System.currentTimeMillis()); // cv.put(COLUMN_COUNT, count); // row = sqlDb.update(TABLE_NAME, cv, COLUMN_ACTION + "='" + action + // "'", // null); // 方法二:代码更新 ContentValues cv = new ContentValues(); cv.put(COLUMN_ACTION, action); cv.put(COLUMN_TIME, System.currentTimeMillis()); cv.put(COLUMN_COUNT, count); String[] args = { action }; row = sqlDb.update(TABLE_NAME, cv, COLUMN_ACTION + "=?", args); /** * 方法三:sql语句更新<br/> * update ActionTable <br/> * set ACTION_NAME='android.intent.action.CALL', <br/> * LAST_TIME=1287482301403, COUNT=12 <br/> * where ACTION_NAME='android.intent.action.CALL' */ // String sql = "update " + TABLE_NAME // <br/> // + " set " + COLUMN_ACTION + "='" + action + "', "// <br/> // + COLUMN_TIME + "=" + System.currentTimeMillis() + ", "// <br/> // + COLUMN_COUNT + "=" + count// <br/> // + " where " + COLUMN_ACTION + "='" + action + "'"; // sqlDb.execSQL(sql); SodinoOut.out("update row=" + row); return row; } public void existTable(String string) { String sql = "select * from sodino"; Cursor cursor = null; try { cursor = sqlDb.rawQuery(sql, null); if (cursor != null) { SodinoOut.out("Exist table :sodino"); } else { SodinoOut.out("<else>DO NO Exist table :sodino"); } } catch (SQLiteException e) { SodinoOut.out(e.toString()); SodinoOut.out("<catch>DO NO Exist table :sodino"); } finally { if (cursor != null) { cursor.close(); } } } public void upgradeAction(String action) { String temp = queryItem(action, COLUMN_COUNT); if (temp != null) { int count = Integer.parseInt(temp); count++; upgradeItem(action, count); SodinoOut.out(action + " update count = " + count); } else { insertItem(action, System.currentTimeMillis(), 1); SodinoOut.out(action + " added count = " + 1); } } public String getAllOrderedList(String order) { String info = null; String sql = "select * from " + TABLE_NAME + " order by " + COLUMN_COUNT + " " + order; Cursor cursor = sqlDb.rawQuery(sql, null); String line = ""; while (cursor.moveToNext()) { line += cursor.getString(cursor.getColumnIndex(COLUMN_ACTION)) + " "; line += cursor.getString(cursor.getColumnIndex(COLUMN_TIME)) + " "; line += cursor.getString(cursor.getColumnIndex(COLUMN_COUNT)) + "/n"; info += line; line = ""; } cursor.close(); return info; } public void clearRecord() { String sql = "drop table '" + TABLE_NAME + "'"; sqlDb.rawQuery(sql, null); SodinoOut.out("Table drop"); } public int deleteFromOnlyTable(String selection, String[] selectionArgs) { int row = sqlDb.delete(TABLE_NAME, selection, selectionArgs); return row; } public int deleteFromOnlyTable(String key, String selection, String[] selectionArgs) { int row = sqlDb.delete(TABLE_NAME, COLUMN_ACTION + "=" + key + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ")" : ""), selectionArgs); return row; } public int insertToOnlyTable(ContentValues values) { long row = sqlDb.insert(TABLE_NAME, null, values); return (int) row; } public Cursor query(String[] projection, String selection, String[] selectionArgs, String sortOrder) { Cursor cursor = sqlDb.query(TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder); return cursor; } public int updateToOnlyTable(ContentValues values, String selection, String[] selectionArgs) { int row = -1; String action = values.getAsString(COLUMN_ACTION); String result = queryItem(action, COLUMN_COUNT); if (result == null) { row = (int) insertItem(values); SodinoOut.out("action inserted successfully, row = " + row + " count = " + 1); } else { int count = Integer.parseInt(result); count++; values.put(COLUMN_COUNT, count); row = sqlDb.update(TABLE_NAME, values, selection, selectionArgs); SodinoOut.out("action updated successfully, row = " + row + " count = " + count); } return row; } } <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="lab.sodino.broadcastaction" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".BroadcastActionRecordAct" 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=".ActionReceiver" android:enabled="true"> <!-- 关于程序包事件 --> <intent-filter> <action android:name="android.intent.action.PACKAGE_ADDED" /> <action android:name="android.intent.action.PACKAGE_CHANGED" /> <action android:name="android.intent.action.PACKAGE_REMOVED" /> <action android:name="android.intent.action.PACKAGE_DATA_CLEARED" /> <action android:name="android.intent.action.PACKAGE_INSTALL" /> <action android:name="android.intent.action.PACKAGE_REPLACED" /> <action android:name="android.intent.action.PACKAGE_RESTARTED" /> <data android:scheme="package"></data> </intent-filter> <!-- 隐秘数字事件 --> <intent-filter> <action android:name="android.provider.Telephony.SECRET_CODE"></action> <data android:scheme="android_secret_code" android:host="0101"></data> </intent-filter> <!-- 收发短信、SIM卡存储已满、WAP PUSH的接收事件,<br/> 需要android.permission.RECEIVER_SMS及android.permission.RECEIVER_MMS权限 --> <intent-filter> <!-- 无法模仿 --> <action android:name="android.provider.Telephony.SIM_FULL"></action> <!-- SMS_REJECTED:An incoming SMS has been rejected by the telephony framework. This intent is sent in lieu of any of the RECEIVED_ACTION intents.(无法模仿) --> <action android:name="android.provider.Telephony.SMS_REJECTED"></action> <action android:name="android.provider.Telephony.SMS_RECEIVED"></action> </intent-filter> <intent-filter> <!-- 向10086发送短信012345即可有WAP_PUSH,需要android.permission.RECEIVE_WAP_PUSH权限 --> <action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED"></action> <data android:mimeType="application/vnd.wap.sic"></data> </intent-filter> <intent-filter> <!-- 向10086发送短信012345即可有WAP_PUSH,需要android.permission.RECEIVE_WAP_PUSH权限,未证实 --> <action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED"></action> <data android:mimeType="application/vnd.wap.sic"></data> </intent-filter> <intent-filter> <!-- 彩信,需要android.permission.RECEIVE_WAP_PUSH权限,未证实 --> <action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED"></action> <data android:mimeType="application/vnd.wap.mms-message"></data> </intent-filter> <intent-filter> <!-- 开机自启动,需要android.permission.RECEIVE_BOOT_COMPLETED --> <action android:name="android.intent.action.BOOT_COMPLETED"></action> <action android:name="android.intent.action.PRE_BOOT_COMPLETED"></action> <action android:name="android.intent.action.REBOOT"></action> </intent-filter> <intent-filter> <!-- 针对摩托罗拉等有相机快捷键的手机 --> <action android:name="android.intent.action.CAMERA_BUTTON"></action> <action android:name="android.intent.action.CALL_BUTTON"></action> </intent-filter> <intent-filter> <!-- 设置时间、时区时触发 --> <action android:name="android.intent.action.TIME_SET"></action> <action android:name="android.intent.action.TIMEZONE_CHANGED"></action> <action android:name="android.intent.action.LOCALE_CHANGED"></action> <action android:name="android.intent.action.DATE_CHANGED"></action> </intent-filter> <intent-filter> <!-- 来去电事件监听,需要android.permission.READ_PHONE_STATE权限 --> <action android:name="android.intent.action.PHONE_STATE"></action> <!-- 开关Wifi时触发 --> <action android:name="android.net.wifi.WIFI_STATE_CHANGED"></action> <!-- 电话的信号强度已经改变。 --> <action android:name="android.intent.action.SIG_STR"></action> <!-- 电话服务的状态已经改变。(调为飞行模式可观察到变化) --> <action android:name="android.intent.action.SERVICE_STATE"></action> <!-- 当改变AIRPLANE_MODE时触发 --> <action android:name="android.intent.action.AIRPLANE_MODE"></action> </intent-filter> <intent-filter> <action android:name="android.intent.action.WALLPAPER_CHANGED"></action> </intent-filter> <intent-filter> <action android:name="android.intent.action.BATTERY_CHANGED"></action> <action android:name="android.intent.action.BATTERY_LOW"></action> <action android:name="android.intent.action.BATTERY_OKAY"></action> </intent-filter> <intent-filter> <!-- 与充电器或USB连接时触发 --> <action android:name="android.intent.action.ACTION_POWER_CONNECTED"></action> <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"></action> <action android:name="android.intent.action.POWER_USAGE_SUMMARY"></action> <action android:name="android.intent.action.ACTION_SHUTDOWN"></action> </intent-filter> <intent-filter> <!-- (USB mass storage)未模拟 --> <action android:name="android.intent.action.UMS_CONNECTED"></action> <action android:name="android.intent.action.UMS_DISCONNECTED"></action> </intent-filter> <intent-filter> <!-- 未模拟 --> <action android:name="android.intent.action.DEVICE_STORAGE_LOW"></action> <action android:name="android.intent.action.DEVICE_STORAGE_OK"></action> </intent-filter> <intent-filter> <!-- 呼叫转接状态已被更改,未模拟 --> <action android:name="android.intent.action.CFF"></action> <!-- 不明其意,未模拟 --> <action android:name="android.intent.action.DATA_STATE"></action> <!-- 不明其意,未模拟 --> <action android:name="android.intent.action.DATA_ACTIVITY"></action> </intent-filter> <intent-filter> <!-- 不明其意,未模拟 --> <action android:name="android.intent.action.CONFIGURATION_CHANGED"></action> </intent-filter> <intent-filter> <!-- 以下内容有反应,规律不明,适用于电子市场 --> <!-- 取消所有被挂起的 (pending) 更新下载。 --> <action android:name="android.server.checkin.FOTA_CANCEL"></action> <!-- 更新已经被确认,马上就要开始安装。 --> <action android:name="android.server.checkin.FOTA_INSTALL"></action> <!-- 更新已经被下载,可以开始安装。 --> <action android:name="android.server.checkin.FOTA_READY"></action> <!-- 恢复已经停止的更新下载。 --> <action android:name="android.server.checkin.FOTA_RESTART"></action> <!-- 通过 OTA 下载并安装操作系统更新。 --> <action android:name="android.server.checkin.FOTA_UPDATE"></action> </intent-filter> <intent-filter> <action android:name="android.intent.action.SYNC_STATE_CHANGED"></action> <action android:name="com.android.sync.SYNC_CONN_STATUS_CHANGED"></action> </intent-filter> <intent-filter> <action android:name="android.intent.action.HEADSET_PLUG"></action> </intent-filter> <intent-filter> <!-- 选择静音时触发 --> <action android:name="android.media.RINGER_MODE_CHANGED"></action> </intent-filter> <intent-filter> <!-- 扩展介质(扩展卡)已经从 SD 卡插槽拔出,但是挂载点 (mount point) 还没解除 (unmount)。 --> <action android:name="android.intent.action.MEDIA_BAD_REMOVAL"></action> <!-- 用户想要移除扩展介质(拔掉扩展卡)。 --> <action android:name="android.intent.action.MEDIA_EJECT"></action> <!-- 扩展介质被插入,而且已经被挂载。 --> <action android:name="android.intent.action.MEDIA_MOUNTED"></action> <!-- 扩展介质被移除。 --> <action android:name="android.intent.action.MEDIA_REMOVED"></action> <!-- 已经扫描完介质的一个目录。 --> <action android:name="android.intent.action.MEDIA_SCANNER_FINISHED"></action> <!-- 开始扫描介质的一个目录 --> <action android:name="android.intent.action.MEDIA_SCANNER_STARTED"></action> <!-- 扩展介质的挂载被解除 (unmount),因为它已经作为 USB 大容量存储被共享。 --> <action android:name="android.intent.action.MEDIA_SCANNER_SHARED"></action> <!-- 扩展介质存在,但是还没有被挂载 (mount)。 --> <action android:name="android.intent.action.MEDIA_UNMOUNTED"></action> </intent-filter> <intent-filter> <!-- 不了解,未证实 --> <action android:name="android.intent.action.MEDIA_BUTTON"></action> <action android:name="android.media.AUDIO_BECOMING_NOISY" /> </intent-filter> <intent-filter> <!-- 设备收到了新的网络 "tickle" 通知,未模拟 --> <action android:name="android.intent.action.NETWORK_TICKLE_RECEIVED"></action> </intent-filter> <intent-filter> <!-- 条件不允许,未模拟 --> <!-- 更新将要(真正)被安装。 --> <action android:name="android.intent.action.PROVIDER_CHANGED"></action> <!-- 要求 polling of provisioning service 下载最新的设置。 --> <action android:name="android.intent.action.PROVISIONING_CHECK"></action> </intent-filter> <!-- 其它广播事件,不明其意,未模拟 --> <intent-filter> <!-- XMPP 连接已经被建立。 --> <action android:name="android.intent.action.XMPP_CONNECTED"></action> <!-- XMPP 连接已经被断开。 --> <action android:name="andandroid.intent.action.XMPP_DI"></action> <!-- 统计信息服务的状态已经改变。 --> <action android:name="android.intent.action.STATISTICS_STATE_CHANGED"></action> <!-- 要求 receivers 报告自己的统计信息。 --> <action android:name="android.intent.action.STATISTICS_REPORT"></action> <action android:name="android.intent.action.GTALK_DISCONNECTED"></action> <action android:name="android.intent.action.GTALK_CONNECTED"></action> <action android:name="android.intent.action.GET_CONTENT"></action> <action android:name="android.intent.action.MANAGE_PACKAGE_STORAGE"></action> <action android:name="android.intent.action.UID_REMOVED"></action> <action android:name="android.intent.action.USER_PRESENT"></action> </intent-filter> </receiver> <provider android:name=".DBContentProvider" android:authorities="lab.sodino.db"></provider> </application> <uses-sdk android:minSdkVersion="3" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission> <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission> <uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission> <uses-permission android:name="android.permission.RECEIVE_WAP_PUSH"></uses-permission> </manifest>