Android静默方式实现批量安装卸载应用程序的深入分析
2023-06-13 09:15:01 时间
前段时间做了一个批量安装卸载应用程序的小应用,由于安装卸载应用程序的部分API是隐藏的,所以必须在ubuntu下下载Android系统源码,并编译之后使用MM命令编译生成APK文件,其实也难。
思路是这样的,在XX/packages/apps目录下有一个PackageInstaller的应用程序,Android机器中安装卸载都是由这个应用程序完成的。但是它没有批量安装和卸载的功能,如果要在自己的应用程序中添加批量安装和卸载的功能,其实很简单,只需要参考PakcageInstaller里面的安装卸载代码加个循环就可以了。但值得注意的是在编译的过程中必须复制PackageInstaller里面的Android.mk文件,修改文件为工程目录名。
好了,废话不再多说,下面是关键代码
1、Android.mk文件
复制代码代码如下:
思路是这样的,在XX/packages/apps目录下有一个PackageInstaller的应用程序,Android机器中安装卸载都是由这个应用程序完成的。但是它没有批量安装和卸载的功能,如果要在自己的应用程序中添加批量安装和卸载的功能,其实很简单,只需要参考PakcageInstaller里面的安装卸载代码加个循环就可以了。但值得注意的是在编译的过程中必须复制PackageInstaller里面的Android.mk文件,修改文件为工程目录名。
好了,废话不再多说,下面是关键代码
LOCAL_PATH:=$(callmy-dir)
include$(CLEAR_VARS)
LOCAL_MODULE_TAGS:=optional
LOCAL_SRC_FILES:=$(callall-subdir-java-files)
LOCAL_PACKAGE_NAME:=PackageInstaller
LOCAL_CERTIFICATE:=platform
include$(BUILD_PACKAGE)
LOCAL_PATH:=$(callmy-dir)
include$(CLEAR_VARS)
LOCAL_MODULE_TAGS:=optional
LOCAL_SRC_FILES:=$(callall-subdir-java-files)
LOCAL_PACKAGE_NAME:=PackageInstaller
LOCAL_CERTIFICATE:=platform
include$(BUILD_PACKAGE)
packagecn.ceadic.apkmgr;
importjava.io.File;
importjava.io.FileNotFoundException;
importjava.io.FileOutputStream;
importjava.io.IOException;
importandroid.content.Context;
importandroid.content.Intent;
importandroid.content.pm.PackageInfo;
importandroid.content.pm.PackageManager;
importandroid.content.pm.PackageManager.NameNotFoundException;
importandroid.net.Uri;
importandroid.util.Log;
importandroid.content.pm.IPackageInstallObserver;
importandroid.content.pm.IPackageDeleteObserver;
importandroid.os.FileUtils;
publicclassPackageInstaller{
privateFilemTmpFile;
privatefinalStringTMP_FILE_NAME="tmpCopy.apk";
privatefinalstaticStringTAG="PackInstaller";
privateContextmContext;
publicPackageInstaller(Contextcontext){
mContext=context;
}
publicvoidinstall(Stringpath,StringpackageName){
Intentintent=newIntent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(newFile(path)),
"application/vnd.android.package-archive");
mContext.startActivity(intent);
}
publicvoidinstatllBatch(Stringpath,StringpackageName){
Log.i(TAG,"path="+path);
intinstallFlags=0;
PackageManagerpm=mContext.getPackageManager();
try{
PackageInfopi=pm.getPackageInfo(packageName,
PackageManager.GET_UNINSTALLED_PACKAGES);
if(pi!=null){
installFlags|=PackageManager.INSTALL_REPLACE_EXISTING;
}
}catch(NameNotFoundExceptione){
}
if((installFlags&PackageManager.INSTALL_REPLACE_EXISTING)!=0){
Log.w(TAG,"Replacingpackage:"+packageName);
}
//Createtempfilebeforeinvokinginstallapi
mTmpFile=createTempPackageFile(path);
if(mTmpFile==null){
//Messagemsg=mHandler.obtainMessage(INSTALL_COMPLETE);
//msg.arg1=PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
//mHandler.sendMessage(msg);
return;
}
UrimPackageURI=Uri.parse("file://"+mTmpFile.getPath());
StringinstallerPackageName=mContext.getIntent().getStringExtra(
Intent.EXTRA_INSTALLER_PACKAGE_NAME);
PackageInstallObserverobserver=newPackageInstallObserver();
pm.installPackage(mPackageURI,observer,installFlags,
installerPackageName);
}
privateFilecreateTempPackageFile(StringfilePath){
FiletmpPackageFile=mContext.getFileStreamPath(TMP_FILE_NAME);
if(tmpPackageFile==null){
Log.w(TAG,"Failedtocreatetempfile");
returnnull;
}
if(tmpPackageFile.exists()){
tmpPackageFile.delete();
}
//Openfiletomakeitworldreadable
FileOutputStreamfos;
try{
fos=openFileOutput(TMP_FILE_NAME,MODE_WORLD_READABLE);
}catch(FileNotFoundExceptione1){
Log.e(TAG,"Erroropeningfile"+TMP_FILE_NAME);
returnnull;
}
try{
fos.close();
}catch(IOExceptione){
Log.e(TAG,"Erroropeningfile"+TMP_FILE_NAME);
returnnull;
}
FilesrcPackageFile=newFile(filePath);
if(!FileUtils.copyFile(srcPackageFile,tmpPackageFile)){
Log.w(TAG,"Failedtomakecopyoffile:"+srcPackageFile);
returnnull;
}
returntmpPackageFile;
}
privateclassPackageInstallObserverextendsIPackageInstallObserver.Stub{
publicvoidpackageInstalled(StringpackageName,intreturnCode){
//Messagemsg=mHandler.obtainMessage(INSTALL_COMPLETE);
//msg.arg1=returnCode;
//mHandler.sendMessage(msg);
Log.i(TAG,"====INSTALL_COMPLETE");
}
}
privateclassPackageDeleteObserverextendsIPackageDeleteObserver.Stub{
publicvoidpackageDeleted(booleansucceeded){
// Messagemsg=mHandler.obtainMessage(UNINSTALL_COMPLETE);
// msg.arg1=succeeded?SUCCEEDED:FAILED;
// mHandler.sendMessage(msg);
Log.i(TAG,"====UNINSTALL_COMPLETE");
}
}
publicvoiduninstall(StringpackageName){
UripackageURI=Uri.parse("package:"+packageName);
IntentuninstallIntent=newIntent(Intent.ACTION_DELETE,
packageURI);
mContext.startActivity(uninstallIntent);
}
publicvoiduninstallBatch(StringpackageName){
PackageDeleteObserverobserver=newPackageDeleteObserver();
mContext.getPackageManager().deletePackage(packageName,observer,0);
}
}
packagecn.ceadic.apkmgr;
importjava.io.File;
importjava.io.FileNotFoundException;
importjava.io.FileOutputStream;
importjava.io.IOException;
importandroid.content.Context;
importandroid.content.Intent;
importandroid.content.pm.PackageInfo;
importandroid.content.pm.PackageManager;
importandroid.content.pm.PackageManager.NameNotFoundException;
importandroid.net.Uri;
importandroid.util.Log;
importandroid.content.pm.IPackageInstallObserver;
importandroid.content.pm.IPackageDeleteObserver;
importandroid.os.FileUtils;
publicclassPackageInstaller{
privateFilemTmpFile;
privatefinalStringTMP_FILE_NAME="tmpCopy.apk";
privatefinalstaticStringTAG="PackInstaller";
privateContextmContext;
publicPackageInstaller(Contextcontext){
mContext=context;
}
publicvoidinstall(Stringpath,StringpackageName){
Intentintent=newIntent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(newFile(path)),
"application/vnd.android.package-archive");
mContext.startActivity(intent);
}
publicvoidinstatllBatch(Stringpath,StringpackageName){
Log.i(TAG,"path="+path);
intinstallFlags=0;
PackageManagerpm=mContext.getPackageManager();
try{
PackageInfopi=pm.getPackageInfo(packageName,
PackageManager.GET_UNINSTALLED_PACKAGES);
if(pi!=null){
installFlags|=PackageManager.INSTALL_REPLACE_EXISTING;
}
}catch(NameNotFoundExceptione){
}
if((installFlags&PackageManager.INSTALL_REPLACE_EXISTING)!=0){
Log.w(TAG,"Replacingpackage:"+packageName);
}
//Createtempfilebeforeinvokinginstallapi
mTmpFile=createTempPackageFile(path);
if(mTmpFile==null){
//Messagemsg=mHandler.obtainMessage(INSTALL_COMPLETE);
//msg.arg1=PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
//mHandler.sendMessage(msg);
return;
}
UrimPackageURI=Uri.parse("file://"+mTmpFile.getPath());
StringinstallerPackageName=mContext.getIntent().getStringExtra(
Intent.EXTRA_INSTALLER_PACKAGE_NAME);
PackageInstallObserverobserver=newPackageInstallObserver();
pm.installPackage(mPackageURI,observer,installFlags,
installerPackageName);
}
privateFilecreateTempPackageFile(StringfilePath){
FiletmpPackageFile=mContext.getFileStreamPath(TMP_FILE_NAME);
if(tmpPackageFile==null){
Log.w(TAG,"Failedtocreatetempfile");
returnnull;
}
if(tmpPackageFile.exists()){
tmpPackageFile.delete();
}
//Openfiletomakeitworldreadable
FileOutputStreamfos;
try{
fos=openFileOutput(TMP_FILE_NAME,MODE_WORLD_READABLE);
}catch(FileNotFoundExceptione1){
Log.e(TAG,"Erroropeningfile"+TMP_FILE_NAME);
returnnull;
}
try{
fos.close();
}catch(IOExceptione){
Log.e(TAG,"Erroropeningfile"+TMP_FILE_NAME);
returnnull;
}
FilesrcPackageFile=newFile(filePath);
if(!FileUtils.copyFile(srcPackageFile,tmpPackageFile)){
Log.w(TAG,"Failedtomakecopyoffile:"+srcPackageFile);
returnnull;
}
returntmpPackageFile;
}
privateclassPackageInstallObserverextendsIPackageInstallObserver.Stub{
publicvoidpackageInstalled(StringpackageName,intreturnCode){
//Messagemsg=mHandler.obtainMessage(INSTALL_COMPLETE);
//msg.arg1=returnCode;
//mHandler.sendMessage(msg);
Log.i(TAG,"====INSTALL_COMPLETE");
}
}
privateclassPackageDeleteObserverextendsIPackageDeleteObserver.Stub{
publicvoidpackageDeleted(booleansucceeded){
// Messagemsg=mHandler.obtainMessage(UNINSTALL_COMPLETE);
// msg.arg1=succeeded?SUCCEEDED:FAILED;
// mHandler.sendMessage(msg);
Log.i(TAG,"====UNINSTALL_COMPLETE");
}
}
publicvoiduninstall(StringpackageName){
UripackageURI=Uri.parse("package:"+packageName);
IntentuninstallIntent=newIntent(Intent.ACTION_DELETE,
packageURI);
mContext.startActivity(uninstallIntent);
}
publicvoiduninstallBatch(StringpackageName){
PackageDeleteObserverobserver=newPackageDeleteObserver();
mContext.getPackageManager().deletePackage(packageName,observer,0);
}
}
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permissionandroid:name="android.permission.INSTALL_PACKAGES"/>
<uses-permissionandroid:name="android.permission.DELETE_PACKAGES"/>
<uses-permissionandroid:name="android.permission.CLEAR_APP_CACHE"/>
<uses-permissionandroid:name="android.permission.READ_PHONE_STATE"/>
<uses-permissionandroid:name="android.permission.CLEAR_APP_USER_DATA"/>
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permissionandroid:name="android.permission.INSTALL_PACKAGES"/>
<uses-permissionandroid:name="android.permission.DELETE_PACKAGES"/>
<uses-permissionandroid:name="android.permission.CLEAR_APP_CACHE"/>
<uses-permissionandroid:name="android.permission.READ_PHONE_STATE"/>
<uses-permissionandroid:name="android.permission.CLEAR_APP_USER_DATA"/>
以上代码在Android2.1的SDK中编译通过,并正确批量安装卸载应用程序
相关文章
- android studio不能输入中文_Android模拟器
- android scaleanimation动画,【Android动画九章】-RotateAnimation(旋转动画)和ScaleAnimation(尺寸动画)…[通俗易懂]
- Android传输数据时加密详解
- android 混淆不起作用,Android代码混淆的写法总结
- android onresume方法,Android onActivityResult()和onResume()的执行顺序
- android 读取本地数据库db文件(Android sqlite)
- android退出app代码,Android应用退出代码各种方式
- iphone4装android,iPhone4可安装Android实现双系统启动.pdf
- android scaleanimation动画,Android 的ScaleAnimation 缩放动画基本运用
- Android AIDL跨进程通信
- Android保存图片到相册(适配android 10以下及以上)
- Android webview 加载html 页面缩放的问题
- 【CMake】Android Studio 中使用 CMake 编译单个 C++ 源文件 ( 常用的 CMake 命令解析 )
- 【Android 启动过程】Activity 启动源码分析 ( ActivityThread 流程分析 二 )
- 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 三 | 等待远程函数执行完毕 | 寄存器获取返回值 )
- 【错误记录】Android 应用安装后出现两个启动图标 ( 排查应用及依赖库中配置了 android.intent.category.LAUNCHER 的 Activity )
- 【错误记录】Android 应用安全检测漏洞修复 ( StrandHogg 漏洞 | 设置 Activity 组件 android:taskAffinity=““ )
- 【Android Gradle 插件】自定义 Gradle 任务 ④ ( Task#doLast 函数用法 | 自定义 Gradle 任务代码示例 )
- 【错误记录】Android Studio 编译报错 ( Could not resolve com.android.tools.build:gradle:7.4.2. )
- Android控制文字水平间距android:letterSpacing详解手机开发
- android广播监听短信并显示内容详解手机开发
- Android中android:visibility的3中属性的剖析详解手机开发
- 谷歌宣布推出Android 12刨冰首个开发预览版 新版提供部分安全功能
- Android版Chrome开始支持WebVR
- android获取屏幕的长与宽实现代码(手写)
- android下拉刷新ListView的介绍和实现代码
- Android需要提升权限的操作方法
- java批量采集豌豆荚网站Android应用图标和包名