Android安装apk应用的时候出现INSTALL_FAILED_SHARED_USER_INCOMPATIBLE如何解决
Posted 用户_147
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android安装apk应用的时候出现INSTALL_FAILED_SHARED_USER_INCOMPATIBLE如何解决相关的知识,希望对你有一定的参考价值。
前言
如果你安装app时出现INSTALL_FAILED_SHARED_USER_INCOMPATIBLE
的错误
那么你大概率在manifest
文件中增加了android:sharedUserId="android.uid.system"
,此属性的作用是将普通app提升为系统app(这样就能使用一些系统权限,例如在应用外显示弹窗)
针对此问题,网上大部分讨论的是去除android:sharedUserId
这个属性,但是如果你的目的就是想使用此属性,并且能安装上去,那么请尝试下面的解决方法。
注意:使用android:sharedUserId
的同时,还需要android系统的key
,不同的系统的key
都是不一样的,一般只提供给专门的开发人员,即使你能百度到一个,也无法在其他android设备上使用。所以如果你想在Android Studio自带的模拟器或者自己手机上使用此属性,请放弃。
1. 对android设备进行root
首先考虑app是否有root权限,运行adb root
和adb remount
命令,某些情况下运行adb remount
后还要重启android系统root才能生效。
2. 卸载旧app再运行
尝试卸载旧的app,然后重新运行程序,大概率就能正常运行。如果定制的android系统上卸载功能找不到,可以使用adb uninstall <apk的包名>
的形式来卸载。
3. 手动放置apk
如果你的app已经是系统应用,且无法直接卸载,考虑去系统路径下(例如:system/app/
)找到自己的应用,然后通过替换安装包的形式来完成安装(替换完成后需要重新系统才能生效)。
注意:有些系统应用被错误删除后可能会影响正常使用,例如:Launcher
或SystemUI
,所以更改系统apk时建议先对旧的安装包进行备份,使用adb pull <手机文件路径> <本机路径>
的命令可以将android中的文件保存到电脑上。
Android应用程序安装过程解析(源码解析)
Android应用程序安装过程解析
1.程序安装的4大步骤
(1) 拷贝apk文件到指定目录
在Android系统中,apk安装文件是会被保存起来的,默认情况下,用户安装的apk首先会被拷贝到 /data/app 目录下。
/data/app目录是用户有权限访问的目录,在安装apk的时候会自动选择该目录存放用户安装的文件,而系统出厂的apk文件则被放到了 /system 分区下,包括 /system/app,/system/vendor/app,以及 /system/priv-app 等等,该分区只有Root权限的用户才能访问,这也就是为什么在没有Root手机之前,我们无法删除系统出厂的app的原因了。
(2) 解压apk,拷贝文件,创建应用的数据目录
为了加快app的启动速度,apk在安装的时候,会首先将app的可执行文件(dex)拷贝到 /data/dalvik-cache 目录,缓存起来。
然后,在/data/data/目录下创建应用程序的数据目录(以应用的包名命名),存放应用的相关数据,如数据库、xml文件、cache、二进制的so动态库等等。
(3) 解析apk的AndroidManifinest.xml文件
Android系统中,也有一个类似注册表的东西,用来记录当前所有安装的应用的基本信息,每次系统安装或者卸载了任何apk文件,都会更新这个文件。这个文件位于如下目录:
/data/system/packages.xml
系统在安装apk的过程中,会解析apk的AndroidManifinest.xml文件,提取出这个apk的重要信息写入到packages.xml文件中,这些信息包括:权限、应用包名、APK的安装位置、版本、userID等等。
由此,我们就知道了为啥一些应用市场和软件管理类的app能够很清楚地知道当前手机所安装的所有的app,以及这些app的详细信息了。
另外一件事就是Linux的用户Id和用户组Id,以便他可以获得合适的运行权限。
以上这些都是由PackageServiceManager完成的,下面我们会重点介绍PackageServiceManager。
(4) 显示快捷方式
这些应用程序只是相当于在PackageManagerService服务注册好了,如果我们想要在Android桌面上看到这些应用程序,还需要有一个Home应用程序,负责从PackageManagerService服务中把这些安装好的应用程序取出来,并以友好的方式在桌面上展现出来,例如以快捷图标的形式。在Android系统中,负责把系统中已经安装的应用程序在桌面中展现出来的Home应用程序就是Launcher了
2.PackageManagerService的启动过程
Android系统在启动的过程中,会启动一个应用程序管理服务PackageManagerService,这个服务负责扫描系统中特定的目录,找到里面的应用程序文件,即以Apk为后缀的文件,然后对这些文件进解析,得到应用程序的相关信息。应用程序管理服务PackageManagerService安装应用程序的过程,其实就是解析析应用程序配置文件AndroidManifest.xml的过程,并从里面得到得到应用程序的相关信息,例如得到应用程序的组件Activity、Service、Broadcast Receiver和Content Provider等信息,有了这些信息后,通过ActivityManagerService这个服务,我们就可以在系统中正常地使用这些应用程序了。应用程序管理服务PackageManagerService是系统启动的时候由SystemServer组件启动的,启后它就会执行应用程序安装的过程,因此,本文将从SystemServer启动PackageManagerService服务的过程开始分析系统中的应用程序安装的过程。
下面我们具体分析每一个步骤。
Step 1. SystemServer.main
这个函数定义在frameworks/base/services/Java/com/android/server/SystemServer.java文件中:
public class SystemServer
......
native public static void init1(String[] args);
......
public static void main(String[] args)
......
init1(args);
......
......
SystemServer组件是由Zygote进程负责启动的,启动的时候就会调用它的main函数,这个函数主要调用了JNI方法init1来做一些系统初始化的工作。
Step 2. SystemServer.init1
这个函数是一个JNI方法,实现在 frameworks/base/services/jni/com_android_server_SystemServer.cpp文件中:
namespace android
extern "C" int system_init();
static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz)
system_init();
/*
* JNI registration.
*/
static JNINativeMethod gMethods[] =
/* name, signature, funcPtr */
"init1", "([Ljava/lang/String;)V", (void*) android_server_SystemServer_init1 ,
;
int register_android_server_SystemServer(JNIEnv* env)
return jniRegisterNativeMethods(env, "com/android/server/SystemServer",
gMethods, NELEM(gMethods));
; // namespace android
这个函数很简单,只是调用了system_init函数来进一步执行操作。
Step 3. libsystem_server.system_init
函数system_init实现在libsystem_server库中,源代码位于frameworks/base/cmds/system_server/library/system_init.cpp文件中:
extern "C" status_t system_init()
LOGI("Entered system_init()");
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
LOGI("ServiceManager: %p\\n", sm.get());
sp<GrimReaper> grim = new GrimReaper();
sm->asBinder()->linkToDeath(grim, grim.get(), 0);
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsurfaceflinger", propBuf, "1");
if (strcmp(propBuf, "1") == 0)
// Start the SurfaceFlinger
SurfaceFlinger::instantiate();
// Start the sensor service
SensorService::instantiate();
// On the simulator, audioflinger et al don't get started the
// same way as on the device, and we need to start them here
if (!proc->supportsProcesses())
// Start the AudioFlinger
AudioFlinger::instantiate();
// Start the media playback service
MediaPlayerService::instantiate();
// Start the camera service
CameraService::instantiate();
// Start the audio policy service
AudioPolicyService::instantiate();
// And now start the Android runtime. We have to do this bit
// of nastiness because the Android runtime initialization requires
// some of the core system services to already be started.
// All other servers should just start the Android runtime at
// the beginning of their processes's main(), before calling
// the init function.
LOGI("System server: starting Android runtime.\\n");
AndroidRuntime* runtime = AndroidRuntime::getRuntime();
LOGI("System server: starting Android services.\\n");
runtime->callStatic("com/android/server/SystemServer", "init2");
// If running in our own process, just go into the thread
// pool. Otherwise, call the initialization finished
// func to let this process continue its initilization.
if (proc->supportsProcesses())
LOGI("System server: entering thread pool.\\n");
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
LOGI("System server: exiting thread pool.\\n");
return NO_ERROR;
这个函数首先会初始化SurfaceFlinger、SensorService、AudioFlinger、MediaPlayerService、CameraService和AudioPolicyService这几个服务,然后就通过系统全局唯一的AndroidRuntime实例变量runtime的callStatic来调用SystemServer的init2函数了。关于这个AndroidRuntime实例变量runtime的相关资料,可能参考前面一篇文章Android应用程序进程启动过程的源代码分析一文。
Step 4. AndroidRuntime.callStatic
这个函数定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中:
/*
* Call a static Java Programming Language function that takes no arguments and returns void.
*/
status_t AndroidRuntime::callStatic(const char* className, const char* methodName)
JNIEnv* env;
jclass clazz;
jmethodID methodId;
env = getJNIEnv();
if (env == NULL)
return UNKNOWN_ERROR;
clazz = findClass(env, className);
if (clazz == NULL)
LOGE("ERROR: could not find class '%s'\\n", className);
return UNKNOWN_ERROR;
methodId = env->GetStaticMethodID(clazz, methodName, "()V");
if (methodId == NULL)
LOGE("ERROR: could not find method %s.%s\\n", className, methodName);
return UNKNOWN_ERROR;
env->CallStaticVoidMethod(clazz, methodId);
return NO_ERROR;
这个函数调用由参数className指定的java类的静态成员函数,这个静态成员函数是由参数methodName指定的。上面传进来的参数className的值为”com/android/server/SystemServer”,而参数methodName的值为”init2”,因此,接下来就会调用SystemServer类的init2函数了。
Step 5. SystemServer.init2
这个函数定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中:
public class SystemServer
......
public static final void init2()
Slog.i(TAG, "Entered the Android system server!");
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
这个函数创建了一个ServerThread线程,PackageManagerService服务就是这个线程中启动的了。这里调用了ServerThread实例thr的start函数之后,下面就会执行这个实例的run函数了。
Step 6. ServerThread.run
这个函数定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中:
class ServerThread extends Thread
......
@Override
public void run()
......
IPackageManager pm = null;
......
// Critical services...
try
......
Slog.i(TAG, "Package Manager");
pm = PackageManagerService.main(context,
factoryTest != SystemServer.FACTORY_TEST_OFF);
......
catch (RuntimeException e)
Slog.e("System", "Failure starting core service", e);
......
......
这个函数除了启动PackageManagerService服务之外,还启动了其它很多的服务,例如在前面学习Activity和Service的几篇文章中经常看到的ActivityManagerService服务,有兴趣的读者可以自己研究一下。
Step 7. PackageManagerService.main
这个函数定义在frameworks/base/services/java/com/android/server/PackageManagerService.java文件中:
class PackageManagerService extends IPackageManager.Stub
......
public static final IPackageManager main(Context context, boolean factoryTest)
PackageManagerService m = new PackageManagerService(context, factoryTest);
ServiceManager.addService("package", m);
return m;
......
3.常见的4种安装场景
1.系统应用安装――开机时完成,没有安装界面
2.网络下载应用安装――通过market应用完成,没有安装界面
3.ADB工具安装――没有安装界面。
4.第三方应用安装――通过SD卡里的APK文件安装,有安装界面,由 packageinstaller.apk应用处理安装及卸载过程的界面。
安装过程:
复制APK安装包到data/app目录下,解压并扫描安装包,把dex文件(Dalvik字节码)保存到dalvik-cache目录,并data/data目录下创建对应的应用数据目录。
卸载过程:
删除安装过程中在上述三个目录下创建的文件及目录。
(1)系统应用安装――开机时完成,没有安装界面
PackageManagerService处理各种应用的安装,卸载,管理等工作,开机时由systemServer启动此服务
在创建这个PackageManagerService服务实例时,会在PackageManagerService类的构造函数中开始执行安装应用程序的过程:
PackageManagerService核心代码
class PackageManagerService extends IPackageManager.Stub
......
public PackageManagerService(Context context, boolean factoryTest)
......
mSetting = new Setting();
synchronized (mInstallLock)
synchronized (mPackages)
......
File dataDir = Environment.getDataDirectory();
mAppDataDir = new File(dataDir, "data");
mSecureAppDataDir = new File(dataDir, "secure/data");
mRestoredSetting = mASetting.readLP();
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
......
mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
mDalvikCacheDir = new File(dataDir, "dalvik-cache");
......
// Find base frameworks (resource packages without code).
mFrameworkInstallObserver = new AppDirObserver(
mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
mFrameworkInstallObserver.startWatching();
scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanMode | SCAN_NO_DEX, 0);
// Collect all system packages.
mSystemAppDir = new File(Environment.getRootDirectory(), "app");
mSystemInstallObserver = new AppDirObserver(
mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
mSystemInstallObserver.startWatching();
scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
// Collect all vendor packages.
mVendorAppDir = new File("/vendor/app");
mVendorInstallObserver = new AppDirObserver(
mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
mVendorInstallObserver.startWatching();
scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
mAppInstallObserver = new AppDirObserver(
mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
mAppInstallObserver.startWatching();
scanDirLI(mAppInstallDir, 0, scanMode, 0);
mDrmAppInstallObserver = new AppDirObserver(
mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
mDrmAppInstallObserver.startWatching();
scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
scanMode, 0);
......
final boolean regrantPermissions = mSetting.mInternalSDKplatform != mSdkVersion;
updatePermissionsLP(null,null,true,rregrantPermissions .regrantPermissions );
msetting.writeLP();
......
这里会调用scanDirLI函数来扫描移动设备上的下面这五个目录中的Apk文件
/system/framework
/system/app
/vendor/app
/data/app
/data/app-private
由于Android每次启动的时候都需要安装一次信息,但是有些信息是保持不变的,例如Linux用户组Id,PackageManagerService 每次安装程序之后,都会把这些程序的信息保存下来,以便下次使用,
恢复上一次程序的安装信息是通过PackageManagerService 的成员变量mSetting的readLP()来实现的,恢复信息之后就开始扫描和安装app了。
扫描安装app
PackageManagerService.scanDirLI
这个函数定义在frameworks/base/services/java/com/android/server/PackageManagerService.java文件中:
class PackageManagerService extends IPackageManager.Stub
......
private void scanDirLI(File dir, int flags, int scanMode, long currentTime)
String[] files = dir.list();
......
int i;
for (i=0; i<files.length; i++)
File file = new File(dir, files[i]);
if (!isPackageFilename(files[i]))
// Ignore entries which are not apk's
continue;
PackageParser.Package pkg = scanPackageLI(file,
flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime);
// Don't mess around with apps in system partition.
if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK)
// Delete the apk
Slog.w(TAG, "Cleaning up failed install of " + file);
file.delete();
......
对于目录中的每一个文件,如果是以后Apk作为后缀名,那么就调用scanPackageLI函数来对它进行解析和安装。
PackageManagerService.scanPackageLI
这个函数定义在frameworks/base/services/java/com/android/server/PackageManagerService.java文件中:
class PackageManagerService extends IPackageManager.Stub
......
private PackageParser.Package scanPackageLI(File scanFile,
int parseFlags, int scanMode, long currentTime)
......
String scanPath = scanFile.getPath();
parseFlags |= mDefParseFlags;
PackageParser pp = new PackageParser(scanPath);
......
final PackageParser.Package pkg = pp.parsePackage(scanFile,
scanPath, mMetrics, parseFlags);
......
return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE, currentTime);
......
这个函数首先会为这个Apk文件创建一个PackageParser实例,接着调用这个实例的parsePackage函数来对这个Apk文件进行解析。这个函数最后还会调用另外一个版本的scanPackageLI函数把来解析后得到的应用程序信息保存在PackageManagerService中。
PackageParser.parsePackage
这个函数定义在frameworks/base/core/java/android/content/pm/PackageParser.java文件中:
public class PackageParser
......
public Package parsePackage(File sourceFile, String destCodePath,
DisplayMetrics metrics, int flags)
......
mArchiveSourcePath = sourceFile.getPath();
......
XmlResourceParser parser = null;
AssetManager assmgr = null;
boolean assetError = true;
try
assmgr = new AssetManager();
int cookie = assmgr.addAssetPath(mArchiveSourcePath);
if(cookie != 0)
parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml");
assetError = false;
else
......
catch (Exception e)
......
......
String[] errorText = new String[1];
Package pkg = null;
Exception errorException = null;
try
// XXXX todo: need to figure out correct configuration.
Resources res = new Resources(assmgr, metrics, null);
pkg = parsePackage(res, parser, flags, errorText);
catch (Exception e)
......
......
parser.close();
assmgr.close();
// Set code and resource paths
pkg.mPath = destCodePath;
pkg.mScanPath = mArchiveSourcePath;
//pkg.applicationInfo.sourceDir = destCodePath;
//pkg.applicationInfo.publicSourceDir = destRes;
pkg.mSignatures = null;
return pkg;
......
每一个Apk文件都是一个归档文件,它里面包含了Android应用程序的配置文件AndroidManifest.xml,这里主要就是要对这个配置文件就行解析了,从Apk归档文件中得到这个配置文件后,就调用另一外版本的parsePackage函数对这个应用程序进行解析了:
public class PackageParser
......
private Package parsePackage(
Resources res, XmlResourceParser parser, int flags, String[] outError)
throws XmlPullParserException, IOException
......
String pkgName = parsePackageName(parser, attrs, flags, outError);
......
final Package pkg = new Package(pkgName);
......
int type;
......
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifest);
......
while ((type=parser.next()) != parser.END_DOCUMENT
&& (type != parser.END_TAG || parser.getDepth() > outerDepth))
if (type == parser.END_TAG || type == parser.TEXT)
continue;
String tagName = parser.getName();
if (tagName.equals("application"))
......
if (!parseApplication(pkg, res, parser, attrs, flags, outError))
return null;
else if (tagName.equals("permission-group"))
......
else if (tagName.equals("permission"))
......
else if (tagName.equals("permission-tree"))
......
else if (tagName.equals("uses-permission"))
......
else if (tagName.equals("uses-configuration"))
......
else if (tagName.equals("uses-feature"))
......
else if (tagName.equals("uses-sdk"))
......
else if (tagName.equals("supports-screens"))
......
else if (tagName.equals("protected-broadcast"))
......
else if (tagName.equals("instrumentation"))
......
else if (tagName.equals("original-package"))
......
else if (tagName.equals("adopt-permissions"))
......
else if (tagName.equals("uses-gl-texture"))
......
else if (tagName.equals("compatible-screens"))
......
else if (tagName.equals("eat-comment"))
......
else if (RIGID_PARSER)
......
else
......
......
return pkg;
......
这里就是对AndroidManifest.xml文件中的各个标签进行解析了,各个标签的含义可以参考官方文档http://developer.android.com/guide/topics/manifest/manifest-intro.html,这里我们只简单看一下application标签的解析,这是通过调用parseApplication函数来进行的。
PackageParser.parseApplication
这个函数定义在frameworks/base/core/java/android/content/pm/PackageParser.java文件中:
public class PackageParser
......
private boolean parseApplication(Package owner, Resources res,
XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
throws XmlPullParserException, IOException
final ApplicationInfo ai = owner.applicationInfo;
final String pkgName = owner.applicationInfo.packageName;
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifestApplication);
......
int type;
while ((type=parser.next()) != parser.END_DOCUMENT
&& (type != parser.END_TAG || parser.getDepth() > innerDepth))
if (type == parser.END_TAG || type == parser.TEXT)
continue;
String tagName = parser.getName();
if (tagName.equals("activity"))
Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false);
......
owner.activities.add(a);
else if (tagName.equals("receiver"))
Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true);
......
owner.receivers.add(a);
else if (tagName.equals("service"))
Service s = parseService(owner, res, parser, attrs, flags, outError);
......
owner.services.add(s);
else if (tagName.equals("provider"))
Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
......
owner.providers.add(p);
else if (tagName.equals("activity-alias"))
Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);
......
owner.activities.add(a);
else if (parser.getName().equals("meta-data"))
......
else if (tagName.equals("uses-library"))
......
else if (tagName.equals("uses-package"))
......
else
......
return true;
......
这里就是对AndroidManifest.xml文件中的application标签进行解析了,我们常用到的标签就有activity、service、receiver和provider,各个标签的含义可以参考官方文档http://developer.android.com/guide/topics/manifest/manifest-intro.html。这里解析完成后,一层层返回到Step 9中,调用另一个版本的scanPackageLI函数把来解析后得到的应用程序信息保存下来。
PackageManagerService.scanPackageLI
这个函数定义在frameworks/base/services/java/com/android/server/PackageManagerService.java文件中:
class PackageManagerService extends IPackageManager.Stub
......
// Keys are String (package name), values are Package. This also serves
// as the lock for the global state. Methods that must be called with
// this lock held have the prefix "LP".
final HashMap<String, PackageParser.Package> mPackages =
new HashMap<String, PackageParser.Package>();
......
// All available activities, for your resolving pleasure.
final ActivityIntentResolver mActivities =
new ActivityIntentResolver();
// All available receivers, for your resolving pleasure.
final ActivityIntentResolver mReceivers =
new ActivityIntentResolver();
// All available services, for your resolving pleasure.
final ServiceIntentResolver mServices = new ServiceIntentResolver();
// Keys are String (provider class name), values are Provider.
final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
new HashMap<ComponentName, PackageParser.Provider>();
......
private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
int parseFlags, int scanMode, long currentTime)
......
synchronized (mPackages)
......
// Add the new setting to mPackages
mPackages.put(pkg.applicationInfo.packageName, pkg);
......
int N = pkg.providers.size();
int i;
for (i=0; i<N; i++)
PackageParser.Provider p = pkg.providers.get(i);
p.info.processName = fixProcessName(pkg.applicationInfo.processName,
p.info.processName, pkg.applicationInfo.uid);
mProvidersByComponent.put(new ComponentName(p.info.packageName,
p.info.name), p);
......
N = pkg.services.size();
for (i=0; i<N; i++)
PackageParser.Service s = pkg.services.get(i);
s.info.processName = fixProcessName(pkg.applicationInfo.processName,
s.info.processName, pkg.applicationInfo.uid);
mServices.addService(s);
......
N = pkg.receivers.size();
r = null;
for (i=0; i<N; i++)
PackageParser.Activity a = pkg.receivers.get(i);
a.info.processName = fixProcessName(pkg.applicationInfo.processName,
a.info.processName, pkg.applicationInfo.uid);
mReceivers.addActivity(a, "receiver");
......
N = pkg.activities.size();
for (i=0; i<N; i++)
PackageParser.Activity a = pkg.activities.get(i);
a.info.processName = fixProcessName(pkg.applicationInfo.processName,
a.info.processName, pkg.applicationInfo.uid);
mActivities.addActivity(a, "activity");
......
......
......
return pkg;
......
这个函数主要就是把前面解析应用程序得到的package、provider、service、receiver和activity等信息保存在PackageManagerService服务中了。
PackageManagerService的作用总结:
1)从apk, xml中载入pacakge信息, 存储到内部成员变量中, 用于后面的查找. 关键的方法是scanPackageLI().
2)各种查询操作, 包括query Intent操作.
3)install package和delete package的操作. 还有后面的关键方法是installPackageLI().
后面重点介绍installPackageLI,后面的额方式本质都会调用它。
(2)从网络上下载应用:
下载完成后,会自动调用Packagemanager的安装方法installPackage()
public void installPackage(
final Uri packageURI, final IPackageInstallObserver observer, final int flags,
final String installerPackageName)
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.INSTALL_PACKAGES, null);
Message msg = mHandler.obtainMessage(INIT_COPY);
msg.obj = new InstallParams(packageURI, observer, flags,
installerPackageName);
mHandler.sendMessage(msg);
通过PackageHandler的实例mhandler.sendMessage(msg)把信息发给继承Handler的类HandleMessage()方法
class PackageHandler extends Handler
*****************省略若干********************
public void handleMessage(Message msg)
try
doHandleMessage(msg);
finally
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
******************省略若干**********************
把信息发给doHandleMessage()方法,方法中用switch()语句进行判定传来Message
void doHandleMessage(Message msg)
switch (msg.what)
case INIT_COPY:
if (DEBUG_SD_INSTALL) Log.i(TAG, "init_copy");
HandlerParams params = (HandlerParams) msg.obj;
int idx = mPendingInstalls.size();
if (DEBUG_SD_INSTALL) Log.i(TAG, "idx=" + idx);
// If a bind was already initiated we dont really
// need to do anything. The pending install
// will be processed later on.
if (!mBound)
// If this is the only one pending we might
// have to bind to the service again.
if (!connectToService())
Slog.e(TAG, "Failed to bind to media container service");
params.serviceError();
return;
else
// Once we bind to the service, the first
// pending request will be processed.
mPendingInstalls.add(idx, params);
else
mPendingInstalls.add(idx, params);
// Already bound to the service. Just make
// sure we trigger off processing the first request.
if (idx == 0)
mHandler.sendEmptyMessage(MCS_BOUND);
break;
case MCS_BOUND:
if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_bound");
if (msg.obj != null)
mContainerService = (IMediaContainerService) msg.obj;
if (mContainerService == null)
// Something seriously wrong. Bail out
Slog.e(TAG, "Cannot bind to media container service");
for (HandlerParams params : mPendingInstalls)
mPendingInstalls.remove(0);
// Indicate service bind error
params.serviceError();
mPendingInstalls.clear();
else if (mPendingInstalls.size() > 0)
HandlerParams params = mPendingInstalls.get(0);
if (params != null)
params.startCopy();
else
// Should never happen ideally.
Slog.w(TAG, "Empty queue");
break;
****************省略若干**********************
public final boolean sendMessage (Message msg)
public final boolean sendEmptyMessage (int what)
两者参数有别。
然后调用抽象类HandlerParams中的一个startCopy()方法
abstract class HandlerParams
final void startCopy()
*****若干if语句判定否这打回handler消息*
handleReturnCode();
handleReturnCode()复写了两次其中有一次是删除时要调用的,只列出安装调用的一个方法
@Override
void handleReturnCode()
// If mArgs is null, then MCS couldn't be reached. When it
// reconnects, it will try again to install. At that point, this
// will succeed.
if (mArgs != null)
processPendingInstall(mArgs, mRet);
这时可以清楚的看见 processPendingInstall()被调用。
其中run()方法如下
run()
synchronized (mInstallLock)
************省略*****************
installPackageLI(args, true, res);
instaPacakgeLI()args,res参数分析
//InstallArgs 是在PackageService定义的static abstract class InstallArgs 静态抽象类。
static abstract class InstallArgs
*********************************************************************
其中定义了flag标志,packageURL,创建文件,拷贝apk,修改包名称,
还有一些删除文件的清理,释放存储函数。
*********************************************************************
class PackageInstalledInfo
String name;
int uid;
PackageParser.Package pkg;
int returnCode;
PackageRemovedInfo removedInfo;
-----------------------------------------------------------------------------------------
[java] view plain copy
private void installPackageLI(InstallArgs args,
boolean newInstall, PackageInstalledInfo res)
int pFlags = args.flags;
String installerPackageName = args.installerPackageName;
File tmpPackageFile = new File(args.getCodePath());
boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
boolean replace = false;
int scanMode = (onSd ? 0 : SCAN_MONITOR) | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
| (newInstall ? SCAN_NEW_INSTALL : 0);
// Result object to be returned
res.returnCode以上是关于Android安装apk应用的时候出现INSTALL_FAILED_SHARED_USER_INCOMPATIBLE如何解决的主要内容,如果未能解决你的问题,请参考以下文章
Ionic Android 应用程序可以工作,但安装时不能使用 apk
一台PC连接多个Android手机,使用adb命令可以给这多台手机同时安装一个apk,这样可以实现吗?怎么写?
android studio 导出apk的时候出现这个问题。build type下拉是空。不是中文路径问题,改过也是这样