android 7.1 上wifi 热点 上的接口变化

android 7.1 上wifi 热点 上的接口变化

在android 7.1 之前 设置wifi ap方法如下:

WifiManager mWifiManager = (WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);
mWifiManager.setWifiApEnabled(null, true)

android 7.1后 api 发生了变化 用 setWifiApEnabled打开会导致 连接热点失败,通过在 android 原生setting 查看源码 发现 7.1后 改用

import static android.net.ConnectivityManager.TETHERING_WIFI;

private Handler mHandler = new Handler();
private OnStartTetheringCallback mStartTetheringCallback;


...................

mStartTetheringCallback = new OnStartTetheringCallback(this); 
ConnectivityManager mCm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
 mCm.startTethering(TETHERING_WIFI, true, mStartTetheringCallback, mHandler);


private static final class OnStartTetheringCallback extends
            ConnectivityManager.OnStartTetheringCallback {
        final WeakReference mTetherSettings;

        OnStartTetheringCallback(TetherSettings settings) {
            mTetherSettings = new WeakReference(settings);
        }

        @Override
        public void onTetheringStarted() {
            update();
        }

        @Override
        public void onTetheringFailed() {
            update();
        }

        private void update() {
            TetherSettings settings = mTetherSettings.get();
            if (settings != null) {
                settings.updateState();
            }
        }
    }


这里7.1采用ConnectivityManager类的 startTethering方法 我们看下framework源码里面 startTethering原型

    @SystemApi  
    public void startTethering(int type, boolean showProvisioningUi,
            final OnStartTetheringCallback callback) {
        startTethering(type, showProvisioningUi, callback, null);
    }


    @SystemApi
    public void startTethering(int type, boolean showProvisioningUi,
            final OnStartTetheringCallback callback, Handler handler) {
        ResultReceiver wrappedCallback = new ResultReceiver(handler) {
            @Override
            protected void onReceiveResult(int resultCode, Bundle resultData) {
                if (resultCode == TETHER_ERROR_NO_ERROR) {
                    callback.onTetheringStarted();
                } else {
                    callback.onTetheringFailed();
                }
            }
        };
        try {
            mService.startTethering(type, wrappedCallback, showProvisioningUi);
        } catch (RemoteException e) {
            Log.e(TAG, "Exception trying to start tethering.", e);
            wrappedCallback.send(TETHER_ERROR_SERVICE_UNAVAIL, null);
        }
    }

    @SystemApi
    public void stopTethering(int type) {
        try {
            mService.stopTethering(type);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

startTethering方法参数官方具体解释如下:
/**
* Runs tether provisioning for the given type if needed and then starts tethering if
* the check succeeds. If no carrier provisioning is required for tethering, tethering is
* enabled immediately. If provisioning fails, tethering will not be enabled. It also
* schedules tether provisioning re-checks if appropriate.
*
* @param type The type of tethering to start. Must be one of
* {@link ConnectivityManager.TETHERING_WIFI},
* {@link ConnectivityManager.TETHERING_USB}, or
* {@link ConnectivityManager.TETHERING_BLUETOOTH}.
* @param showProvisioningUi a boolean indicating to show the provisioning app UI if there
* is one. This should be true the first time this function is called and also any time
* the user can see this UI. It gives users information from their carrier about the
* check failing and how they can sign up for tethering if possible.
* @param callback an {@link OnStartTetheringCallback} which will be called to notify the caller
* of the result of trying to tether.
* @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
* @hide

我们 代开wifi 热点 用 ConnectivityManager.TETHERING_WIFI
显示UI更新 ,这里用到 ConnectivityManager.OnStartTetheringCallback
由于这是一个静态的类,我们可以用过弱引用找到父类的 一些方法 和 Context等
来更新 打开热点的结果

      private static final class OnStartTetheringCallback extends
            ConnectivityManager.OnStartTetheringCallback {
        final WeakReference mTetherSettings;

        OnStartTetheringCallback(TetherSettings settings) {
            mTetherSettings = new WeakReference(settings);
        }

        @Override
        public void onTetheringStarted() {
            update();
        }

        @Override
        public void onTetheringFailed() {
            update();
        }

        private void update() {
            TetherSettings settings = mTetherSettings.get();
            //**通过get方法找到父类的引用 并调用方法**
            if (settings != null) {
                settings.updateState();
            }
        }
    }

最后在 7.1上面通过修改setWifiApEnabled方法 并成功连接到wifi ap 上网

PS: android7.1 startTethering方法是系统api 只能在系统源码里面编译 自己做了个jar包 以及导入的方法 还有demo apk 方便使用eclipse 的童鞋使用

注意:很多童鞋反应没有作用,请 ps | grep com.example.wifiap7 看下uid是否为 system , 7.1权限更严格.必须是system用户才能控制wifi热点,附件里面提供的platform签名文件为android原生的,其他厂家可能自己有改

android 7.1 wifi热点Demo

你可能感兴趣的:(Android,Framework)