Android P新特性实践-Slices
概述
在2018年谷歌I/O开发者大会上,谷歌发布了万众期待的Android最新版本-Android P。Slice作为Android P版本更新的一大功能,其使用场景以及新API的使用也格外引人注目。
Slice其实是一个UI展示模块,它可以在搜索APP、语音助手、关键字识别等动作中动态地显示你的APP部分模块的内容,通过它,可以丰富地显示你的APP当中的内容。Slice提供shortcut、small、large三种View显示模板,开发者可以根据自身APP需求选择合适的显示模板。
开始使用
Tips
1.在开始使用之前,你需要更新最新版本的Android Studio,到目前我使用的最新版本为 Android Studio 3.3 Canary 3 。以便支持最新的Android扩展插件,AndroidX。
2.下载安装谷歌官方提供的Slice模块搜索测试工具,[Slice Viewer sample](Slice Viewer ) ,仅支持安卓4.4以上的手机调试使用。
1.新建你的Android项目,在gradle中添加如下依赖:
implementation 'androidx.slice:slice-core:1.0.0-beta01'
implementation 'androidx.slice:slice-builders:1.0.0-beta01'
2.为你的APP创建Slice,你需要在你的项目文件中,点击右键选择New… > Other > Slice Provider,编辑器将会自动帮你在AndroidManifest.xml中添加Provider:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.app">
...
<application>
...
<provider
android:name=".provider.MySliceProvider"
android:authorities="com.xxx.xxxxxx.slicedemo.provider"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.app.slice.category.SLICE" />
<data
android:host="guanjianhui.teach.com"
android:pathPrefix="/hello"
android:scheme="http" />
</intent-filter>
</provider>
...
</application>
</manifest>
3.其中,SliceProvider继承于ContentProvider,其APP间数据的传递通过
ContentProvider的方式,应用APP向搜索APP对外提供其对应Slice的Uri,封装成Slice对象通过Parcelable序列化的方式实现APP之间的数据传递。新建类继承SliceProvider,并重写onBindSlice()方法,在该方法里可以编写Slice展示模块中的相关逻辑代码:
@Override
public Slice onBindSlice(Uri sliceUri) {
if (getContext() == null) {
return null;
}
SliceAction activityAction = createActivityAction();
ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY);
// Create parent ListBuilder.
if ("/hello".equals(sliceUri.getPath())) {
listBuilder.addRow(new ListBuilder.RowBuilder()
.setTitle("Hello World")
.setPrimaryAction(activityAction)
);
} else {
listBuilder.addRow(new ListBuilder.RowBuilder()
.setTitle("URI not recognized")
.setPrimaryAction(activityAction)
);
}
return listBuilder.build();
}
Uri的scheme统一为content,如上述例子的Uri为:
content://com.xxx.xxxxxx.slicedemo.provider/hello
4.跟notifications类似,你可以使用PendingIntents 来处理用户的点击事件,比如点击Slice模块打开宿主APP:
public Slice createSlice(Uri sliceUri) {
if (getContext() == null) {
return null;
}
SliceAction activityAction = createActivityAction();
return new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
.addRow(new ListBuilder.RowBuilder()
.setTitle("Perform action in app.")
.setPrimaryAction(activityAction)
).build();
}
public SliceAction createActivityAction() {
if (getContext() == null) {
return null;
}
return SliceAction.create(
PendingIntent.getActivity(
getContext(),
0,
new Intent(getContext(), MainActivity.class),
0
),
IconCompat.createWithResource(getContext(), R.drawable.ic_home),
ListBuilder.ICON_IMAGE,
"Enter app"
);
}
5.通过开始安装的Slice Viewer ,搜索框中输入对应Slice的URI地址,便可在搜索APP中看到应用APP中添加的Slice模块:
Slice模板
ListBuilder
Slices通过ListBuilder类来创建。在ListBuilder中,你可以添加不同类型的行模块在你的Slice中进行展示。
SliceAction
对于每一个Slice来说,最基础的构造实现类是SliceAction,在SliceAction你可以添加PendingIntent来实现用户操作,比如Toggle选择操作:
SliceAction toggleAction =SliceAction.createToggle(createToggleIntent(),"Toggle adaptive brightness",true);
SliceAction可以配置在搜索APP中显示的模块三种不同的显示方式:
ICON_IMAGE:tiny size and tintable:
SMALL_IMAGE:small size and non-tintable:
LARGE_IMAGE: largest size and non-tintable:
模块构造Builder
对于每个Slice模块的创建构造,谷歌官方提供了HeaderBuilder、RowBuilder、GridBuilder、RangeBuilder模块四种构造器。其中,HeaderBuilder只支持一行头部的展示view;RowBuilder可以添加一行view进行展示,如此前没有添加header,则首行row默认为header;GridBuilder支持上述所说的三种模块展示方式;而RangeBuilder则支持进度条相关的view展示。
延时加载
对于一些需要耗时加载数据的操作,比如网络请求图片等,可以采取与ListView加载图片类似的方法,先本地加载一个默认的占位数据,等耗时操作完成回调回来真实数据的时候调用getContentResolver().notifyChange(sliceUri) 方法,通知搜索APP调用Slice Uri,完成真实数据的显示。
结语
Slice的功能模板非常的强大,通过不同的builder组合可以在搜索模块中搭配出丰富多彩的Slice,快速直达用户想要的功能。但是Slice只提供了三种模板,自带模板中对安卓原生控件的支持有所欠缺,比如ScollView等,可能需要用户自定义自己的模板才能实现更强大的功能。