把APK安装到SD卡和TF卡实现方案
首先给大家分享一个巨牛巨牛的人工智能教程,是我无意中发现的。教程不仅零基础,通俗易懂,而且非常风趣幽默,还时不时有内涵段子,像看小说一样,哈哈~我正在学习中,觉得太牛了,所以分享给大家!点这里可以跳转到教程
1. 简介
为了能把应用程序安装到SD卡和TF卡上,Android系统默认是不支持的,它只有一个asec mount点: /mnt/secure/asec,在我的系统中,此mount点由/mnt/sdcard给占用了,所以TF卡就支持不了。为了解决此问题,除了把代码读明白之外,无其它的办法。为了方便理解下面的描述,先看下Vold(管理外设热插拔)的系统框架图:
关于相关类图,引用其他仁兄的图:
2. 从U盘安装应用程序流程
PackageInstallerActivity.java::initiateInstall->
::startInstallConfirm->
InstallAppProgress::onCreate->
InstallAppProgress::initView->
PackageManager::installPackage->
PackageManagerService::installPackage->
installPackageWithVerification->
mHandler.sendMessage(msg)->
PackageHandler::handleMessage->
PackageHandler::doHandleMessage->
HandlerParams::startCopy->
InstallParams::handleStartCopy-> (根据installLocation确认安装位置,只有针对/data分区有lowThreshold)
SdInstallArgs::copyApk-> (关键的地方,下面详解)
InstallParams::handleReturnCode->
PackageManagerService::processPendingInstall->
PackageManagerService::installPackageLI-> //args, res分析
PackageManagerService::installNewPackageLI-> // or replacePackageLI
PackageManagerService::scanPackageLI-> (KEY)->parsePackage(解析AndroidManifest.xml)
Installer::install (mInstaller.install)-> (Socket)--->
installd(真正做事的地方)
2.1 SdInstallArgs::copyApk
SdInstallArgs::copyApk->
DefaultContainerService::copyResourceInner->
PackageHelper::createSdDir->
MountService::createSecureContainer->
(cmd = String.format(new Locale("en", "Us"),
"asec create %s %d %s %s %d", id, sizeMb, fstype, key, ownerUid);)
NativeDaemonConnector::doCommandLocked->(向"vold" socket发送命令给vold,并等待结果)
NativeDaemonConnector::sendCommandLocked-> (Socket)
FrameworkListener::onDataAvailable-> (receive message) "buffer=asec list"
或"buffer=asec create smdl2tmp1 19 fat caf791d0426d682e5b2aafc5439d55a9 10023"
FrameworkListener::dispatchCommand->
CommandListener::AsecCmd::runCommand-> (所有与Volume::SEC_ASECDIR相关的代码都需要修改)
VolumeManager::createAsec (决定安装文件的路径Volume::SEC_ASECDIR)
2.2 复杂的mount关系
详细代码参见Volume.cpp::
代码默认不把sdcard && udisk mount为asec,为此需要把SD卡或TF卡mount到asec挂载点,当然系统默认只有一个/mnt/secure/asec,你可以在init.rc中创建一个/mnt/secure/asecsd或/mnt/secure/asectf,并执行mount即可。
• /mnt/secure: 下的mount点为物理外设的mount点
•/mnt/asec: 为公共挂载点,它是一个tmpfs文件系统的挂载点,安装到SD或TF上的应用程序都可以被mount到此目录下的mount点
复杂的mount关系如下所示:
1) /dev/block/vold/31:9 mount to /mnt/secure/staging
2) /mnt/secure/staging/.android_secure mount to /mnt/secure/asec (MS_BIND)
3) tmpfs mount to /mnt/secure/staging/.android_secure (只读0字节tmpfs,把它隐藏起来, obscuring the asec image directory from non root users)
4) 把/mnt/secure/staging下的子目录(.android_secure)移动到/mnt/sdcard下
注:MS_BIND: 执行bind挂载,使文件或者子目录树在文件系统内的另一个点上可视。
搞这么复杂的目的只有一个:只有root用户才能查看/mnt/secure/asec下的文件,当然把TF卡取出来,在Widows上可以看到.android_secure目录下的.asec文件。
2.3 把APK安装到SD卡或TF卡上留下的东东
当把APK安装到SD卡或TF卡上时,将在以下地方留下它的东东:
1) /mnt/secure/asec: (安装之后产生的.asec文件,它才是真正的内容)
-rwxrwxr-x system sdcard_rw 20257280 2013-04-07 06:14 com.myarrow.test-1.asec
2) /mnt/asec/com.myarrow.test-1: (是被mount上去的,它是一个tmpfs,并不真正占用flash空间)
dr-xr-xr-x system root 2013-04-07 06:14 lib
-r-xr-xr-x system root 4973096 2013-04-07 06:14 pkg.apk
3) /data/data/com.myarrow.test: (只是一个链接,不真正占用flash空间)
lrwxrwxrwx system system 2013-04-09 06:51 lib -> /mnt/asec/com.myarrow.test-1/lib
4) /data/dalvik-cache: (包含apk包中的dex文件,它占用data分区的flash空间, 所以data分区必须预留空间)
-rw-r--r-- system app_58 36608 2013-04-07 06:14 mnt@asec@com.myarrow.test-1@pkg.apk@classes.dex
3. 需要修改的主要文件
1) Volume.cpp
修改其中的mountVol/unmountVol,把SD或TF卡也执行bindmount
2) DefaultContainerService.java
修改isUnderExternalThreshold,当空间不足时,看看SD或TF卡上是否有足够的空间
3) VolumeManager.cpp
扩展与Volume::SEC_ASECDIR相关的地方,因为我们增加了一个Volume::SEC_SD_ASECDIR
4. Mount和Unmoun asec t流程
1) Mount:
MountService.java (notifyVolumeStateChange/onEvent)->
MountService.jvav (updatePublicVolumeState) ->
PackageManagerService.java (updateExternalMediaStatus) ->
(updateExternalMediaStatusInner) ->
(loadMediaPackages) ->
SdInstallArgs.doPreInstall->
PackageHelper.java (mountSdDir) ->
MountService.java(mountSecureContainer)->
CommandListener.cpp(CommandListener::AsecCmd::runCommand)
2) Unmount:
MountService.java (notifyVolumeStateChange/onEvent)->
MountService.jvav (updatePublicVolumeState) ->
PackageManagerService.java (updateExternalMediaStatus) ->
(updateExternalMediaStatusInner) ->
(unloadMediaPackages) ->(send UPDATED_MEDIA_STATUS)
PackageHandler.doHandleMessage (get UPDATED_MEDIA_STATUS)->
unloadAllContainers ->
(SdInstallArgs.doPostDeleteLI)->
PackageHelper.java (unMountSdDir) ->
MountService.java (unmountSecureContainer)->
CommandListener.cpp(CommandListener::AsecCmd::runCommand)
5. copyResourceInner
其详细代码如下所示:
private String copyResourceInner(Uri packageURI, String newCid, String key, String resFileName) { // Make sure the sdcard is mounted. String status = Environment.getExternalStorageState(); if (!status.equals(Environment.MEDIA_MOUNTED)) { Slog.w(TAG, "Make sure sdcard is mounted."); return null; } // The .apk file String codePath = packageURI.getPath(); File codeFile = new File(codePath); // Calculate size of container needed to hold base APK. int sizeMb; try { sizeMb = calculateContainerSize(codeFile); } catch (FileNotFoundException e) { Slog.w(TAG, "File does not exist when trying to copy " + codeFile.getPath()); return null; } // Create new container final String newCachePath; if ((newCachePath = PackageHelper.createSdDir(sizeMb, newCid, key, Process.myUid())) == null) { Slog.e(TAG, "Failed to create container " + newCid); return null; } /*if (localLOGV)*/ { Slog.i(TAG, "Created container for " + newCid + " at path : " + newCachePath); } final File resFile = new File(newCachePath, resFileName); if (FileUtils.copyFile(new File(codePath), resFile)) { /*if (localLOGV)*/ { Slog.i(TAG, "Copied " + codePath + " to " + resFile); } } else { Slog.e(TAG, "Failed to copy " + codePath + " to " + resFile); // Clean up container PackageHelper.destroySdDir(newCid); return null; } final File sharedLibraryDir = new File(newCachePath, LIB_DIR_NAME); if (sharedLibraryDir.mkdir()) { int ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(codeFile, sharedLibraryDir); if (ret != PackageManager.INSTALL_SUCCEEDED) { Slog.e(TAG, "Could not copy native libraries to " + sharedLibraryDir.getPath()); PackageHelper.destroySdDir(newCid); return null; } } else { Slog.e(TAG, "Could not create native lib directory: " + sharedLibraryDir.getPath()); PackageHelper.destroySdDir(newCid); return null; } if (!PackageHelper.finalizeSdDir(newCid)) { Slog.e(TAG, "Failed to finalize " + newCid + " at path " + newCachePath); // Clean up container PackageHelper.destroySdDir(newCid); return null; } if (localLOGV) { Slog.i(TAG, "Finalized container " + newCid); } if (PackageHelper.isContainerMounted(newCid)) { if (localLOGV) { Slog.i(TAG, "Unmounting " + newCid + " at path " + newCachePath); } // Force a gc to avoid being killed. Runtime.getRuntime().gc(); PackageHelper.unMountSdDir(newCid); } else { if (localLOGV) { Slog.i(TAG, "Container " + newCid + " not mounted"); } } return newCachePath; }
其主要功能为:
1)创建.asec文件
2)copy apk
3)copy lib
4)final .asec文件
其详细log信息如下:
D/VoldVolumeManager( 85): createAsec(367) call createImageFile E/Vold ( 85): createImageFile(236) call creat E/Vold ( 85): createImageFile(241) call ftruncate E/Vold ( 85): createImageFile(247) END D/VoldVolumeManager( 85): createAsec(374) call asecHash D/VoldVolumeManager( 85): createAsec(383) call Loop::create D/VoldVolumeManager( 85): createAsec(397) call Devmapper::create D/VoldVolumeManager( 85): createAsec(414) call open D/VoldVolumeManager( 85): createAsec(436) write sb D/VoldVolumeManager( 85): createAsec(453) Fat::format D/VoldVolumeManager( 85): createAsec(477) Fat::doMount D/VoldVolumeManager( 85): createAsec(491) End ****copy apk and lib***** D/VoldVolumeManager( 85): finalizeAsec(502) start D/VoldVolumeManager( 85): finalizeAsec(520) End D/VoldVolumeManager( 85): renameAsec:538 Volume::SEC_ASECDIR startD/VoldVolumeManager( 85): renameAsec:538 Volume::SEC_ASECDIR start
浏览人工智能教程
把APK安装到SD卡和TF卡实现方案相关推荐
- 硬盘、移动硬盘、内存卡(SD卡、TF卡)、U盘修复,格式化
文章目录: 1 问题描述 2 硬盘.移动硬盘.内存卡(SD卡.TF卡).U盘修复工具 3 扇区的介绍 1 问题描述 我的是SD卡(就是TF卡)出现了问题,然后在windows系统PC上可以读出来,但是 ...
- SD卡、TF卡、SIM卡的区别
SD卡(Secure Digital Memory Card)是一种基于半导体快闪记忆器的新一代记忆设备.SD卡由日本松下.东芝及美国SanDisk公司于1999年8月共同开发研制.大小犹如一张邮票的 ...
- ICMAX八大方法教你快速分清什么是SD卡与TF卡
很多人搞不清几种内存卡的区别,因为内存卡有好几种,这里说一下sd卡和TF卡的区别,sd卡一般是相机使用的大的内存卡,TF就是手机使用的小的内存卡, 不管是SD卡还是TF卡如果坏了都可以试着用内存卡修复 ...
- pcie16x能插1x的卡嘛?_这7个修复工具分享给你:不仅能修复U盘,SD卡、TF卡也能修复!...
今天小编就一口气把7个修复工具分享给大家,这些修复工具不仅能修复U盘,而且还能修复SD卡和TF卡哦~下面就来看看是哪几个神器吧!(文末提供下载) 在正式操作之前有几点需要提醒一下: 1.修复的过程中不 ...
- pcie16x能插1x的卡嘛?_小白把这7个修复工具分享给你:不仅能修复U盘,SD卡、TF卡也能修复!...
此前分享给大家的U盘量产工具帮助了许多朋友修复了本来不能使用的U盘,但是仍然有不少朋友反映"主控型号无法检测""没有对应的量产工具可以下载""量产后仍 ...
- SD NAND 为什么可以完胜T卡(tf卡/sd卡)?
现在科技发展中,各种电子设备很普及,随处可见,使用率高的情况下,难免会出现一些问题.比如说很多人突然遇到一些设备识别不到T卡(tf卡/sd卡)了?再不然就是T卡突然间崩溃?再比如有的设备 ...
- SD卡和TF卡的区别
源于百度经验 最近看到有些网友经常询问SD卡和TF卡的区别,所以作家俺根据亲身经验给大家说说这个. SD卡和TF卡的区别 1外观区分: SD卡体积为24mm×32mm×2.1mm: TF卡体积为15m ...
- CS品牌SD NAND VS TF卡 SD NAND和TF卡的区别
最近工程师群里都会出现一个CS品牌的SD NAND的存储芯片,那么很多人的疑问什么是SD NAND?今天就带大家详细的了解一下.SD NAND俗称贴片式T卡,贴片式TF卡,贴片式SD卡,贴片式内存卡, ...
- 优盘Flash, SD卡, TF 卡 ,CF卡一体黑胶存储颗粒数据恢复专用必备工具合
优盘Flash, SD卡, TF 卡 ,CF卡一体黑胶存储颗粒数据恢复专用必备工具合集 对于数据的丢失是大家最不想看到的,毕竟 数据无价的道理都懂,但是意外总是没有预兆,目前市场上流通的便携式存储无外 ...
最新文章
- 牛客小白月赛5-F题: 圆(circle)
- 学习如何写 Bug 的一天! | 每日趣闻
- win这个傻逼系统,高PPI上默认的情况下是放大的,放大了之后逻辑分辨率不跟着放大。
- 中国通货膨胀率2.8%,数据分析买房风险直线上升
- 使用pip安装python库的几种方式,解决pip安装python库慢的问题
- fpga如何约束走线_FPGA设计约束技巧之XDC约束之I/O篇 (上)
- 世界首富比尔盖茨花钱全过程!
- git clone大文件EOF错误
- 五大步骤快速搭建个人网站
- kafkatemplate无法注入_SpringBoot 整合 Spring-Kafka 深度踩坑实战
- 基于STM32F103自制CMSIS-DAP下载器
- Cisco ASA 5505 (Version 9.X)的 LAN上网和NAT的配置
- Google完整安装包下载
- pp助手苹果版_iOS 版 PP 助手下线,再见了
- 一篇文章带你入门python基础开发
- 服务认证的介绍-实施依据及作用
- 商业仲裁与诉讼律师Katherine Cheung加入德汇香港担任合伙人
- java 获取年和季度_java获取当前时间的年周月季度等的开始结束时间
- sif4j 字符串拼接和占位符的区别
- V 社秘密开发 Steam 跨系统兼容工具;甲骨文开源 GraphPipe,机器学习模型标准
热门文章
- ORA-03135 connections lost contact Process ID:0
- 【Java常用工具类汇总 2,零基础如何成为高级Java开发
- 如何用Arduino IDE开发9.9元的合宙LuatOS ESP32C3开发板?
- 常用连接嵌入式设备的工具方法
- HTML5CSS3特效-上下跳动的小球-遁地龙卷风
- 机器学习算法之监督学习与非监督学习
- Apache httpd.conf详解
- 解读乔新亮的《看透本质:研发出了生产事故,到底要不要罚钱?》
- 抖音养号教程技巧,做抖音怎么养号上热门!
- 怎么学Python能够高薪就业 需要掌握哪些技术