編輯:關於Android編程
從上一篇獲取符合默認短信應用來看,獲取思路是正確的,但是還很不完善,但是這歸根結底是google整出來的一套規范,如何去找到符合規范的應用呢,這得google告訴我們。
因此,我看了一下android源碼,關鍵是SmsApplication中的SmsApplicationData, 裡面有個函數叫getApplicationCollection(Context context),這就是android4.4中系統用於獲取符合默認短信應用要求的應用信息的代碼,如下:
/**
* Returns the list of available SMS apps defined as apps that are registered for both the
* SMS_RECEIVED_ACTION (SMS) and WAP_PUSH_RECEIVED_ACTION (MMS) broadcasts (and their broadcast
* receivers are enabled)
*
* Requirements to be an SMS application:
* Implement SMS_DELIVER_ACTION broadcast receiver.
* Require BROADCAST_SMS permission.
*
* Implement WAP_PUSH_DELIVER_ACTION broadcast receiver.
* Require BROADCAST_WAP_PUSH permission.
*
* Implement RESPOND_VIA_MESSAGE intent.
* Support smsto Uri scheme.
* Require SEND_RESPOND_VIA_MESSAGE permission.
*
* Implement ACTION_SENDTO intent.
* Support smsto Uri scheme.
*/
public static Collection getApplicationCollection(Context context) {
PackageManager packageManager = context.getPackageManager();
// Get the list of apps registered for SMS
Intent intent = new Intent(Intents.SMS_DELIVER_ACTION);
List smsReceivers = packageManager.queryBroadcastReceivers(intent, 0);
HashMap receivers = new HashMap();
// Add one entry to the map for every sms receiver (ignoring duplicate sms receivers)
for (ResolveInfo resolveInfo : smsReceivers) {
final ActivityInfo activityInfo = resolveInfo.activityInfo;
if (activityInfo == null) {
continue;
}
if (!permission.BROADCAST_SMS.equals(activityInfo.permission)) {
continue;
}
final String packageName = activityInfo.packageName;
if (!receivers.containsKey(packageName)) {
final String applicationName = resolveInfo.loadLabel(packageManager).toString();
final SmsApplicationData smsApplicationData = new SmsApplicationData(
applicationName, packageName, activityInfo.applicationInfo.uid);
smsApplicationData.mSmsReceiverClass = activityInfo.name;
receivers.put(packageName, smsApplicationData);
}
}
// Update any existing entries with mms receiver class
intent = new Intent(Intents.WAP_PUSH_DELIVER_ACTION);
intent.setDataAndType(null, "application/vnd.wap.mms-message");
List mmsReceivers = packageManager.queryBroadcastReceivers(intent, 0);
for (ResolveInfo resolveInfo : mmsReceivers) {
final ActivityInfo activityInfo = resolveInfo.activityInfo;
if (activityInfo == null) {
continue;
}
if (!permission.BROADCAST_WAP_PUSH.equals(activityInfo.permission)) {
continue;
}
final String packageName = activityInfo.packageName;
final SmsApplicationData smsApplicationData = receivers.get(packageName);
if (smsApplicationData != null) {
smsApplicationData.mMmsReceiverClass = activityInfo.name;
}
}
// Update any existing entries with respond via message intent class.
intent = new Intent(TelephonyManager.ACTION_RESPOND_VIA_MESSAGE,
Uri.fromParts("smsto", "", null));
List respondServices = packageManager.queryIntentServices(intent, 0);
for (ResolveInfo resolveInfo : respondServices) {
final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
if (serviceInfo == null) {
continue;
}
if (!permission.SEND_RESPOND_VIA_MESSAGE.equals(serviceInfo.permission)) {
continue;
}
final String packageName = serviceInfo.packageName;
final SmsApplicationData smsApplicationData = receivers.get(packageName);
if (smsApplicationData != null) {
smsApplicationData.mRespondViaMessageClass = serviceInfo.name;
}
}
// Update any existing entries with supports send to.
intent = new Intent(Intent.ACTION_SENDTO,
Uri.fromParts("smsto", "", null));
List sendToActivities = packageManager.queryIntentActivities(intent, 0);
for (ResolveInfo resolveInfo : sendToActivities) {
final ActivityInfo activityInfo = resolveInfo.activityInfo;
if (activityInfo == null) {
continue;
}
final String packageName = activityInfo.packageName;
final SmsApplicationData smsApplicationData = receivers.get(packageName);
if (smsApplicationData != null) {
smsApplicationData.mSendToClass = activityInfo.name;
}
}
// Remove any entries for which we did not find all required intents.
for (ResolveInfo resolveInfo : smsReceivers) {
final ActivityInfo activityInfo = resolveInfo.activityInfo;
if (activityInfo == null) {
continue;
}
final String packageName = activityInfo.packageName;
final SmsApplicationData smsApplicationData = receivers.get(packageName);
if (smsApplicationData != null) {
if (!smsApplicationData.isComplete()) {
receivers.remove(packageName);
}
}
}
return receivers.values();
}
/**
* Checks to see if we have a valid installed SMS application for the specified package name
* @return Data for the specified package name or null if there isn't one
*/
private static SmsApplicationData getApplicationForPackage(
Collection applications, String packageName) {
if (packageName == null) {
return null;
}
// Is there an entry in the application list for the specified package?
for (SmsApplicationData application : applications) {
if (application.mPackageName.contentEquals(packageName)) {
return application;
}
}
return null;
} 由於這個是隱藏的類和函數,我們獲取不到,用反射又會相當麻煩,直接把實現給拷出來不失為一個良策。
要判斷拿到的collection中的某一個是不是完全符合默認短信應用的要求怎麼辦呢?調用一下SmsApplication.isComplete()就OK了。
Android性能優化之MAT內存檢測
前言1.什麼是內存洩漏?這個問題說來話太長了,似乎盤古開天劈地以來就有的話題一樣,這個問題一直在困擾著程序員,內存洩露 memory leak,是指程序在申請內存後,無法
Android Tab -- 使用Fragment、FragmentManager來實現
效果: 代碼:https://github.com/ldb-github/Layout_Tab1、布局:使用LinearLayout布置標簽;再使用FrameL
安卓輸入框被虛擬鍵盤擋住的問題(微信開發)
先通過一個頁面看下事情的來龍去脈,頁面如下所示: 這個頁面剛好一屏幕大小,所以沒有滾動條,因為“保存”鍵上面那個項目備注是需要用戶去填寫的,當他點擊後就會出現虛
Android打造不一樣的新手引導頁面(一)
本篇博客主要講解怎樣自定義一個circleIndicator控件?下一遍博客主要講解怎樣更改ViewPager切換的效果, 預計明天晚上之前更新。效果圖如下1)首先我們先