Android Q新增悬浮设置Panel,方便三方应用上下文灵活相关设置。
Android官方网站文档中有给到一个场景:
当用户打开浏览器想访问某个站点时,发现当前网络状态是断开的或者处于飞行模式下,这是需要重新开启网络,无论是WiFi还是流量数据哪种。
Android Q之前的做法是,最多浏览器给到一个断网提示,然后用户需要重新进入Settings或者下拉状态栏来连接网络。
而Chrome浏览器,点击后,直接去到的是Settings网络相关界面,这是就退出了当前应用,切换到了系统应用。
而在Android Q引入Settings Panel快捷设置之后,就在三方应用(浏览器)上下文弹窗供用户完成操作。
仿佛就是三方应用(浏览器)本地使用一般。
方便快捷。
从官网可知,Android Q开始,Sdk定义了4个public Action, 如下:
/Android/Sdk/sources/android-29/android/provider/Settings.java
/frameworks/base/core/java/android/provider/Settings.java
/**
* The Settings provider contains global system-level device preferences.
*/
public final class Settings {
//省略若干
/**
* <p>
* A Settings panel is floating UI that contains a fixed subset of settings to address a
* particular user problem. For example, the
* {@link #ACTION_INTERNET_CONNECTIVITY Internet Panel} surfaces settings related to
* connecting to the internet.
* <p>
* Settings panels appear above the calling app to address the problem without
* the user needing to open Settings and thus leave their current screen.
*/
public static final class Panel {
private Panel() {
}
/**
* Activity Action: Show a settings dialog containing settings to enable internet
* connection.
* <p>
* Input: Nothing.
* <p>
* Output: Nothing.
*/
@SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_INTERNET_CONNECTIVITY =
"android.settings.panel.action.INTERNET_CONNECTIVITY";
/**
* Activity Action: Show a settings dialog containing NFC-related settings.
* <p>
* Input: Nothing.
* <p>
* Output: Nothing.
*/
@SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_NFC =
"android.settings.panel.action.NFC";
/**
* Activity Action: Show a settings dialog containing controls for Wifi.
* <p>
* Input: Nothing.
* <p>
* Output: Nothing.
*/
@SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_WIFI =
"android.settings.panel.action.WIFI";
/**
* Activity Action: Show a settings dialog containing all volume streams.
* <p>
* Input: Nothing.
* <p>
* Output: Nothing.
*/
@SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_VOLUME =
"android.settings.panel.action.VOLUME";
}
//省略若干
}
启动方式也很简单,
// settings_panel_type : eg. ACTION_INTERNET_CONNECTIVITY
val panelIntent = Intent(Settings.Panel.settings_panel_type)
startActivityForResult(panelIntent)
据AOSP源码,这些Action通通由一个Activity响应,根据Action加载不同布局。该Activity为:
com.android.settings.panel.SettingsPanelActivity
<activity android:name=".panel.SettingsPanelActivity"
android:label="@string/settings_panel_title"
android:theme="@style/Theme.Panel"
android:launchMode="singleInstance"
android:excludeFromRecents="true"
android:configChanges="orientation|keyboardHidden|screenSize"
android:exported="true">
<intent-filter>
<action android:name="android.settings.panel.action.INTERNET_CONNECTIVITY" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.settings.panel.action.NFC" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.settings.panel.action.WIFI" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.settings.panel.action.VOLUME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
布局由/Settings/src/com/android/settings/panel/PanelFragment.java加载实现。
接下来先看看,各个Action启动后呈现的效果.
无论是哪个界面,其底部都 有两个按钮,see more和done。
see more跳转到Settings中设置的界面,可以看到更多详细的信息和复杂的操作。
done则直接消失弹窗,回归当前应用上下文。
// done button click
public class PanelFragment extends Fragment {
mDoneButton = mLayoutView.findViewById(R.id.done);
mDoneButton.setOnClickListener(getCloseListener());
@VisibleForTesting
View.OnClickListener getCloseListener() {
return (v) -> {
mPanelClosedKey = PanelClosedKeys.KEY_DONE;
getActivity().finish();
};
}
}
上边提到启动方式是startActivityForResult(intent)。
那么返回来时onActivityResult,会有什么带回来吗?从done响应事件处理看看,没有。
写个demo看看,以WIFI为例,无论是进入到settings回来还是弹窗操作完, 也是没有的。
06-08 12:54:25.523 28138 28138 D knealq : click btn...
06-08 12:54:25.551 28138 28138 D activity1: onPause:
06-08 12:54:25.551 28138 28138 D activity1: getProp: unknown
06-08 12:54:26.768 28138 28138 D activity1: onStop:
06-08 12:54:26.772 28138 28138 D activity1: onSaveInstanceState: 2
// done click
06-08 12:56:25.831 28138 28138 D activity1: onActivityResult: requestCode:123, resultCode:0, data:null
06-08 12:56:25.832 28138 28138 D activity1: onActivityResult: back from Settings.Panel
06-08 12:56:25.840 28138 28138 D activity1: onRestart:
06-08 12:56:25.851 28138 28138 D activity1: onStart:
06-08 12:56:25.859 28138 28138 D activity1: onResume:
06-08 12:56:25.860 28138 28138 D activity1: onResume:
所以当done返回界面后,需要自身进行网络状态的重检,或者继续本地流程。
还有一个问题,发现WIFI最多只能显示3个,也就是说,如果以你的热点在当前所有热点靠后的地方,是无法下拉找到,必须see more。
如果热点在前三,并未记住过,可以直接基于弹窗选中连接热点,无须进入到Settings-> wifi界面点击热点连接。
但是如果你记住过自己的热点,那么该热点会自动重连,并排在第一位,这就相当于只需要在弹窗打开wifi开关即可。
完