在网上找了好久唯一launcher的实现方式,发现都是一同一个人写的,而且并没有实现这个功能,因为按照这个方式去做的话,当你按下HOME键还是出现了选择launcher的对话框,然后自己研究了一天,找到了最直接有效的而且是最简单的方法实现全局唯一launcher的功能:

修改frameworks\base\core\java\android\content\pm\PackageParser.java,在parseIntent这个私有方法,因为APK在安装的时候会通过这个方法解析Manifest清单文件,然后将每个Activity的intent-filter保存在内存中,所以修改这个方法就相当于修改了内存的应用注册表的信息,也就是偷换概念的做法,等于是在安装的时候就把问题解决了,扼杀在萌芽状态:


修改部分为:

这里xxx随便你输入,例如你在你自己的launcher的Manifest的Activity里Intent-filter里加入:


<category android:name="android.intent.category.HOME.xxx" />


那么在代码里修改的地方的xxx就替换成你自己起的名字

原理就是安装每个APK的时候 只要是launcher ,就把category是HOME的值改成x,只要是你的launcher就把category的值改成HOME,那么全局就只有你一个launcher了


这里是修改的部分:

/*************************************************************************************/                if(Intent.CATEGORY_HOME.equals(value)) {                value = "x";                } else if((Intent.CATEGORY_HOME + ".xxx").equals(value)) {                value = Intent.CATEGORY_HOME;                }                /*************************************************************************************/

使用这种方法修改时必须确保你的launcher被安装了或者放在了syste/app下了且Manifest的Activity里的intent-filter为android.category.HOME.xxx




具体的原理请参考我的另外一篇博客:http://blog.csdn.net/zhbinary/article/details/7353739





修改frameworks\base\core\java\android\content\pm\PackageParser.java里的parseIntent方法
private boolean parseIntent(Resources res,            XmlPullParser parser, AttributeSet attrs, int flags,            IntentInfo outInfo, String[] outError, boolean isActivity)            throws XmlPullParserException, IOException {        TypedArray sa = res.obtainAttributes(attrs,                com.android.internal.R.styleable.AndroidManifestIntentFilter);        int priority = sa.getInt(                com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);        if (priority > 0 && isActivity && (flags&PARSE_IS_SYSTEM) == 0) {            Log.w(TAG, "Activity with priority > 0, forcing to 0 at "                    + mArchiveSourcePath + " "                    + parser.getPositionDescription());            priority = 0;        }        outInfo.setPriority(priority);                TypedValue v = sa.peekValue(                com.android.internal.R.styleable.AndroidManifestIntentFilter_label);        if (v != null && (outInfo.labelRes=v.resourceId) == 0) {            outInfo.nonLocalizedLabel = v.coerceToString();        }        outInfo.icon = sa.getResourceId(                com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);        sa.recycle();        int outerDepth = parser.getDepth();        int type;        while ((type=parser.next()) != parser.END_DOCUMENT               && (type != parser.END_TAG || parser.getDepth() > outerDepth)) {            if (type == parser.END_TAG || type == parser.TEXT) {                continue;            }            String nodeName = parser.getName();            if (nodeName.equals("action")) {                String value = attrs.getAttributeValue(                        ANDROID_RESOURCES, "name");                if (value == null || value == "") {                    outError[0] = "No value supplied for <android:name>";                    return false;                }                XmlUtils.skipCurrentTag(parser);                outInfo.addAction(value);            } else if (nodeName.equals("category")) {                String value = attrs.getAttributeValue(                        ANDROID_RESOURCES, "name");                if (value == null || value == "") {                    outError[0] = "No value supplied for <android:name>";                    return false;                }                XmlUtils.skipCurrentTag(parser);                                                                /*************************************************************************************/                if(Intent.CATEGORY_HOME.equals(value)) {                value = "x";                } else if((Intent.CATEGORY_HOME + ".xxx").equals(value)) {                value = Intent.CATEGORY_HOME;                }                /*************************************************************************************/                                                                outInfo.addCategory(value);            } else if (nodeName.equals("data")) {                sa = res.obtainAttributes(attrs,                        com.android.internal.R.styleable.AndroidManifestData);                String str = sa.getNonConfigurationString(                        com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);                if (str != null) {                    try {                        outInfo.addDataType(str);                    } catch (IntentFilter.MalformedMimeTypeException e) {                        outError[0] = e.toString();                        sa.recycle();                        return false;                    }                }                str = sa.getNonConfigurationString(                        com.android.internal.R.styleable.AndroidManifestData_scheme, 0);                if (str != null) {                    outInfo.addDataScheme(str);                }                String host = sa.getNonConfigurationString(                        com.android.internal.R.styleable.AndroidManifestData_host, 0);                String port = sa.getNonConfigurationString(                        com.android.internal.R.styleable.AndroidManifestData_port, 0);                if (host != null) {                    outInfo.addDataAuthority(host, port);                }                str = sa.getNonConfigurationString(                        com.android.internal.R.styleable.AndroidManifestData_path, 0);                if (str != null) {                    outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);                }                str = sa.getNonConfigurationString(                        com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);                if (str != null) {                    outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);                }                str = sa.getNonConfigurationString(                        com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);                if (str != null) {                    outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);                }                sa.recycle();                XmlUtils.skipCurrentTag(parser);            } else if (!RIGID_PARSER) {                Log.w(TAG, "Unknown element under <intent-filter>: "                        + parser.getName() + " at " + mArchiveSourcePath + " "                        + parser.getPositionDescription());                XmlUtils.skipCurrentTag(parser);            } else {                outError[0] = "Bad element under <intent-filter>: " + parser.getName();                return false;            }        }        outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);        if (false) {            String cats = "";            Iterator<String> it = outInfo.categoriesIterator();            while (it != null && it.hasNext()) {                cats += " " + it.next();            }            System.out.println("Intent d=" +                    outInfo.hasDefault + ", cat=" + cats);        }        return true;    }


更多相关文章

  1. Android(安卓)Gallery控件使用方法详解
  2. 源码学习总结《1》Android(安卓)系统启动流程
  3. Android(安卓)应用程序开关GPS
  4. android 实现listview动态加载列表项
  5. 调用onSaveInstanceState(Bundle)保存数据的注意事项
  6. Android(安卓)IntentService源码分析
  7. Adapter 要从源头开始适配
  8. Android(安卓)Framework 深入浅出-HAL, Binder, View System 与
  9. Android读写XML(中)

随机推荐

  1. Android学习——android:cacheColorHint=
  2. android manifest.xml 标签汇总
  3. 一个提供Android各历史版本在线源码的网
  4. Android:This text field does not speci
  5. Android教程之Android(安卓)SDK1.5模拟器
  6. Android高手进阶教程(七)之----Android(
  7. android 定时器的实现 (转)
  8. ImageView的android:maxHeight,android:mi
  9. Android基础概念
  10. Android(安卓)众多的布局属性详解