在網上找了很久惟一launcher的實現方式,發現都是一同一我的寫的,並且並無實現這個功能,由於按照這個方式去作的話,當你按下HOME鍵仍是出現了選擇launcher的對話框,而後本身研究了一天,找到了最直接有效的並且是最簡單的方法實現全局惟一launcher的功能:html
修改frameworks\base\core\Java\Android\content\pm\PackageParser.java,在parseIntent這個私有方法,由於APK在安裝的時候會經過這個方法解析Manifest清單文件,而後將每一個Activity的intent-filter保存在內存中,因此修改這個方法就至關於修改了內存的應用註冊表的信息,也就是偷換概念的作法,等因而在安裝的時候就把問題解決了,扼殺在萌芽狀態:java
修改部分爲:node
這裏xxx隨便你輸入,例如你在你本身的launcher的Manifest的Activity裏Intent-filter里加入:
[html] view plain copy
<category android:name="android.intent.category.HOME.xxx" /> android
那麼在代碼裏修改的地方的xxx就替換成你本身起的名字app
原理就是安裝每一個APK的時候 只要是launcher ,就把category是HOME的值改爲x,只要是你的launcher就把category的值改爲HOME,那麼全局就只有你一個launcher了.net
這裏是修改的部分:
[java] view plain copy
/*************************************************************************************/
if(Intent.CATEGORY_HOME.equals(value)) {
value = "x";
} else if((Intent.CATEGORY_HOME + ".xxx").equals(value)) {
value = Intent.CATEGORY_HOME;
}
/*************************************************************************************/ orm
使用這種方法修改時必須確保你的launcher被安裝了或者放在了syste/app下了且Manifest的Activity裏的intent-filter爲android.category.HOME.xxxhtm
具體的原理請參考個人另一篇博客:http://blog.csdn.net/zhbinary/article/details/7353739blog
修改frameworks\base\core\java\android\content\pm\PackageParser.java裏的parseIntent方法
[java] view plain copy
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;
}ip