安卓中 廣播 服務 及其簡單應用範圍的一些總結
阿新 • • 發佈:2019-01-26
1.廣播與廣播接收者
1.API
靜態註冊廣播接收者
清單檔案中配置:
<receiver android:name="包名.廣播接收者檔案" >
<intent-filter android:priority="廣播攔截的優先順序(最大:2147483647)" >
<action android:name="廣播監聽的動作 可以是自定義的或者系統廣播" />
</intent-filter>
</receiver>
動態註冊廣播接收者
1.動態建立一個廣播接收者
class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//收到廣播後
//1.可以觸發某些事件
//2.從initen引數中獲取廣播發送的資料
}
};
2.對廣播接收者進行動態註冊
Receiver = new MyReceiver();
//設定filter資訊
IntentFilter filter = new IntentFilter();
filter.addAction("自定義的或者系統廣播"); //設定廣播監聽的動作
//註冊
registerReceiver(Receiver, filter);
3.取消註冊
unregisterReceiver(mReceiver);
mReceiver = null;
自定義廣播發送(通過intent攜帶資料)
Intent intent = new Intent();
intent.putExtra("鍵", 要攜帶到接收者的資訊);
intent.setAction("自定義廣播"); //設定廣播監聽的動作
sendBroadcast(intent);
兩種廣播的區別
靜態註冊廣播接收者在程式的整個執行期間都會監聽。
動態註冊的廣播接收者可以控制在需要的時候開啟監聽,不需要的時候關閉監聽。通常可以將動態註冊廣播接收者放到一個服務中,服務開啟時註冊廣播,服務關閉時取消註冊。
2.例子
常見系統廣播
//監聽系統啟動廣播
<receiver android:name=".receiver.BootCompleteReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
//監聽簡訊
<receiver android:name=".receiver.SmsReceiver" >
<intent-filter android:priority="2147483647" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
//獲取管理員許可權 MyAdminReceiver需要實現但是不用寫內容
<receiver
android:name=".receiver.MyAdminReceiver"
android:description="@string/sample_device_admin_description"
android:label="@string/sample_device_admin"
android:permission="android.permission.BIND_DEVICE_ADMIN" >
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/device_admin_sample" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
//監聽建立快捷方式
<receiver android:name=".receiver.MyWidget" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/process_widget_provider" />
</receiver>
//監聽殺死所有程序
<receiver android:name=".receiver.KillProcess">
<intent-filter>
<action android:name="com.example.mobilesafe.KILLALLPROCESS" />
</intent-filter>
</receiver>
動態註冊廣播接收者(一般在服務中動態註冊 重要)
適用情況: 廣播接收者監聽事件變化,有變化後就返回給服務,服務通過返回Bind或者寫SharePrecefence等方法傳出資料。
具體運用舉例:
1.開啟電話監聽,監聽來電去電 ,例如 黑名單,歸屬地查詢等
2.程式加鎖 ,監聽當前棧頂程式是否被加鎖
3.實時定位 ,不斷讀取當前定位資訊
4.鎖屏事件 ,監聽到鎖屏後可以做一些清理工作
5.和桌面上的Widget通訊
兩種註冊型別的區別:
靜態註冊是當程式關閉後,如果有廣播發過來,還能啟動程式
動態註冊的生命週期跟程式的生命週期是一樣的,程式關閉後動態註冊的廣播是不能在接收到廣播的
動態註冊的優點:在Android的廣播機制中,動態註冊的優先順序高於靜態註冊的優先順序,因此在必要情況下,我們需要動態註冊廣播接收器。
靜態註冊的有點:動態註冊廣播接收器還有一個優點就是當用來註冊廣播的Activity關閉後,廣播也就失效了,同時反映了靜態註冊廣播的一個優勢,就是無需擔心廣播接收器是否關閉,只要裝置處於開啟狀態,廣播接收器就能接收。
操作頻繁的廣播事件,如果只是在清單配置檔案配置,是不生效的。需要使用程式碼註冊才能生效;
步驟:
例1:// 監聽螢幕開關
// 1、得到廣播接收者的物件
ScreenBroadCastReceiver screenReceiver = new ScreenBroadCastReceiver();
// 2、建立一個intentFilter物件
IntentFilter filter = new IntentFilter();
// 3、註冊接收的事件型別
filter.addAction("android.intent.action.SCREEN_ON");
filter.addAction("android.intent.action.SCREEN_OFF");
// 4、註冊廣播接收者
this.registerReceiver(screenReceiver, filter);
例2.// 註冊監聽去電的廣播
mReceiver = new OutCallReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_NEW_OUTGOING_CALL);
registerReceiver(mReceiver, filter);
以上兩例需要我們自己實現廣播接收者,下面這個例子中系統為我們實現了回撥方法
例3. //來電話
mListener = new MyPhoneStateListener();
mTM.listen(mListener, PhoneStateListener.LISTEN_CALL_STATE);// 監聽來電狀態
class MyPhoneStateListener extends PhoneStateListener {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:// 電話玲響
break;
case TelephonyManager.CALL_STATE_IDLE:// 通話結束
break;
default:
break;
}
super.onCallStateChanged(state, incomingNumber);
}
}
例4.//設定快捷方式
Intent intent = new Intent(
"com.android.launcher.action.INSTALL_SHORTCUT");
// 設定快捷方式的圖示
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, BitmapFactory
.decodeResource(getResources(), R.drawable.home_tools));
// 設定快捷方式名稱
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "黑馬小衛士");
//不允許重複
intent.putExtra("duplicate", false);
// 動作,跳轉主頁面
Intent actionIntent = new Intent();
actionIntent.setClass(this,MainActivity.class);
//actionIntent.setAction("com.example.mobilesafe.MAIN");// 通過action啟動主頁面,需要在清單檔案配置action
//actionIntent.addCategory(Intent.CATEGORY_DEFAULT);// 必須配置categroy
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, actionIntent);
// 傳送廣播
sendBroadcast(intent);
2.服務
2.1 API
註冊一個服務
清單檔案
<service android:name=".service.MyService" />
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
//建立服務的時候呼叫
@Override
public void onCreate() {
System.out.println("*****onCreate******");
super.onCreate();
}
//啟動server 每次start都會呼叫一次
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("*****onStartCommand******");
return super.onStartCommand(intent, flags, startId);
}
//手動停止程式後會終止服務,會呼叫onDestroy()方法
@Override
public void onDestroy() {
System.out.println("*****onDestroy******");
super.onDestroy();
}
}
開啟一個服務
1.啟動
//使用Intent
Intent intent = new Intent(當前Activity.this, MyService.class);
startService(intent);
stopService(intent);
2.使用bind讓其他元件獲取服務提供的資料
//使用Intent
Intent intent = new Intent(當前Activity.this, MyService.class);
bindService(intent, conn, BIND_AUTO_CREATE);
unbindService(conn);
注意事項
bindService繫結服務、unBindService解除繫結的服務;
服務是在被繫結的時候被建立,呼叫oncreate、onbind方法;
服務只能被繫結一次;
服務只能被解除一次,接觸繫結的時候呼叫onUnbind、onDestrory方法,如果多次解除繫結會丟擲異常;
推薦的方式(啟用順序):
1.startService:開啟並建立一個服務,服務長期執行在後臺;
2.bindService:繫結服務,可以呼叫服務裡面的方法;
3.unBindService:解除服務,停止服務裡面的方法;
4.stopService:停止服務,銷燬服務物件;
獲取服務中的資料(與服務通訊)
MyService中
//這個函式用於返回資料
public IBinder onBind(Intent intent)
{
return new MyBind(); //返回到前臺的物件,包含要執行的service中的方法
}
//繼承Binder類,這是因為要返回一個實現IBinder型別介面的
public class MyBind extends Binder
{
public void callPaly() {
paly();
}
}
客戶端
//繫結服務
bindService(intent, new MyServiceConnection(), BIND_AUTO_CREATE);
//獲取服務返回的資料
class MyServiceConnection implements ServiceConnection
{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//返回服務中包含要呼叫方法的類
serverRet = (MyBind) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
aidl 獲取其他程序服務的資訊
3.內容提供者
3.1API
1.內容解釋者
作用: 用來解析內容觀察者提供的資料庫資訊
ContentResolver contentResolver = getContentResolver();
//getContentResolver();是上下文中攜帶的方法,用於處理內容提供者提供的訪問方式。
尋找哪個內容提供者需要用通過uri,uri路徑分文 "主機名"+"具體要操作的資料" 其中"主機名"在提供資料庫程式的清單檔案中定義,"具體要操作的資料"在這個程式的原始碼中(一般檔名有provide字樣),
我們可以通過查詢"UriMatcher"函式搜尋相關的資訊。
Uri uri = Uri.parse("content://.../"); //指定查詢哪個應用下資料庫的哪個表
Cursor cursor = contentResolver.query(uri, ... ...);
2.內容觀察者
//註冊內容觀察者
getContentResolver().registerContentObserver(uri, true, new MyObeserver(new Handler()));
//收到通知後回撥其中的方法
class MyObeserver extends ContentObserver
{
public MyObeserver(Handler handler) {
super(handler);
}
//發現監視路徑下的資料庫發生變化就會呼叫此方法
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
}
}
//在資料庫操作中發出訊號,通知觀察者
// 通知觀察者,資料發生變化了
Context.getContentResolver().notifyChange(Uri.parse("content://..."),null);
3.2應用場合舉例
1.查詢聯絡人資料庫
2.查詢簡訊資料庫
3.音樂檔案
自定義的資料庫我們直接使用SQLiteOpenHelper進行查詢
4.意圖 的一些應用場合和分類
隱式意圖
開啟其他應用
安裝程式
/**
* 使用隱式題圖安裝指定路徑下的apk
* @param path
*/
private void installApk(String path)
{
File file = new File(path);
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file),"application/vnd.android.package-archive");
//startActivity(intent);
startActivityForResult(intent, 0);
}
解除安裝程式
/**
* 解除安裝應用
*/
private void uninstall(String packageName) {
// 跳轉到解除安裝頁面
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(Uri.parse("package:" + packageName));
startActivityForResult(intent, 0);
}
清理快取
// 清理單個檔案快取
// 跳轉到系統設定頁面
Intent intent = new Intent();
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.setData(Uri.parse("package:" + info.packageName));
intent.addCategory(Intent.CATEGORY_DEFAULT);
startActivity(intent);
打電話
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setAction(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:"+number));
startActivity(intent);
顯式意圖
...
傳送廣播
例子見第一章
開啟服務
例子見第二章
帶返回值的開啟新的Activity
1.A頁面跳轉到B:
Intent intent = new Intent(AActivity.this, BActivity.class);
// 如果需要返回資料,用此方法傳送intent 第二個引數為傳送碼
startActivityForResult(intent, 2);
2.B頁面傳送資料給A,B頁面關閉:
Intent intent = new Intent();
intent.putExtra("...", ...);
setResult(2, intent);
finish();
3.A頁面接收B傳來的資料:
在A頁面的類中複寫以下方法,通過傳送碼或者返回碼判斷接收到資料的流向
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode == 1)
{
...
}else if(resultCode == 2){
...
}
super.onActivityResult(requestCode, resultCode, data);
}
這裡寫程式碼片