解决Android4.4 Widget之AppWidgetHost.allocateAppWidgetId()返回-1
16lz
2021-01-25
【原创文章,转载请声明】转自http://blog.csdn.net/allen_704/article/details/28640827
Android4.4对widget有了一些变化,遇到的问题如题所示,无法创建widget。
看4.4的源码,在frameworks\base\services\java\com\android\server\AppWidgetServiceImpl.java这个类里面
public int allocateAppWidgetId(String packageName, int hostId) { int callingUid = enforceSystemOrCallingUid(packageName); synchronized (mAppWidgetIds) { if (!mHasFeature) { return -1; } ensureStateLoadedLocked(); int appWidgetId = mNextAppWidgetId++; Host host = lookupOrAddHostLocked(callingUid, packageName, hostId); AppWidgetId id = new AppWidgetId(); id.appWidgetId = appWidgetId; id.host = host; host.instances.add(id); mAppWidgetIds.add(id); saveStateAsync(); if (DBG) log("Allocating AppWidgetId for " + packageName + " host=" + hostId + " id=" + appWidgetId); return appWidgetId; } }
看到这里,瞬间怀疑方法开始的这个if(!mHasFeature)这个判断,为了更进一步确认看一下4.1的源码,手上正好也有
public int allocateAppWidgetId(String packageName, int hostId) { int callingUid = enforceCallingUid(packageName); synchronized (mAppWidgetIds) { ensureStateLoadedLocked(); int appWidgetId = mNextAppWidgetId++; Host host = lookupOrAddHostLocked(callingUid, packageName, hostId); AppWidgetId id = new AppWidgetId(); id.appWidgetId = appWidgetId; id.host = host; host.instances.add(id); mAppWidgetIds.add(id); saveStateLocked(); return appWidgetId; } }
看到了吧!基本可以判断是4.4中的那个判断引起的了,此时,来追踪mHasFeature这个变量。其声明和赋值如下
final boolean mHasFeature;//-------------------------------------AppWidgetServiceImpl(Context context, int userId, Handler saveStateHandler) { mContext = context; mPm = AppGlobals.getPackageManager(); mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); mUserId = userId; mSaveStateHandler = saveStateHandler; mHasFeature = context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_APP_WIDGETS); computeMaximumWidgetBitmapMemory(); }
到了这里,去查PackageManager的hasSystemFeature方法,最后实现是在这个地方frameworks\base\services\java\com\android\server\pm\PackageManagerService.java
public boolean hasSystemFeature(String name) { synchronized (mPackages) { return mAvailableFeatures.containsKey(name); } }
继续看mAvailableFeatures这个集合是在哪里声明赋值的,首先看声明
// These are the features this devices supports that were read from the // etc/permissions.xml file. final HashMap mAvailableFeatures = new HashMap();
高潮来了, 看注释!These are the features this devices supports that were read from the etc/permissions.xml file.哈哈,到这里基本就知道问题在哪了,不过顺便也看看mAvailableFeatures是怎么赋值的
private void readPermissionsFromXml(File permFile) { FileReader permReader = null; try { permReader = new FileReader(permFile); } catch (FileNotFoundException e) { Slog.w(TAG, "Couldn't find or open permissions file " + permFile); return; } try { XmlPullParser parser = Xml.newPullParser(); parser.setInput(permReader); XmlUtils.beginDocument(parser, "permissions"); while (true) { XmlUtils.nextElement(parser); if (parser.getEventType() == XmlPullParser.END_DOCUMENT) { break; } String name = parser.getName(); if ("group".equals(name)) { // ..... } else if ("permission".equals(name)) { // ..... } else if ("assign-permission".equals(name)) { // ..... } else if ("library".equals(name)) {// ..... } else if ("feature".equals(name)) { String fname = parser.getAttributeValue(null, "name"); if (fname == null) { Slog.w(TAG, " without name at " + parser.getPositionDescription()); } else { //Log.i(TAG, "Got feature " + fname); FeatureInfo fi = new FeatureInfo(); fi.name = fname; mAvailableFeatures.put(fname, fi); } XmlUtils.skipCurrentTag(parser); continue; } else { XmlUtils.skipCurrentTag(parser); continue; } } permReader.close(); } catch (XmlPullParserException e) { Slog.w(TAG, "Got execption parsing permissions.", e); } catch (IOException e) { Slog.w(TAG, "Got execption parsing permissions.", e); } }
结合刚才说的注释,就去检查etc/permisions.xml里面有没有关于widget的feature咯,这个feature的字符串可以从PackageManager里面可以看到是“android.software.app_widgets”。
取出/system/etc/permissions.xml文件一搜,果真没有这个feature,同时也检查了etc目录下其他xml文件,都没有这个feature。
那么现在要做的就是增加这个feature,在permisions.xml中追加如下内容,也可以弄成单独xml放到etc目录
将文件push进去之后再次创建widget,Bingo!, allocateAppWidgetId返回不是-1啦,widget也创建成功了~~~
【原创文章,转载请声明】转自http://blog.csdn.net/allen_704/article/details/28640827
更多相关文章
- 一款常用的 Squid 日志分析工具
- GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
- RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
- Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
- Android(安卓)简单GreenDao增删改查
- 我的Android工作笔记
- Android学习笔记(十五)-简易视频播放器
- android中使用ant打包APK
- android 源码开发 关于编译等小知识点总结