Android8.1 Lancher3添加默认widget
Android8.1 Lancher3添加默认widget
话不多说,直接上代码
在res/xml/default_workspace_4x4.xml中添加
<appwidget
launcher:container="-100"
launcher:packageName="com.android.deskclock"
launcher:className="com.android.alarmclock.DigitalAppWidgetProvider"
launcher:screen="0"
launcher:spanX="5"
launcher:spanY="2"
launcher:x="0"
launcher:y="2"/>
其中
a. launcher:container="-100",表示添加在 desktop 中,如果是-101那就是在 HotSeat 中,但是这里我们的 widget 是要添加在 desktop,所以是-100;
b. launcher:packageName=“com.android.deskclock”,这个没啥说的,就是widget的包名,我这里添加的是数字时钟,所以这里填写的是 时钟模块 的包名;
c. launcher:className=“com.android.alarmclock.DigitalAppWidgetProvider”,这个是 widget 所在的类,这是是数字时钟,如果要添加 表盘时钟(指针时钟),就填写com.android.alarmclock.AnalogAppWidgetProvider;
d. launcher:screen=“0”,这个是添加在哪一屏;
e. launcher:spanX=“5”,这个表示 widget 在 x 方向上占位多少,我的launcher是 x 方向可以放5个APP图标,所以这里widget是占满整个 x 方向;
f. launcher:spanY=“2”,这个表示 widget 在 y 方向上站位多少,2表示占用相当于两个APP图标的高度;
g. launcher:x=“0”,这个表示 widget 的 x 方向上的位置,这里0表示从屏幕最左侧开始显示;
h. launcher:y=“2”,这个表示 widget 的 y 方向上的位置,这里3表示从上往下第3个位置开始显示(从0开始,所以2就是第3个)。
看下效果图:
这样就结束了。
但是有一个偶现的问题:有时widget会添加不上!
找了一下原因,发现在
src/com/android/launcher3/DefaultLayoutParser.java中:
protected class AppWidgetParser extends PendingWidgetParser {
@Override
protected long verifyAndInsert(ComponentName cn, Bundle extras) {
......
final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
long insertedId = -1;
try {
int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
if (!appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, cn)) {
Log.e(TAG, "Unable to bind app widget id " + cn);
mAppWidgetHost.deleteAppWidgetId(appWidgetId);
return -1;
}
......
每一个widget添加的时候都会存到 launcher.db 中,失败的时候 appWidgetId 的值是0,这里调用的是
framework/base/core/java/android/appwidget/AppWidgetHost.java->allocateAppWidgetId()
/**
* Get a appWidgetId for a host in the calling process.
*
* @return a appWidgetId
*/
public int allocateAppWidgetId() {
if (sService == null) {
return -1;
}
try {
return sService.allocateAppWidgetId(mContextOpPackageName, mHostId);
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
}
}
最终调用的是:
framework/base/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java->allocateAppWidgetId()
@Override
public int allocateAppWidgetId(String callingPackage, int hostId) {
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "allocateAppWidgetId() " + userId);
}
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(callingPackage);
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
if (mNextAppWidgetIds.indexOfKey(userId) < 0) {
mNextAppWidgetIds.put(userId, AppWidgetManager.INVALID_APPWIDGET_ID + 1);
}
final int appWidgetId = incrementAndGetAppWidgetIdLocked(userId);
// NOTE: The lookup is enforcing security across users by making
// sure the caller can only access hosts it owns.
HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage);
Host host = lookupOrAddHostLocked(id);
Widget widget = new Widget();
widget.appWidgetId = appWidgetId;
widget.host = host;
host.widgets.add(widget);
addWidgetLocked(widget);
saveGroupStateAsync(userId);
if (DEBUG) {
Slog.i(TAG, "Allocated widget id " + appWidgetId
+ " for host " + host.id);
}
return appWidgetId;
}
}
找了一会还是没找到最终出现这个问题的原因,如果有同学知道原因,还请不吝指教