【原创文章,转载请声明】转自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


更多相关文章

  1. 一款常用的 Squid 日志分析工具
  2. GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
  3. RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
  4. Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
  5. Android(安卓)简单GreenDao增删改查
  6. 我的Android工作笔记
  7. Android学习笔记(十五)-简易视频播放器
  8. android中使用ant打包APK
  9. android 源码开发 关于编译等小知识点总结

随机推荐

  1. android静默安装探讨
  2. AI一分钟 | 谷歌:欧盟做出50亿美元罚款决
  3. 反编译并且修改Android(安卓)APK包
  4. Linux文件的特殊权限位SUID、SGID作用及
  5. 关于Android的selector背景选择器的配置
  6. Android和ios哪个前景更好
  7. Android内核开发:序
  8. 如何检索Android设备的唯一ID
  9. [Android算法] Android蓝牙开发浅谈
  10. Alibaba无线搜索事业部-产品经理(移动端产