MTKデュアルカードの移動データのオン/オフに関するいくつかの小さな研究


最近、MTKデュアルカード携帯電話、4.1のシステムを研究しています.プログラムでデータを移動させるスイッチを制御するのは、難題にぶつかった.以前に反射的な方法でConnectivityManagerクラスを呼び出したsetMobileDataEnabledメソッドが無効になったことを発見したため,このメソッドが見つからないことを示すメッセージが表示され,第一の反応は4.1システムにこのメソッドがないのか,考えても不可能であることである.ソースコードを調べると、断固として元と同じです.再度デバッグを行い、ConnectivityManagerクラスのすべての関数を取り出します.このメソッドもあります.理由を調べると、プライベートメソッドのため、呼び出せない可能性があります.しかし、コードを変更してプライベートメソッドを呼び出すことができて、権限を加えて、システムの署名を加えて、やはりこのようにして、私のコードに問題があるのかどうか分かりませんが、みんなは見て、笑ってはいけません.
private void setGprsEnable(boolean isEnable) {
        int result = 0;
ConnectivityManager mCM = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
        try {
            Class clazz = Class.forName(mCM.getClass().getName());
            Constructor[] cons = clazz.getDeclaredConstructors();
            Constructor con = clazz.getConstructor();//getDeclaredConstructors();
            con.setAccessible(true);

            Field iConnectivityManagerField = clazz.getDeclaredField("mService");
            iConnectivityManagerField.setAccessible(true);
            Object iConnectivityManager = iConnectivityManagerField.get(mCM);
            //Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName());
            ConnectivityManager cm =  (ConnectivityManager)con.newInstance(iConnectivityManager);
            Class[] argClasses = new Class[1];
            argClasses[0] = Boolean.class;
            Method ms = clazz.getDeclaredMethod("setMobileDataEnabled", argClasses);
            ms.setAccessible(true);
            Object obj = ms.invoke(cm, isEnable);
            result = (Integer) obj;
        } catch (ClassNotFoundException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
}

この方法が通じない以上、別の方法を探します.まず海卓のインターネットマスターを降りて、結果はシステムの署名が必要でデータスイッチを制御することができることを提示して、再起動した後にappはシステム/appの中で移動して、断固として実現することができて、しかしどんな方法を使うのか分からないで、ソースコードがなくて調べることができて、googleも資料がありません.logcatを真剣に観察するしかありませんが、少しは発見できるかどうか見てみましょう.
皇天は心を持たないで、いくつかの情報を見つけます.データ接続がオンの場合、logcatはいくつかの重要な情報を出力します.
Provider/Settings(506): put string name = gprs_connection_setting , value = 1 userHandle = 0
SettingsProvider(506): insert(content://settings/system) for user 0 by 0
SettingsProvider(506): redundant, old Value: 0 new value: 1
SettingsProvider(506): system <- value=1 name=gprs_connection_setting for user 0

Provider/Settings(506): put string name = gprs_connection_sim_setting , value = 3 userHandle = 0
SettingsProvider(506): insert(content://settings/system) for user 0 by 0
SettingsProvider(506): redundant, old Value: 0 new value: 3
SettingsProvider(506): system <- value=3 name=gprs_connection_sim_setting for user 0

Provider/Settings(506): Global.putString(name=mobile_data, value=1 for 0
Provider/Settings(506): put string name = mobile_data , value = 1 userHandle = 0
SettingsProvider(506): redundant, old Value: 0 new value: 1
SettingsProvider(506): global <- value=1 name=mobile_data for user 0

この3つの値を変更すればいいのではないでしょうか.思い切ってやってみるのが嬉しい.
ContentResolver cr = getWindow().getContext().getContentResolver();
Settings.System.putInt(cr, "gprs_connection_setting", 1);
Settings.System.putInt(cr, "gprs_connection_sim_setting", 3);
Settings.Global.putInt(cr, "mobile_data", 1);

加えてWRITE_SECURE_SETTINGSとWRITE_SETTINGS権限、システム署名を加えて再試行します.結果は依然として開くことができなくて、しかし発見して、ドロップダウンメニューの中のショートカットボタン、状態はすでに変わって、データ接続はすでに開いたことを表示して、信号値のあの少ないデータ接続のHあるいはEアイコンです.システムがどのように配置情報を更新していないのかと悩んでいたところ、飛行モードをオンにしてみましたが、オンになってから飛行モードをオフにして、結局、データがつながってしまいました.フライトモードがオフになると、システムがネットワークを再構成し始め、ネットワーク構成を更新し、変更した値が有効になります.
ネットワークの状態が変化すると、システムはネットワーク構成を更新することができる以上、ネットワーク変更のブロードキャストを送信すると、私たちが変更した構成をすぐに更新することができるのではないでしょうか.いくつかの放送を出してみたが、残念ながらだめで、理解できなかった.しかし、wifiをスイッチすれば、効果は飛行モードと同じで、依然として私の望む結果に達することができます.so、時間が限られているので、まずこの方法を使いましょう.wifiのスイッチについて私はこのように操作しています.wifiが接続されているとき、実はデータ接続が開いているかどうかは重要ではありません.wifiがオフになると、システムは自動的に構成を更新します.
Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            switch(msg.what){
            case 0:
                //wifi  ,    
                if(wifiManager.isWifiEnabled()&&mActivity.getWifiState()==200){
                    wifiManager.setWifiEnabled(false);
                    sendEmptyMessageDelayed(2, 200);
                }
                else if(wifiManager.isWifiEnabled()){

                }
                else{
                    wifiManager.setWifiEnabled(true);
                    sendEmptyMessageDelayed(1, 200);
                }
                break;
            case 1:
                wifiManager.setWifiEnabled(false);
                break;
            case 2:
                wifiManager.setWifiEnabled(true);
                break;
            }
            super.handleMessage(msg);
        }
    };

今問題は解決した.MTKデュアルカードのシステムを使っているので、ここではもう少し処理します
int defaultsim = getDefaultSim();
Settings.System.putInt(cr, "gprs_connection_setting", defaultsim);

getDefaultSim()メソッドはMTKのインタフェースで、反射で取れます.ここはもう貼らない.そうだ、権限をつけるのを忘れないでCHANGE_NETWORK_STATE、CHANGE_WIFI_STATE、ACCESS_WIFI_STATE.
この方法は完璧ではありませんが、いつも使えます.OMG、時間があればゆっくり研究しましょう.