一.
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:\ZK-R31X_5.1_RK3128_Firmware\ZK_R31A_RK312X_ANDROID5.1\out\target\product\rk312x\system\etc\apns-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 + "\n"); os.writeBytes("exit\n"); 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) { } } } }
全球運營商APN-參數