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>