最近做项目中涉及到了apn,以及双卡双待的apn,遇到一些问题,各种纠结,好在给解决了,现在记录下来,方便自己以后用到,也希望能让大家以后遇到少走些弯路。
首先说下单卡apn,4.0以下的版本,对apn有增、删、改、查的权限,4.0以上只有查的权限了(即使在manifest里面加上权限也只能查询),想来是android基于安全考虑吧,apn实际上是一张系统表,每行数据都会在设置里面显示,现在有很多定制的手机厂商加入了很多东西,比如电信“PPP拨叫号码”等,这些在android原生里面是不存在的,所以在设置apn的时候,注意下是不是定制手机。
单卡的 apn:
好了,开始进入关键部分吧,首先得在manifest里面加上权限
<uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
此外还需要定义好uriUri PREFERRED_APN_URI = Uri.parse("content://telephony/carriers/preferapn"); // 获取当前选中的apn
Uri APN_TABLE_URI = Uri.parse("content://telephony/carriers"); // 获取所有的apn信息这两个一定要区分开
查询所有apn:
ContentResolver resolver = mContext.getContentResolver();
Cursor cursor = resolver.query(PREFERRED_APN_URI, null, null, null, null);
while(cursor.movetonext){
}
查询当前选中的apn:
ContentResolver resolver = mContext.getContentResolver();
Cursor cursor = resolver.query( APN_TABLE_URI,
null, null, null, null);while(cursor.movetonext){
}
我们是通过列名来找相对应的信息,下面就说下比较常见的列名吧:
_id //apn的id
name //apn名称 ( 比如联通apn 的名称:沃3G连接互联网)
apn //对应的apn (比如联通apn:3gnet)
numeric //运营商编码 46000,46002 表示移动,46001 表示联通,46003 表示电信
当然apn的列名我们也可以查询出来
for(int i = 0 ;i<c.getColumnNames().length;i++){
System.out.println(c.getColumnName(i));
}注意:当前apn选中的uri 跟手机里面所有apn的uri 的区别,
插入apn:
public void insertAPN(String name, String apn_addr, String username, String password) {
ContentResolver resolver = mContext.getContentResolver();
Cursor c = null;c = resolver.query(PREFERRED_APN_URI, new String[] { "mcc", "mnc", "numeric" }, null, null, null);
if (c != null) {
if (c.moveToNext()) {
cmcc = c.getString(0);
cmnc = c.getString(1);
cnumeric = c.getString(2);
}
}ContentValues values = new ContentValues();
values.put("name", name);
values.put("apn", apn_addr);
values.put("user", username);
values.put("password", password);values.put("mcc", cmcc != null ? cmcc : "460");
values.put("mnc", cmnc != null ? cmnc : "02");
values.put("numeric", cnumeric != null ? cnumeric : "46002");
Uri newRow = resolver.insert(APN_TABLE_URI, values);
}
} catch (SQLException e) {
e.printStackTrace();
}if (c != null)
c.close();}
修改apn:
public boolean SetDefaultAPN(int id) {
boolean res = false;
ContentResolver resolver = mContext.getContentResolver();
ContentValues values = new ContentValues();
values.put("apn_id", id);
try {
resolver.update(PREFERRED_APN_URI, values, null, null);
Cursor c = resolver.query(PREFERRED_APN_URI, new String[] { "name",
"apn" }, "_id=" + id, null, null);
if (c != null) {
res = true;
c.close();
}
} catch (SQLException e) {
Log.d(mTAG, e.getMessage());
}
return res;
}删除apn:
public int deleteAPN(int id) {
ContentResolver resolver = mContext.getContentResolver();
ContentValues values = new ContentValues();
values.put("_id", id);
return resolver.delete(APN_TABLE_URI, "_id=" + id, null);
}最后说下双卡双待的apn,
双卡双待的手机,比如一个电信,一个移动,那么只能用其中的一个,在激活之后,当前apn就是激活卡当前选中的apn,切换之后,也是一样,虽然android原生代码里面有没有双卡双待这么一说,不过当前的apn还是可以通过代码获取到的,这样就只跟卡是否开通apn有关系了。