Launcher3桌面appwidget不见了问题排查

原因是这样,我gradle插件升级到3.1.3.然后在launcher3里面加了一个app的过滤,为了不让这个app显示出来而已,简简单单的一行代码,把数据库删了重新运行一遍,结果桌面的widget不见了。。。不见了,于是第一步把代码回退,还是没有出现。于是有了这篇文章记录下整个分析过程。

launcher加载

launcher第一次加载读取的xml的资源default_workspace.xml,读取完之后保存在数据库,后面有了数据库就不会去读xml资源了。
所以想法一:数据库是否有这个widget,我把数据库pull下来之后发现没有。--也就是说读取xml这边就出问题了。

读取xml方法:
在LauncherProvider.loadFavorites()中,这个方法主要是加载favorite。

              private int loadFavorites(SQLiteDatabase db, int workspaceResourceId) {
            Intent intent = new Intent(Intent.ACTION_MAIN, null);
            intent.addCategory(Intent.CATEGORY_LAUNCHER);
            ContentValues values = new ContentValues();

            if (LOGD)
                Log.v(TAG, String.format("Loading favorites from resid=0x%08x", workspaceResourceId));

            PackageManager packageManager = mContext.getPackageManager();
            int i = 0;
            try {
                //读取xml资源
                XmlResourceParser parser = mContext.getResources().getXml(workspaceResourceId);
                AttributeSet attrs = Xml.asAttributeSet(parser);
                beginDocument(parser, TAG_FAVORITES);

                final int depth = parser.getDepth();

                int type;
                //找到标签元素开始,将其一一对应
                //这个next相当于指针,指向下一位
                while (((type = parser.next()) != XmlPullParser.END_TAG ||
                        parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {

                    if (type != XmlPullParser.START_TAG) {
                        continue;
                    }

                    boolean added = false;
                    final String name = parser.getName();
                    //如果标签是
                    if (TAG_INCLUDE.equals(name)) {
                        final TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.Include);

                        final int resId = a.getResourceId(R.styleable.Include_workspace, 0);

                        if (LOGD)
                            Log.v(TAG, String.format(("%" + (2 * (depth + 1)) + "s"),
                                    "", resId));
                        //遍历的资源
                        if (resId != 0 && resId != workspaceResourceId) {
                            // recursively load some more favorites, why not?
                            i += loadFavorites(db, resId);
                            added = false;
                        } else {
                            Log.w(TAG, String.format("Skipping ", resId));
                        }

                        a.recycle();

                        if (LOGD)
                            Log.v(TAG, String.format(("%" + (2 * (depth + 1)) + "s"), ""));
                        continue;
                    }
                    //这个和自定义属性是一样的,通过tpyeArray找到对应的属性
                    TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.Favorite);
                    for (int ii =0;ii< attrs.getAttributeCount();ii++){
                        Log.d(TAG, "loadFavorites: maliimali  attr"+attrs.getAttributeName(ii)+" :"+attrs.getAttributeValue(ii));
                    }
                    long container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
                    if (a.hasValue(R.styleable.Favorite_container)) {
                        container = Long.valueOf(a.getString(R.styleable.Favorite_container));
                    }
                    //获取属性值
                    String screen = a.getString(R.styleable.Favorite_screen);
                    String x = a.getString(R.styleable.Favorite_x);
                    String y = a.getString(R.styleable.Favorite_y);

                    values.clear();
                    //将属性值保存在values里
                    values.put(LauncherSettings.Favorites.CONTAINER, container);
                    values.put(LauncherSettings.Favorites.SCREEN, screen);
                    values.put(LauncherSettings.Favorites.CELLX, x);
                    values.put(LauncherSettings.Favorites.CELLY, y);

                    if (LOGD) {
                        final String title = a.getString(R.styleable.Favorite_title);
                        final String pkg = a.getString(R.styleable.Favorite_packageName);
                        final String something = title != null ? title : pkg;
                        Log.d(TAG, "maliimali loadFavorites: name = "+name+" container = "+container +"screen = "+screen +" x= "+x+" y = "+y+" something = "+something  );
                        Log.v(TAG, String.format(
                                ("%" + (2 * (depth + 1)) + "s<%s%s c=%d s=%s x=%s y=%s>"),
                                "", name,
                                (something == null ? "" : (" \"" + something + "\"")),
                                container, screen, x, y));
                    }
                    //对应标签添加不同类型的内容,将其保存在数据库里
                    if (TAG_FAVORITE.equals(name)) {
                        long id = addAppShortcut(db, values, a, packageManager, intent);
                        added = id >= 0;
                    } else if (TAG_SEARCH.equals(name)) {
                        added = addSearchWidget(db, values);
                    } else if (TAG_CLOCK.equals(name)) {
                        added = addClockWidget(db, values);
                    } else if (TAG_APPWIDGET.equals(name)) {
                        added = addAppWidget(parser, attrs, type, db, values, a, packageManager);
                    } else if (TAG_SHORTCUT.equals(name)) {
                        long id = addUriShortcut(db, values, a);
                        added = id >= 0;
                    } else if (TAG_FOLDER.equals(name)) {
                        String title;
                        int titleResId = a.getResourceId(R.styleable.Favorite_title, -1);
                        if (titleResId != -1) {
                            title = mContext.getResources().getString(titleResId);
                        } else {
                            title = mContext.getResources().getString(R.string.folder_name);
                        }
                        values.put(LauncherSettings.Favorites.TITLE, title);
                        long folderId = addFolder(db, values);
                        added = folderId >= 0;

                        ArrayList folderItems = new ArrayList();

                        int folderDepth = parser.getDepth();
                        while ((type = parser.next()) != XmlPullParser.END_TAG ||
                                parser.getDepth() > folderDepth) {
                            if (type != XmlPullParser.START_TAG) {
                                continue;
                            }
                            final String folder_item_name = parser.getName();

                            TypedArray ar = mContext.obtainStyledAttributes(attrs,
                                    R.styleable.Favorite);
                            values.clear();
                            values.put(LauncherSettings.Favorites.CONTAINER, folderId);

                            if (LOGD) {
                                final String pkg = ar.getString(R.styleable.Favorite_packageName);
                                final String uri = ar.getString(R.styleable.Favorite_uri);
                                Log.v(TAG, String.format(("%" + (2 * (folderDepth + 1)) + "s<%s \"%s\">"), "",
                                        folder_item_name, uri != null ? uri : pkg));
                            }

                            if (TAG_FAVORITE.equals(folder_item_name) && folderId >= 0) {
                                long id =
                                        addAppShortcut(db, values, ar, packageManager, intent);
                                if (id >= 0) {
                                    folderItems.add(id);
                                }
                            } else if (TAG_SHORTCUT.equals(folder_item_name) && folderId >= 0) {
                                long id = addUriShortcut(db, values, ar);
                                if (id >= 0) {
                                    folderItems.add(id);
                                }
                            } else {
                                throw new RuntimeException("Folders can " +
                                        "contain only shortcuts");
                            }
                            ar.recycle();
                        }
                        // We can only have folders with >= 2 items, so we need to remove the
                        // folder and clean up if less than 2 items were included, or some
                        // failed to add, and less than 2 were actually added
                        if (folderItems.size() < 2 && folderId >= 0) {
                            // We just delete the folder and any items that made it
                            deleteId(db, folderId);
                            if (!folderItems.isEmpty()) {
                                deleteId(db, folderItems.get(0));
                            }
                            added = false;
                        }
                    }
                    if (added) i++;
                    a.recycle();
                }
            } catch (XmlPullParserException e) {
                Log.w(TAG, "Got exception parsing favorites.", e);
            } catch (IOException e) {
                Log.w(TAG, "Got exception parsing favorites.", e);
            } catch (RuntimeException e) {
                Log.w(TAG, "Got exception parsing favorites.", e);
            }

            // Update the max item id after we have loaded the database
            if (mMaxItemId == -1) {
                mMaxItemId = initializeMaxItemId(db);
            }

            return i;
        }

打印log显示传入xml好端端的,通过TypeArray读取出来就为null了,真的匪夷所思。

06-18 16:24:22.711 13793-13793/com.android.launcher3 D/TestDeskClock: loadFavorites: maliimali  attr className :com.android.alarmclock.DigitalAppWidgetProvider
06-18 16:24:22.711 13793-13793/com.android.launcher3 D/TestDeskClock: loadFavorites: maliimali  attr packageName :com.android.deskclock
06-18 16:24:22.711 13793-13793/com.android.launcher3 D/TestDeskClock: loadFavorites: maliimali  attr screen :1
06-18 16:24:22.711 13793-13793/com.android.launcher3 D/TestDeskClock: loadFavorites: maliimali  attr spanX :3
06-18 16:24:22.711 13793-13793/com.android.launcher3 D/TestDeskClock: loadFavorites: maliimali  attr spanY :1
06-18 16:24:22.711 13793-13793/com.android.launcher3 D/TestDeskClock: loadFavorites: maliimali  attr x :0
06-18 16:24:22.711 13793-13793/com.android.launcher3 D/TestDeskClock: loadFavorites: maliimali  attr y :0
06-18 16:24:22.712 13793-13793/com.android.launcher3 D/TestDeskClock: loadFavorites: type = 2 parserName = appwidget attributeSet = 7
06-18 16:24:22.712 13793-13793/com.android.launcher3 D/TestDeskClock: loadFavorites: maliimali parser className :com.android.alarmclock.DigitalAppWidgetProvider
06-18 16:24:22.712 13793-13793/com.android.launcher3 D/TestDeskClock: loadFavorites: maliimali parser packageName :com.android.deskclock
06-18 16:24:22.712 13793-13793/com.android.launcher3 D/TestDeskClock: loadFavorites: maliimali parser screen :1
06-18 16:24:22.712 13793-13793/com.android.launcher3 D/TestDeskClock: loadFavorites: maliimali parser spanX :3
06-18 16:24:22.712 13793-13793/com.android.launcher3 D/TestDeskClock: loadFavorites: maliimali parser spanY :1
06-18 16:24:22.712 13793-13793/com.android.launcher3 D/TestDeskClock: loadFavorites: maliimali parser x :0
06-18 16:24:22.712 13793-13793/com.android.launcher3 D/TestDeskClock: loadFavorites: maliimali parser y :0
06-18 16:24:22.712 13793-13793/com.android.launcher3 D/TestDeskClock: maliimali loadFavorites: name = appwidget container = -100screen = null x= null y = null something = null

最后走了九九八十一关之后,就把xml里面的命名空间指定的包名给删了,没错就是这个

xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"

运行,他喵的竟然可以了。
由于前面耗费了太多仙气,我有点体力不支,到嘴的答案不想钻了,毕竟问题已经改了。还请有人知道的话,悄咪咪的告诉我一声,不胜感激 感激涕零 。
猜测:这个应该和gralde插件有关,插件2.+的时候没有遇到过这个问题,就是最近升级了插件才出现的。
这个可能有解答
In Gradle projects, the actual package used in the final APK can vary; for example,you can add a .debug package suffix in one version and not the other. Therefore, you should not hardcode the application package in the resource; instead, use the special namespace http://schemas.android.com/apk/res-auto which will cause the tools to figure out the right namespace for the resource regardless of the actual package used during the build.

你可能感兴趣的:(Launcher3桌面appwidget不见了问题排查)