当前位置: 首页 > news >正文

椒江建设网保障性阳光工程网站广告联盟代理平台

椒江建设网保障性阳光工程网站,广告联盟代理平台,wordpress使用百度统计,商城购物网站开发意义和你一起终身学习#xff0c;这里是程序员Android 经典好文推荐#xff0c;通过阅读本文#xff0c;您将收获以下知识点: 本篇文章主要介绍 Android 开发中的部分知识点#xff0c;通过阅读本篇文章#xff0c;您将收获以下内容: 一、前言二、PackageInstaller介绍三、App… 和你一起终身学习这里是程序员Android 经典好文推荐通过阅读本文您将收获以下知识点: 本篇文章主要介绍 Android 开发中的部分知识点通过阅读本篇文章您将收获以下内容: 一、前言二、PackageInstaller介绍三、App安装过程中涉及类四、App安装流程分析五、总结六、参考文献 一、前言 首先本文不是做PackageManagerService学习总结PackageManagerService这货有1万2千多行代码学习起来颇费劲并且这货功能强大本文只会总结其中一个小小的功能为何要做这个总结呢说来话长鄙人菜鸟一枚接到一个安装应用过程中重启的问题原因找到但不知如何解决无奈只有硬着头皮学习了下这部分内容OK废话不多说接下来直接上干货如果文中有问题或有质疑的地方可以直接修改不胜感激。 二、PackageInstaller介绍 PackageInstaller是个神马东西呢我们知道安装app有很多中方式诸如adb install,应用助手豌豆荚,开机安装开机启动时下载到手机存储后点击安装。PackageInstaller这哥就是给手动安装app提供一个界面的apk。当我们点安装应用时会启动这个应用来显示安装过程安装的事情并不是他在做正在安装是由PackageManagerService来完成当然幕后英雄确是Installer。代码位置packages/apps/PackageInstaller疑问【以下有几个问题如果亲都知道的话那么可以不用再看本文啦】如何使用PackageInstaller来安装应用应用首选安装位置是在何时确定的是在设置里设置的还是在app中定义的还是PackageManagerService这货说了算安装应用过程中哪些服务和类会插手这件事安装过程中首先会生成一个.tmp临时文件这个文件在何时被rename为apk的应用都有uid这个uid是在什么时候被赋值的packages.xml and packages.list有什么用安装app主要做了哪些事 三、App安装过程中涉及类 先来盘类图看看如对PackageManagerService不熟悉的话先看后面的流程看完再来看这个类图 安装过程时会插手的主要类如下 packages/apps/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java packages/apps/PackageInstaller/src/com/android/packageinstaller/InstallAppProgress.java frameworks/base /core/java/android/app/ApplicationPackageManager.java frameworks/base /core/java/android/content/pm/PackageParser.java frameworks/base /core/java/android/content/res/AssetManager.java frameworks/base /packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java frameworks/base /services/java/com/android/server/pm/Installer.java frameworks/base /services/java/com/android/server/pm/PackageManagerService.java frameworks/base /services/java/com/android/server/pm/Settings.java 简单说明这些类作用 PackageInstallerActivity.java在文件管理器里点击apk后就会调用该类主要用于显示要安装的apk的一些权限信息InstallAppProgress.java当看完所有权限后点安装后就会调用该类用于显示安装进度这时候- PackageManagerService 就在默默的安装应用ApplicationPackageManager.java这是类是PackageManager的儿子我们使用mContext.getPackageManager得到的其实就是ApplicationPackageManager的对象它爹PackageManager是个抽象类对外的方法都定义在里面PackageParser.java解析app主要解析apk中的AndroidManifest.xml解析里面的四大组件以及权限信息放入内存里最后写到packages.xml和package.list/data/system下中AssetManager.java把AndroidManifest.xml从app中拿出来给PackageParser.java去解析DefaultContainerService.java这个服务用于检查存储状态得到合适的安装位置Installer.javaPackageManagerService调用它去执行安装他会把PackageManagerService传过来的数据封装成命令然后让底层的Installer去执行PackageManagerService.java管理app的大神安装、移动、卸载、查询等都由他管 四、App安装流程分析 先来个时序图--安装成功的时序图。点击两次可看大图 安装流程 流程分析当然对着代码看上面的时序图也很明了1.当点击文件管理器中的apk时会调用FolderFragment的openFile方法该方法里会将应用信息传给PackageInstallerActivity并启动PackageInstaller 代码位置vendor/qcom/proprietary/qrdplus/FileExplorer/src/com/android/qrdfileexplorer/FolderFragment.javaprivate void openFile(File f) {final Uri fileUri Uri.fromFile(f);final Intent intent new Intent();intent.setAction(android.content.Intent.ACTION_VIEW);intent.putExtra(Intent.EXTRA_TITLE, f.getName());intent.putExtra(EXTRA_ALL_VIDEO_FOLDER, true);Uri contentUri null;String type getMIMEType(f);......if (contentUri ! null) {intent.setDataAndType(contentUri, type);} else {intent.setDataAndType(fileUri, type);}try {startActivitySafely(intent);} ......} 2.PackageInstaller启动过后会检查是否开启未知来源未开启就需要先进入设置设置后方可继续安装之后会依次调用initiateInstall()-startInstallConfirm();在initiateInstall中会检查是否已经安装过是否是系统应用等调用startInstallConfirm去初始化界面显示权限信息当点击安装按钮时启动安装切换界面到InstallAppProgress 代码位置packages/apps/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.javaOverrideprotected void onCreate(Bundle icicle) {......mPm getPackageManager();boolean requestFromUnknownSource isInstallRequestFromUnknownSource(intent);......initiateInstall();}private void initiateInstall() {String pkgName mPkgInfo.packageName;String[] oldName mPm.canonicalToCurrentPackageNames(new String[] { pkgName });if (oldName ! null oldName.length 0 oldName[0] ! null) {pkgName oldName[0];mPkgInfo.packageName pkgName;mPkgInfo.applicationInfo.packageName pkgName;}// Check if package is already installed. display confirmation dialog if replacing pkgtry {// This is a little convoluted because we want to get all uninstalled// apps, but this may include apps with just data, and if it is just// data we still want to count it as installed.mAppInfo mPm.getApplicationInfo(pkgName,PackageManager.GET_UNINSTALLED_PACKAGES);if ((mAppInfo.flagsApplicationInfo.FLAG_INSTALLED) 0) {mAppInfo null;}} catch (NameNotFoundException e) {mAppInfo null;}mInstallFlowAnalytics.setReplace(mAppInfo ! null);mInstallFlowAnalytics.setSystemApp((mAppInfo ! null) ((mAppInfo.flags ApplicationInfo.FLAG_SYSTEM) ! 0));startInstallConfirm();} 3.在InstallAppProgress中会调用initView去初始化界面并调用ApplicationPackageManager的installPackageWithVerificationAndEncryption方法来安装 代码位置packages/apps/PackageInstaller/src/com/android/packageinstaller/InstallAppProgress.javaOverridepublic void onCreate(Bundle icicle) {......initView();}public void initView() {......if (package.equals(mPackageURI.getScheme())) {try {pm.installExistingPackage(mAppInfo.packageName);observer.packageInstalled(mAppInfo.packageName,PackageManager.INSTALL_SUCCEEDED);} catch (PackageManager.NameNotFoundException e) {observer.packageInstalled(mAppInfo.packageName,PackageManager.INSTALL_FAILED_INVALID_APK);}} else {pm.installPackageWithVerificationAndEncryption(mPackageURI, observer, installFlags,installerPackageName, verificationParams, null);}} 4.ApplicationPackageManager的installPackageWithVerificationAndEncryption里也是调用PMS的installPackageWithVerificationAndEncryption方法 代码位置frameworks/base/core/java/android/app/ApplicationPackageManager.javaOverridepublic void installPackageWithVerificationAndEncryption(Uri packageURI,IPackageInstallObserver observer, int flags, String installerPackageName,VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {try {mPM.installPackageWithVerificationAndEncryption(packageURI, observer, flags,installerPackageName, verificationParams, encryptionParams);} catch (RemoteException e) {// Should never happen!}} 5.installPackageWithVerificationAndEncryption方法里首先会获取设置中的用户安装位置并且会把InstallParams对象和安装位置flag封装到Message里然后发出一个消息后就撒手不管了。 代码位置frameworks/base/services/java/com/android/server/pm/PackageManagerService.java public void installPackageWithVerificationAndEncryption(Uri packageURI,IPackageInstallObserver observer, int flags, String installerPackageName,VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,null);final int uid Binder.getCallingUid();if(getInstallLocation() PackageHelper.APP_INSTALL_INTERNAL){userFilteredFlags flags |PackageManager.INSTALL_INTERNAL;} else if(getInstallLocation() PackageHelper.APP_INSTALL_EXTERNAL){userFilteredFlags flags |PackageManager.INSTALL_EXTERNAL;} else{userFilteredFlags filteredFlags;}final Message msg mHandler.obtainMessage(INIT_COPY);msg.obj new InstallParams(packageURI, observer, userFilteredFlags, installerPackageName,verificationParams, encryptionParams, user);mHandler.sendMessage(msg);} 6.接下来就该PackageHandler上场了会依次处理INIT_COPY、MCS_BOUN消息这里面会去连接DefaultContainerService服务接着会InstallParams的startCopy方法 代码位置frameworks/base/services/java/com/android/server/pm/PackageManagerService.java -内部类PackageHandlerpublic void handleMessage(Message msg) {try {doHandleMessage(msg);} finally {Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);}}void doHandleMessage(Message msg) {switch (msg.what) {case INIT_COPY: {HandlerParams params (HandlerParams) msg.obj;if (!mBound) {if (!connectToService()) {params.serviceError();return;} else {mPendingInstalls.add(idx, params);}} else {mPendingInstalls.add(idx, params);if (idx 0) {mHandler.sendEmptyMessage(MCS_BOUND);}}break;}case MCS_BOUN: {if (msg.obj ! null) {mContainerService (IMediaContainerService) msg.obj;}if (mContainerService null) {for (HandlerParams params : mPendingInstalls) {params.serviceError();}mPendingInstalls.clear();} else if (mPendingInstalls.size() 0) {HandlerParams params mPendingInstalls.get(0);if (params ! null) {if (params.startCopy()) {......}}} else {Slog.w(TAG, Empty queue);}break;}......case POST_INSTALL: {...if (data ! null) {InstallArgs args data.args;PackageInstalledInfo res data.res;if (res.returnCode PackageManager.INSTALL_SUCCEEDED) {......sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,res.pkg.applicationInfo.packageName, extras, null, null, firstUsers);final boolean update res.removedInfo.removedPackage ! null;if (update) {extras.putBoolean(Intent.EXTRA_REPLACING, true);}sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,res.pkg.applicationInfo.packageName, extras, null, null, updateUsers);if (update) {sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,res.pkg.applicationInfo.packageName, extras, null, null, updateUsers);sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,null, null, res.pkg.applicationInfo.packageName, null, updateUsers);if (isForwardLocked(res.pkg) || isExternal(res.pkg)) {......sendResourcesChangedBroadcast(true, true, pkgList,uidArray, null);}}if (res.removedInfo.args ! null) {deleteOld true;}}......if (args.observer ! null) {try {args.observer.packageInstalled(res.name, res.returnCode);} catch (RemoteException e) {Slog.i(TAG, Observer no longer exists.);}}} else {Slog.e(TAG, Bogus post-install token msg.arg1);}break;}}} 7.InstallParams的startCopy方法里会调用handleStartCopy方法 代码位置frameworks/base/services/java/com/android/server/pm/PackageManagerService.java -内部类InstallParams 继承于HandlerParamsfinal boolean startCopy() {boolean res;try {if (mRetries MAX_RETRIES) {Slog.w(TAG, Failed to invoke remote methods on default container service. Giving up);mHandler.sendEmptyMessage(MCS_GIVE_UP);handleServiceError();return false;} else {handleStartCopy();res true;}} catch (RemoteException e) {mHandler.sendEmptyMessage(MCS_RECONNECT);res false;}handleReturnCode();return res;} 8.handleStartCopy方法中会检查应用是否能安装如不合法则返回FAILED的CODE接着会调用DefaultContainerService的getMinimalPackageInfo方法该方法用于获取存储状态返回合适的安装位置如果返回码是INSTALL_SUCCEEDED那接下来就会调用InstallParams的copyApk如果安装到内置调用的就是FileInstallArgs的copyApk方法如安装到外置就调用AsecInstallArgs的copyApk方法AsecInstallArgs和FileInstallArgs都是InstallParams的子类 代码位置frameworks/base/services/java/com/android/server/pm/PackageManagerService.java -内部类FileInstallArgs 继承于InstallParams public void handleStartCopy() throws RemoteException {......if (onInt onSd) {ret PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;} else {......try {mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, mPackageURI,Intent.FLAG_GRANT_READ_URI_PERMISSION);........if (packageFile ! null) {......pkgLite mContainerService.getMinimalPackageInfo(packageFilePath, flags, lowThreshold);}}}final InstallArgs args createInstallArgs(this);mArgs args;......if (ret PackageManager.INSTALL_SUCCEEDED) {......ret args.copyApk(mContainerService, true);......}mRet ret;} 9.copyApk方法中会依次调用FileInstallArgs 的createCopyFile-PackageManagerService的createTempPackageFile方法去创建临时文件。 代码位置frameworks/base/services/java/com/android/server/pm/PackageManagerService.java -内部类FileInstallArgs 继承于InstallParamsframeworks/base/services/java/com/android/server/pm/PackageManagerService.java vmdl*.tmp就是copy成的临时文件void createCopyFile() {installDir isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;codeFileName createTempPackageFile(installDir).getPath();resourceFileName getResourcePathFromCodePath();libraryPath getLibraryPathFromCodePath();created true;}private File createTempPackageFile(File installDir) {File tmpPackageFile;try {tmpPackageFile File.createTempFile(vmdl, .tmp, installDir);} catch (IOException e) {Slog.e(TAG, Couldnt create temp file for downloaded package file.);return null;}try {FileUtils.setPermissions(tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,-1, -1);if (!SELinux.restorecon(tmpPackageFile)) {return null;}} catch (IOException e) {Slog.e(TAG, Trouble getting the canoncical path for a temp file.);return null;}return tmpPackageFile;} 10.临时文件已经有了handleStartCopy方法走完接着回到步骤7调用InstallParams的handleReturnCode方法handleReturnCode中会执行processPendingInstall在该方法中做了大量工作 Overridevoid handleReturnCode() {if (mArgs ! null) {processPendingInstall(mArgs, mRet);if (mTempPackage ! null) {if (!mTempPackage.delete()) {Slog.w(TAG, Couldnt delete temporary file: mTempPackage.getAbsolutePath());}}}} 11.来看看processPendingInstall到底做了什么processPendingInstall中最关键方法--installPackageLI主要的操作验证签名创建/data/data分配UID,dexopt都在这个方法中完成。 private void processPendingInstall(final InstallArgs args, final int currentStatus) {mHandler.post(new Runnable() {public void run() {mHandler.removeCallbacks(this);PackageInstalledInfo res new PackageInstalledInfo();res.returnCode currentStatus;res.uid -1;res.pkg null;res.removedInfo new PackageRemovedInfo();if (res.returnCode PackageManager.INSTALL_SUCCEEDED) {args.doPreInstall(res.returnCode);synchronized (mInstallLock) {installPackageLI(args, true, res);}args.doPostInstall(res.returnCode, res.uid);}......if (!doRestore) {Message msg mHandler.obtainMessage(POST_INSTALL, token, 0);mHandler.sendMessage(msg);}}});} 12.我们来看一下installPackageLI方法首选会让parsePackage去解析apk里的AndroidManifest.xml,使用的是parsePackage方法把解析出来的内容放到Package对象中接着调用doRename去将之前的tmp文件重命名为apk。apk已经在/data/app下了apk的属性也被解析出来放在内存Package对象中了那么现在还需要做什么呢apk有了数据目录(/data/data还没有所以后面会进行uid赋值验证签名创建相应的/data/data目录dexopt操作这些工作是由installNewPackageLI来完成 private void installPackageLI(InstallArgs args,boolean newInstall, PackageInstalledInfo res) {......int parseFlags mDefParseFlags | PackageParser.PARSE_CHATTY| (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)| (onSd ? PackageParser.PARSE_ON_SDCARD : 0);PackageParser pp new PackageParser(tmpPackageFile.getPath());pp.setSeparateProcesses(mSeparateProcesses);final PackageParser.Package pkg pp.parsePackage(tmpPackageFile,null, mMetrics, parseFlags);......if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {res.returnCode PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;return;}......if (replace) {replacePackageLI(pkg, parseFlags, scanMode, args.user,installerPackageName, res);} else {installNewPackageLI(pkg, parseFlags, scanMode | SCAN_DELETE_DATA_ON_FAILURES, args.user,installerPackageName, res);}synchronized (mPackages) {final PackageSetting ps mSettings.mPackages.get(pkgName);if (ps ! null) {res.newUsers ps.queryInstalledUsers(sUserManager.getUserIds(), true);}}} 13.让我们来看看installNewPackageLI具体怎么完成这些工作的吧。 private void installNewPackageLI(PackageParser.Package pkg,int parseFlags, int scanMode, UserHandle user,String installerPackageName, PackageInstalledInfo res) {......PackageParser.Package newPackage scanPackageLI(pkg, parseFlags, scanMode, System.currentTimeMillis(), user);if (newPackage null) {......} else {updateSettingsLI(newPackage, installerPackageName, null, null, res);......if (res.returnCode ! PackageManager.INSTALL_SUCCEEDED) {deletePackageLI(pkgName, UserHandle.ALL, false, null, null, dataDirExists ? PackageManager.DELETE_KEEP_DATA : 0,res.removedInfo, true);}}} 14.scanPackageLI方法中先调用getPackageLPw-newUserIdLPwSettings类方法)去设置uid在调用verifySignaturesLP验证签名然后调用createDataDirsLI创建/data/data数据目录最后调用performDexOptLI进行dexopt操作createDataDirsLI是靠调用mInstaller.install方法来完成目录创建framework中的Installer会和底层幕后Installer勾兑完成目录创建工作performDexOptLI操作最后也是通过mInstaller.dexopt来完成的 private PackageParser.Package scanPackageLI(PackageParser.Package pkg,int parseFlags, int scanMode, long currentTime, UserHandle user) {......synchronized (mPackages) {......pkgSetting mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,destResourceFile, pkg.applicationInfo.nativeLibraryDir,pkg.applicationInfo.flags, user, false);if (pkgSetting null) {mLastScanError PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;return null;}......if (!verifySignaturesLP(pkgSetting, pkg)) {if ((parseFlagsPackageParser.PARSE_IS_SYSTEM_DIR) 0) {return null;}// The signature has changed, but this package is in the system// image... lets recover!pkgSetting.signatures.mSignatures pkg.mSignatures;// However... if this package is part of a shared user, but it// doesnt match the signature of the shared user, lets fail.// What this means is that you cant change the signatures// associated with an overall shared user, which doesnt seem all// that unreasonable.if (pkgSetting.sharedUser ! null) {if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,pkg.mSignatures) ! PackageManager.SIGNATURE_MATCH) {Log.w(TAG, Signature mismatch for shared user : pkgSetting.sharedUser);mLastScanError PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;return null;}}// File a report about this.String msg System package pkg.packageName signature changed; retaining data.;reportSettingsProblem(Log.WARN, msg);}......}......if (mPlatformPackage pkg) {......} else {......if (dataPath.exists()) {......} else {......int ret createDataDirsLI(pkgName, pkg.applicationInfo.uid,pkg.applicationInfo.seinfo);if (ret 0) {// Error from installermLastScanError PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;return null;}if (dataPath.exists()) {pkg.applicationInfo.dataDir dataPath.getPath();} else {Slog.w(TAG, Unable to create data directory: dataPath);pkg.applicationInfo.dataDir null;}}/** Set the data dir to the default /data/data/package name/lib* if we got here without anyone telling us different (e.g., apps* stored on SD card have their native libraries stored in the ASEC* container with the APK).** This happens during an upgrade from a package settings file that* doesnt have a native library path attribute at all.*/if (pkg.applicationInfo.nativeLibraryDir null pkg.applicationInfo.dataDir ! null) {if (pkgSetting.nativeLibraryPathString null) {setInternalAppNativeLibraryPath(pkg, pkgSetting);} else {pkg.applicationInfo.nativeLibraryDir pkgSetting.nativeLibraryPathString;}}pkgSetting.uidError uidError;}......// We also need to dexopt any apps that are dependent on this library. Note that// if these fail, we should abort the install since installing the library will// result in some apps being broken.if (clientLibPkgs ! null) {if ((scanModeSCAN_NO_DEX) 0) {for (int i0; iclientLibPkgs.size(); i) {PackageParser.Package clientPkg clientLibPkgs.get(i);if (performDexOptLI(clientPkg, forceDex, (scanModeSCAN_DEFER_DEX) ! 0, false) DEX_OPT_FAILED) {if ((scanMode SCAN_DELETE_DATA_ON_FAILURES) ! 0) {removeDataDirsLI(pkg.packageName);}mLastScanError PackageManager.INSTALL_FAILED_DEXOPT;return null;}}}}// Request the ActivityManager to kill the process(only for existing packages)// so that we do not end up in a confused state while the user is still using the older// version of the application while the new one gets installed.......// Also need to kill any apps that are dependent on the library.......return pkg;}private int createDataDirsLI(String packageName, int uid, String seinfo) {int[] users sUserManager.getUserIds();int res mInstaller.install(packageName, uid, uid, seinfo);if (res 0) {return res;}for (int user : users) {if (user ! 0) {res mInstaller.createUserData(packageName,UserHandle.getUid(user, uid), user);if (res 0) {return res;}}}return res;}private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer,boolean inclDependencies) {......return performDexOptLI(pkg, forceDex, defer, done);}private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer,HashSetString done) {......if ((pkg.applicationInfo.flagsApplicationInfo.FLAG_HAS_CODE) ! 0) {......try {if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {if (!forceDex defer) {if (mDeferredDexOpt null) {mDeferredDexOpt new HashSetPackageParser.Package();}mDeferredDexOpt.add(pkg);return DEX_OPT_DEFERRED;} else {final int sharedGid UserHandle.getSharedAppGid(pkg.applicationInfo.uid);ret mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg));pkg.mDidDexOpt true;performed true;}}} catch (FileNotFoundException e) {......} catch (IOException e) {......} catch (dalvik.system.StaleDexCacheError e) {......} catch (Exception e) {......}if (ret 0) {//error from installerreturn DEX_OPT_FAILED;}}return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;} performDexOptLI后生成的文件 15.到目前为止scanPackageLI已经走完了接下来就该更新packages.list,packages.xml了系统中所有app的信息都保存在这两个文件中当有app安装、卸载、更新时都会更新这两个文件回到步骤13当installNewPackageLI中的scanPackageLI走完后后面会调用updateSettingsLI去更新文件mSettings.writeLPr()来完成往packages.list,packages.xml中更新数据 private void updateSettingsLI(PackageParser.Package newPackage, String installerPackageName,int[] allUsers, boolean[] perUserInstalled,PackageInstalledInfo res) {String pkgName newPackage.packageName;synchronized (mPackages) {......mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_INCOMPLETE);mSettings.writeLPr();}......synchronized (mPackages) {updatePermissionsLPw(newPackage.packageName, newPackage,UPDATE_PERMISSIONS_REPLACE_PKG | (newPackage.permissions.size() 0? UPDATE_PERMISSIONS_ALL : 0));......mSettings.writeLPr();}} packages.list文件部分截取 packages.xml部分截取包含包名安装时间签名权限文件安装路径等信息 16.installPackageLI到这里已经执行完了现在回到步骤11后续会执行到Message msg mHandler.obtainMessage(POST_INSTALL, token, 0); mHandler.sendMessage(msg);发送消息消息发出后回到步骤POST_INSTALL这里面主要做了两件事发生一条ACTION_PACKAGE_ADDED广播告诉大家又有新包了这是launcher什么的赶紧把图标加上然后回调args.observer.packageInstalled(res.name, res.returnCode);告诉PackageInstaller安装结果然后就显示安装完成界面。欧拉应用安装结束。 五、总结 小结一下安装app到底主要做了哪些事情 1.验证是否允许安装未知来源应用2.得到用户设置的首选安装位置3.检验app有效性检查存储状态得到最佳安装位置4.拷贝app到安装位置此时为.tmp临时文件5.解析AndroidManifest.xml6.重命名tmp为apk7.赋值UID验证权限8.创建/data/data/下数据目录9.执行dexopt操作10.更新packages.xml,packages.list11.发送广播回调安装状态 原文作者默默9518原文链接https://sgzy001/article/details/44857057 参考文献 【腾讯文档】Android Framework 知识库https://docs.qq.com/doc/DSXBmSG9VbEROUXF5 友情推荐 Android 开发干货集锦 至此本篇已结束。转载网络的文章小编觉得很优秀欢迎点击阅读原文支持原创作者如有侵权恳请联系小编删除欢迎您的建议与指正。同时期待您的关注感谢您的阅读谢谢 点击阅读原文为大佬点赞
http://www.hkea.cn/news/14536810/

相关文章:

  • 杭州网站建设公司在韩国注册公司需要什么条件
  • 网站权重问题h5制作步骤
  • 专业简历制作网站有哪些网站建设入门教程pdf
  • 信誉好的永州网站建设建设推广型网站
  • 图片无版权网站微信 网站 收费
  • 网站建设功能表正规网站建设方案详细
  • 网站是什么字体木质家居 技术支持 东莞网站建设
  • 青岛谁家做网站石家庄哪里做微网站
  • 北控水务建设发展有限公司网站笔记本怎么建设网站
  • 产品盘网站建设乐达淄博网站建设制作
  • 网站建设栏目标语口号cms门户网站模板下载
  • 网站型跟商城型google秒收录方法
  • 手机网站优化怎么做企业网址怎么注册
  • 全球外贸网站制作教程深圳做网站的公司哪家最好
  • ysl免费网站建设免费行情网站在线
  • 商务网站建设论文总结网站外链优化
  • 自己做的网站显示不出来php网站发送邮件
  • 基础网站建设的实施步骤淮安制作网站在那里
  • 怎么做能让网站尽快收录网站建设的优点与不足
  • 吗网站建设仿西部数码网站
  • 怎么搭建网站视频教程哈尔滨建站系统报价
  • 网站建设推广多少钱网络架构拓扑图
  • jq动画效果网站服务器放网站吗
  • 爱站网关键词查询工具365做网站
  • 客户说做网站没效果萍乡网站建设萍乡
  • 官方商城网站建设wordpress放在哪
  • 制作网站源码软件广告文案生成器
  • 营销网站好不好网页制作工具及用途
  • 各省网站备案时长吴江区建设局网站
  • 如何使用c 进行网站开发企业展厅建筑外观