随笔之所以叫随笔,就是太随意了,说起来,之前的闹钟系列随笔还没写完,争取在十月结束之前找时间把它给写了吧。今天要讲的Android APK的静默安装、卸载。网上关于静默卸载的教程有很多,更有说要调用隐藏API,在源码下用MM命令编译生成APK的,反正我能力有限,没一一研究过,这里选择一种我试验成功的来讲。
静默安装、卸载的好处就是你可以偷偷摸摸,干点坏事什么的,哈哈~
一、准备工作
要实现静默安装、卸载,首先你要有root权限,能把你的静默安装、卸载程序移动到system/app目录下。
1、用RE浏览器将你的应用(一般在/data/app目录下)移动到/system/app目录下,如果你的程序有.so文件,那么请将相应的.so文件从/data/data/程序包名/lib目录下移动到/system/lib目录下
2、重启你的手机,你就会发现你的应用已经是系统级应用了,不能被卸载,也就是说你的应用现在已经八门全开,活力无限了。
二、静默安装需要的权限
<!-- 静默安装所需权限,如与Manifest报错,请运行Project->clean -->
<!-- 允许程序安装应用 -->
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<!-- 允许程序删除应用 -->
<uses-permission android:name="android.permission.DELETE_PACKAGES" />
<!-- 允许应用清除应用缓存 -->
<uses-permission android:name="android.permission.CLEAR_APP_CACHE" />
<!-- 允许应用清除应用的用户数据 -->
<uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />
三、示例Demo创建
首先,先把AndroidManifest.xml给完善好
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.lsj.slient"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <!-- 静默安装所需权限,如与Manifest报错,请运行Project->clean -->
<!-- 允许程序安装应用 -->
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<!-- 允许程序删除应用 -->
<uses-permission android:name="android.permission.DELETE_PACKAGES" />
<!-- 允许应用清除应用缓存 -->
<uses-permission android:name="android.permission.CLEAR_APP_CACHE" />
<!-- 允许应用清除应用的用户数据 -->
<uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" /> <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.lsj.slient.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application> </manifest>
接着,把布局文件activity_main.xml写好
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" > <Button
android:id="@+id/install"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="静默安装"/> <Button
android:id="@+id/uninstall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="静默卸载"/> </LinearLayout>
接下来,把实现静默安装的ApkManager工具类写完整
package com.lsj.slient; import java.io.ByteArrayOutputStream;
import java.io.InputStream; import android.util.Log; /**
* 应用管理类
*
* @author Lion
*
*/
public class ApkManager { private static final String TAG = "ApkManager";
private static final String INSTALL_CMD = "install";
private static final String UNINSTALL_CMD = "uninstall"; /**
* APK静默安装
*
* @param apkPath
* APK安装包路径
* @return true 静默安装成功 false 静默安装失败
*/
public static boolean install(String apkPath) {
String[] args = { "pm", INSTALL_CMD, "-r", apkPath };
String result = apkProcess(args);
Log.e(TAG, "install log:"+result);
if (result != null
&& (result.endsWith("Success") || result.endsWith("Success\n"))) {
return true;
}
return false;
} /**
* APK静默安装
*
* @param packageName
* 需要卸载应用的包名
* @return true 静默卸载成功 false 静默卸载失败
*/
public static boolean uninstall(String packageName) {
String[] args = { "pm", UNINSTALL_CMD, packageName };
String result = apkProcess(args);
Log.e(TAG, "uninstall log:"+result);
if (result != null
&& (result.endsWith("Success") || result.endsWith("Success\n"))) {
return true;
}
return false;
} /**
* 应用安装、卸载处理
*
* @param args
* 安装、卸载参数
* @return Apk安装、卸载结果
*/
public static String apkProcess(String[] args) {
String result = null;
ProcessBuilder processBuilder = new ProcessBuilder(args);
Process process = null;
InputStream errIs = null;
InputStream inIs = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int read = -1;
process = processBuilder.start();
errIs = process.getErrorStream();
while ((read = errIs.read()) != -1) {
baos.write(read);
}
baos.write('\n');
inIs = process.getInputStream();
while ((read = inIs.read()) != -1) {
baos.write(read);
}
byte[] data = baos.toByteArray();
result = new String(data);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (errIs != null) {
errIs.close();
}
if (inIs != null) {
inIs.close();
}
} catch (Exception e) {
e.printStackTrace();
}
if (process != null) {
process.destroy();
}
}
return result;
}
}
最后,把MainActivity.class补充完整
package com.lsj.slient; import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast; public class MainActivity extends Activity implements OnClickListener { /**
* <pre>
* 需要安装的APK程序包所在路径
* 在Android4.2版本中,Environment.getExternalStorageDirectory().getAbsolutePath()得到的不一定是SDCard的路径,也可能是内置存储卡路径
* </pre>
*/
private static final String apkPath = Environment
.getExternalStorageDirectory().getAbsolutePath() + "/test.apk";
/**
* 要卸载应用的包名
*/
private static final String packageName = "com.example.directory"; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); findViewById(R.id.install).setOnClickListener(this);
findViewById(R.id.uninstall).setOnClickListener(this);
} @Override
public void onClick(View v) {
boolean isSucceed = false;
switch (v.getId()) {
case R.id.install:
isSucceed = ApkManager.install(apkPath);
if (isSucceed) {
Toast.makeText(MainActivity.this, "静默安装成功", Toast.LENGTH_SHORT)
.show();
} else {
Toast.makeText(MainActivity.this, "静默安装失败", Toast.LENGTH_SHORT)
.show();
}
break;
case R.id.uninstall:
isSucceed = ApkManager.uninstall(packageName);
if (isSucceed) {
Toast.makeText(MainActivity.this, "静默卸载成功", Toast.LENGTH_SHORT)
.show();
} else {
Toast.makeText(MainActivity.this, "静默卸载失败", Toast.LENGTH_SHORT)
.show();
}
break;
default:
break;
}
} }
OK,如此,静默安装、卸载就已经实现了!
作者:登天路
转载请说明出处:http://www.cnblogs.com/travellife/
源码下载:百度云盘
测试APK:百度云盘