編輯:Android開發教程
android如何使用BroadcastReceiver後台實現來電通話記錄的監聽並存取到sqllite數據庫通過Contentprovilder實現接口
BroadcastReceiver 是android四大組件的一個,本質上是一種全局的監聽器 ,用於監聽全局的廣播消息。下面實現了後台監聽android手機通話記錄。本demo 分兩個程序,第一個程序是設置監聽器,然後模擬器重啟後就會有一個全局的 service在後台監聽你的來電顯示,大多數通話管理軟件都是這麼干的,第二個項 目是獲取通話記錄的,由於只是做一個小實驗,所以是根據某個項目改的,裡面 涉及到一些ContentPrivler的知識,還有sqllite數據庫,裡面定義名稱並非其意 思。
第一個程序代碼配置文件
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android" android:versionCode="1" android:versionName="1.0" > <application android:icon="@drawable/ic_launcher" android:label="@string/app_name"> <service android:name=".TtActivity"> </service> <!-- 定義一個BroadcastReceiver,監聽系統開機廣播 --> <receiver android:name=".LaunchReceiver"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> <provider android:name=".DictProvider" android:authorities="org.crazyit.providers.dictprovider"/> </application> <!-- 授予應用程序訪問系統開機事件的權限 --> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> </manifest> /** * */ package com.android; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class LaunchReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Intent tIntent = new Intent(context , TtActivity.class); // 啟動指定Service context.startService(tIntent); } } /** * */ package com.android; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class MyDatabaseHelper extends SQLiteOpenHelper { final String CREATE_TABLE_SQL = "create table dict(_id integer primary key autoincrement , word , detail)"; /** * @param context * @param name * @param version */ public MyDatabaseHelper(Context context, String name, int version) { super(context, name, null, version); } @Override public void onCreate(SQLiteDatabase db) { // 第一個使用數據庫時自動建表 db.execSQL(CREATE_TABLE_SQL); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { System.out.println("--------onUpdate Called--------" + oldVersion + "--->" + newVersion); } } package com.android; import java.io.FileNotFoundException; import java.io.OutputStream; import java.text.SimpleDateFormat; import java.util.Date; import android.app.Service; import android.content.Context; import android.content.Intent; import android.database.sqlite.SQLiteDatabase; import android.os.IBinder; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; public class TtActivity extends Service { MyDatabaseHelper dbHelper; TelephonyManager tManager; SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String word=format.format(new Date()); @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { tManager = (TelephonyManager) getSystemService (Context.TELEPHONY_SERVICE); dbHelper = new MyDatabaseHelper(this , "myDict.db3" , 1); // 創建一個通話狀態監聽器 PhoneStateListener listener = new PhoneStateListener() { @Override public void onCallStateChanged(int state , String detail) { switch (state) { // 無任何狀態 case TelephonyManager.CALL_STATE_IDLE: break; case TelephonyManager.CALL_STATE_OFFHOOK: break; // 來電鈴響時 case TelephonyManager.CALL_STATE_RINGING: OutputStream os = null; try { os = openFileOutput("phoneList", MODE_APPEND); } catch (FileNotFoundException e) { e.printStackTrace(); } insertData(dbHelper.getReadableDatabase() , word , detail); // PrintStream ps = new PrintStream(os); // // 將來電號碼記錄到文件中 // ps.println(new Date() + " 來電:" + incomingNumber); // ps.close(); break; default: break; } super.onCallStateChanged(state, detail); } }; //監聽電話通話狀態的改變 tManager.listen(listener , PhoneStateListener.LISTEN_CALL_STATE); } private void insertData(SQLiteDatabase db , String word , String detail) { //執行插入語句 db.execSQL("insert into dict values(null , ? , ?)" , new String[]{word , detail}); } @Override public void onDestroy() { super.onDestroy(); //退出程序時關閉MyDataBaseHelper裡的SQLiteDatabase if (dbHelper != null) { dbHelper.close(); } } } /** * */ package com.android; import android.net.Uri; import android.provider.BaseColumns; /** * @version 1.0 */ public final class Words { // 定義該ContentProvider的Authority public static final String AUTHORITY = "org.crazyit.providers.dictprovider"; //定義一個靜態內部類 public static final class Word implements BaseColumns { // 定義Content所允許操作的3個數據列 public final static String _ID = "_id"; public final static String WORD = "word"; public final static String DETAIL = "detail"; // 定義該Content提供服務的兩個Uri public final static Uri DICT_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/words"); public final static Uri WORD_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/word"); } }
/** * */ package com.android; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; /** * @version 1.0 */ public class DictProvider extends ContentProvider { private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); private static final int WORDS = 1; private static final int WORD = 2; private MyDatabaseHelper dbOpenHelper; static { // 為UriMatcher注冊兩個Uri matcher.addURI(Words.AUTHORITY, "words", WORDS); matcher.addURI(Words.AUTHORITY, "word/#", WORD); } // 第一次調用該DictProvider時,系統先創建DictProvider對象,並回調該方法 @Override public boolean onCreate() { dbOpenHelper = new MyDatabaseHelper(this.getContext(), "myDict.db3", 1); return true; } // 插入數據方法 @Override public Uri insert(Uri uri, ContentValues values) { // 獲得數據庫實例 SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); // 插入數據,返回行ID long rowId = db.insert("dict", Words.Word._ID, values); // 如果插入成功返回uri if (rowId > 0) { // 在已有的 Uri的後面追加ID數據 Uri wordUri = ContentUris.withAppendedId(uri, rowId); // 通知數據已經改變 getContext().getContentResolver().notifyChange(wordUri, null); return wordUri; } return null; } // 刪除數據的方法 @Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); // 記錄所刪除的記錄數 int num = 0; // 對於uri進行匹配。 switch (matcher.match(uri)) { case WORDS: num = db.delete("dict", selection, selectionArgs); break; case WORD: // 解析出所需要刪除的記錄ID long id = ContentUris.parseId(uri); String where = Words.Word._ID + "=" + id; // 如果原來的where子句存在,拼接where子句 if (selection != null && !selection.equals("")) { where = where + " and " + selection; } num = db.delete("dict", where, selectionArgs); break; default: throw new IllegalArgumentException("未知Uri:" + uri); } // 通知數據已經改變 getContext().getContentResolver().notifyChange(uri, null); return num; } // 修改數據的方法 @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); // 記錄所修改的記錄數 int num = 0; switch (matcher.match(uri)) { case WORDS: num = db.update("dict", values, selection, selectionArgs); break; case WORD: // 解析出想修改的記錄ID long id = ContentUris.parseId(uri); String where = Words.Word._ID + "=" + id; // 如果原來的where子句存在,拼接where子句 if (selection != null && !selection.equals("")) { where = where + " and " + selection; } num = db.update("dict", values, where, selectionArgs); break; default: throw new IllegalArgumentException("未知Uri:" + uri); } // 通知數據已經改變 getContext().getContentResolver().notifyChange(uri, null); return num; } // 查詢數據的方法 @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); switch (matcher.match(uri)) { case WORDS: // 執行查詢 return db.query("dict", projection, selection, selectionArgs, null, null, sortOrder); case WORD: // 解析出想查詢的記錄ID long id = ContentUris.parseId(uri); String where = Words.Word._ID + "=" + id; // 如果原來的where子句存在,拼接where子句 if (selection != null && !"".equals(selection)) { where = where + " and " + selection; } return db.query("dict", projection, where, selectionArgs, null, null, sortOrder); default: throw new IllegalArgumentException("未知Uri:" + uri); } } // 返回指定uri參數對應的數據的MIME類型 @Override public String getType(Uri uri) { switch (matcher.match(uri)) { // 如果操作的數據是多項記錄 case WORDS: return "vnd.android.cursor.dir/org.crazyit.dict"; // 如果操作的數據是單項記錄 case WORD: return "vnd.android.cursor.item/org.crazyit.dict"; default: throw new IllegalArgumentException("未知Uri:" + uri); } } }
CyanogenMod 10(CM10),最新基於Android 4.1果凍豆版本的ROM,在今天對少數設備推出。版本10已經在過去的數月經歷了無數個夜晚的beta開發,
前面介紹了Android測試的一些理論知識,從本篇開始的幾篇將結合ApiDemoTest示例來介紹Android測試的實例。在此之前可 以參照Android測試教程(3)
App->Activity->Custom Dialog 例子使用Activity 來實現自定義對話框。 類CustomDialogActivity本身無任何
Google已經提供了你正在使用的三個Nexus設備之一的系統更新,我們高興的是,Nexus 4和10的Android 4.2 OTA更新也開始推出了。此次的升級包括了&