问题
新增和编辑APN都是使用ApnEditorActivity,但是进入的方式不同,如果APN做成插件的话,点击添加按钮的时候会提示“选择要使用的应用”,因为Settings本身也有这个界面被安装进去了 。
- 新增功能通过Intent.ACTION_INSERT跳转界面
- 编辑功能通过Intent.ACTION_EDIT跳转界面
参考解决方案
通过优先级设置(<intent-filter android:priority="100">)并不能解决“选择要使用的应用”弹窗的问题,只能在AndroidManifest.xml移除Settings中对ApnEditorActivity的定义。
<!--
<activity android:name="Settings$ApnEditorActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:exported="true"
android:label="@string/apn_edit">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.EDIT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/telephony-carrier" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.INSERT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.dir/telephony-carrier" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.network.apn.ApnEditor" />
<meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
android:value="@string/menu_key_network"/>
</activity>
-->
代码分析
新增APN
在ApnSettings中创建菜单,添加对应key=MENU_NEW,当菜单选择时执行addNewApn从而Intent.ACTION_INSERT
/** Handle each different apn setting. */
public class ApnSettings extends RestrictedSettingsFragment
implements Preference.OnPreferenceChangeListener {
static final String TAG = "ApnSettings";
public static final String EXTRA_POSITION = "position";
private static final int MENU_NEW = Menu.FIRST;
private static final int MENU_RESTORE = Menu.FIRST + 1;
//APN设置的菜单
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (!mUnavailable) {
if (mAllowAddingApns) {
menu.add(0, MENU_NEW, 0,//新建
getResources().getString(R.string.menu_new))
.setIcon(R.drawable.ic_add_24dp)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
menu.add(0, MENU_RESTORE, 0,//重置
getResources().getString(R.string.menu_restore))
.setIcon(android.R.drawable.ic_menu_upload);
}
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_NEW:
addNewApn();
return true;
case MENU_RESTORE:
restoreDefaultApn();
return true;
}
return super.onOptionsItemSelected(item);
}
private void addNewApn() {
final Intent intent = new Intent(Intent.ACTION_INSERT, Telephony.Carriers.CONTENT_URI);
final int subId = mSubscriptionInfo != null ? mSubscriptionInfo.getSubscriptionId()
: SubscriptionManager.INVALID_SUBSCRIPTION_ID;
intent.putExtra(SUB_ID, subId);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (!TextUtils.isEmpty(mMvnoType) && !TextUtils.isEmpty(mMvnoMatchData)) {
intent.putExtra(MVNO_TYPE, mMvnoType);
intent.putExtra(MVNO_MATCH_DATA, mMvnoMatchData);
}
startActivity(intent);
}
}
编辑APN
在ApnSettings中apn_list添加了ApnPreference,将每个APN加载到APN列表中,而ApnPreference会相应点击事件,触发APN编辑功能,进入APN详情页。
/**
* Preference of APN UI entry
*/
public class ApnPreference extends Preference implements CompoundButton.OnCheckedChangeListener,
View.OnClickListener {
private static final String TAG = "ApnPreference";
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@Override
public void onClick(View layoutView) {
super.onClick();
final Context context = getContext();
final int pos = Integer.parseInt(getKey());
if (context == null) {
Log.w(TAG, "No context available for pos=" + pos);
return;
}
if (mHideDetails) {
Toast.makeText(context, context.getString(
R.string.cannot_change_apn_toast), Toast.LENGTH_LONG).show();
return;
}
//APN对应的数据库信息
final Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos);
final Intent editIntent = new Intent(Intent.ACTION_EDIT, url);
editIntent.putExtra(ApnSettings.SUB_ID, mSubId);
editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(editIntent);
}