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>