一.
Apn设置,即“接入点名称”设置,Apn的全称是Access PointName,是用户在通过手机上网时必须配置的一个参数,它决定了您的手机通过哪种接入方式来访问移动网络。
对于移动终端用户来说,可以访问的外部网络类型有很多,例如:Internet、WAP网站、集团企业内部网络、行业内部专用网络。而不同的接入点所能访问的范围以及入的方式是不同的,网络侧如何知道移动终端激活以后要访问哪个网络从而分配哪个网段的 IP呢,这就要靠 APN来区分了,即 APN决定了用户的移动终端通过哪种接入方式来访问什么样的网络。
常见的 APN有:中国移动的 cmnet 和 cmwap、中国联通的uninet 和 uniwap、中国电信的 ctnet 和 ctwap
1.1.apns-conf.xml
<apn carrier="中国移动物联网2G" mcc="460" mnc="04" apn="cmmtm" type="default,supl" /> <apn carrier="中国联通物联网gzm2mapn" mcc="460" mnc="06" apn="unim2m.gzm2mapn" port="80" type="default,supl" /> <apn carrier="中国联通物联网njm2mapn" mcc="460" mnc="06" apn="unim2m.njm2mapn" type="default,supl" /> <apn carrier="中国电信物联网m2m" mcc="460" mnc="03" apn="CTNET" user="m2m" password="vnet.mobi" type="default" /> <apn carrier="中国移动物联网卡00" mcc="460" mnc="00" apn="cmiot" type="default,supl" /> <apn carrier="中国移动物联网卡02" mcc="460" mnc="02" apn="cmiot" type="default,supl" />
1.2.
// 解释: // IMSI是国际移动用户识别码的简称(International Mobile Subscriber Identity) // IMSI共有15位,其结构如下: // MCC+MNC+MIN // MCC:Mobile Country Code,移动国家码,共3位,中国为460; // MNC:Mobile NetworkCode,移动网络码,共2位 // 在中国,移动的代码为电00和02,联通的代码为01,电信的代码为03 // 合起来就是(也是Android手机中APN配置文件中的代码): // 中国移动:46000 46002 // 中国联通:46001 // 中国电信:46003 // 举例,一个典型的IMSI号码为460030912121001
1.3.
cmnet(China Mobile Network) 中国移动互联网 cmiot 中国移动物联网的简称
1.4.
查询当前apn信息 content query --uri content://telephony/carriers/preferapn 修改接入点 content insert --uri content://telephony/carriers/preferapn --bind apn_id:i:123456 后面的123456换成查询到的id
二.
2.1.APN Uri介绍
content://telephony/carriers代表的是APN数据库的位置,所有的APN都在这个数据库中。 content://telephony/carriers //取得全部apn列表 content://telephony/carriers/preferapn //取得当前设置的 content://telephony/carriers/current //取得current=1的apn列表 content://telephony/carriers/restore //恢复默认设置
2.2.权限
<!--开关APN的权限 --> <uses-permission android:name="android.permission.WRITE_APN_SETTINGS" /> <!-- 允许读取电话状态SIM的权限 --> <uses-permission android:name="android.permission.READ_PHONE_STATE" />
2.3.
package com.gatsby.apn; import android.app.Activity; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.telephony.TelephonyManager; import android.util.Log; public class MainActivity extends Activity { public static final Uri APN_URI = Uri.parse("content://telephony/carriers"); public static final Uri CURRENT_APN_URI = Uri.parse("content://telephony/carriers/preferapn"); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); int czyhId = addAPN(); SetAPN(czyhId); } // apn carrier="中国移动物联网卡08" mcc="460" mnc="08" apn="cmiot" type="default,supl" // 新增一个接入点 public int addAPN() { int id = -1; String NUMERIC = getSIMInfo(); Log.d("gatsby", "NUMERIC->" + NUMERIC); if (NUMERIC == null) { return -1; } ContentResolver resolver = this.getContentResolver(); ContentValues values = new ContentValues(); values.put("name", "中国移动物联网卡08");// apn中文描述 values.put("apn", "cmiot"); // apn名称 values.put("mcc", "460");// apn类型 values.put("mnc", "08"); values.put("numeric", NUMERIC);// 中国移动:46000 46002 values.put("type", "default,supl"); // apn类型 Cursor c = null; Uri newRow = resolver.insert(APN_URI, values); if (newRow != null) { c = resolver.query(newRow, null, null, null, null); int idIndex = c.getColumnIndex("_id"); c.moveToFirst(); id = c.getShort(idIndex); } if (c != null) c.close(); return id; } public void SetAPN(int id) { ContentResolver resolver = this.getContentResolver(); ContentValues values = new ContentValues(); values.put("apn_id", id); resolver.update(CURRENT_APN_URI, values, null, null); } protected String getSIMInfo() { TelephonyManager iPhoneManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); return iPhoneManager.getSimOperator(); } }
三.
3.1.
adb root adb remount adb push Z:K-R31X_5.1_RK3128_FirmwareK_R31A_RK312X_ANDROID5.1out argetproduct k312xsystemetcapns-conf.xml system/etc adb shell cd /data/data/com.android.providers.telephony/databases rm -rf /data/data/com.android.providers.telephony/databases/telephony.db
3.2.
package com.gatsby.test; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.util.Timer; import java.util.TimerTask; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class MainActivity extends Activity implements OnClickListener { private Button btn1; private boolean isoncl = true; private static String UPDATE_TITLE = "Copying File!"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn1 = (Button) findViewById(R.id.btn1); btn1.setOnClickListener(this); } @Override public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.btn1: if (isoncl) { isoncl = false; // set update title btn1.setText(UPDATE_TITLE); btn1.setTextSize(64); Toast.makeText(MainActivity.this, "update file start", Toast.LENGTH_SHORT).show(); // NO.1 copy the asserts to /mnt/sdcard/ copyFilesFassets(this, "apns-conf.xml", "/mnt/sdcard/apns-conf.xml"); // NO.3 remount the system in case the system is read only if (Build.VERSION.SDK_INT >= 25) { RootCommand("mount -o rw,remount -t ext4 /system"); RootCommand("mount -o rw,remount -t ext4 /vendor"); } else { RootCommand("mount -o remount,rw /system"); } // NO.4 RootCommand("busybox cp -rf /mnt/sdcard/apns-conf.xml /system/etc/apns-conf.xml"); // NO.5 Toast.makeText(MainActivity.this, "Copy file successfully! To Repoot ", Toast.LENGTH_LONG).show(); timer.schedule(task, 10000); } break; } } Timer timer = new Timer(); @SuppressLint("HandlerLeak") Handler handler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case 1: // NO.7 reboot RootCommand("rm -rf /mnt/sdcard/apns-conf.xml"); RootCommand("rm -rf /data/data/com.android.providers.telephony/databases/telephony.db"); RootCommand("reboot"); break; } super.handleMessage(msg); } }; TimerTask task = new TimerTask() { public void run() { Message message = new Message(); message.what = 1; handler.sendMessage(message); } }; public void copyFilesFassets(Context context, String oldPath, String newPath) { try { InputStream is = context.getAssets().open(oldPath); FileOutputStream fos = new FileOutputStream(new File(newPath)); byte[] buffer = new byte[1024]; int byteCount = 0; while ((byteCount = is.read(buffer)) != -1) { fos.write(buffer, 0, byteCount); } fos.flush(); is.close(); fos.close(); } catch (Exception e) { e.printStackTrace(); } } private void RootCommand(String cmd) { Process process = null; DataOutputStream os = null; DataInputStream is = null; try { process = Runtime.getRuntime().exec("/system/xbin/su"); os = new DataOutputStream(process.getOutputStream()); os.writeBytes(cmd + " "); os.writeBytes("exit "); os.flush(); int aa = process.waitFor(); is = new DataInputStream(process.getInputStream()); byte[] buffer = new byte[is.available()]; is.read(buffer); String out = new String(buffer); Log.d("xinhua", out + aa); } catch (Exception e) { e.printStackTrace(); } finally { try { if (os != null) { os.close(); } if (is != null) { is.close(); } process.destroy(); } catch (Exception e) { } } } }