安卓实现安装已有apk到系统目录下和安装apk自身到系统目录下

手机一定要root ,没有root 实现不了,安装其他apk是参考网上的资料的,安装自身apk原理上差不多。不管哪样,安装完后要重启手机才能看到。这也是一个没解决的问题。

安装其他apk:tom.apk

要安装的tom.apk要事先存储在手机存储的根目录下。通过在代码中执行linux命令来将tom.apk安装到system/app目录下。其实实际上是把这个tom.apk文件拷贝到了system/app目录下。所以安装完成后要重启手机才能看到tom.apk的图标。

这一部分参考:http://bbs.csdn.net/topics/390171063

具体的解释都在代码里了,直接上代码:


安装apk自身:

  将apk自身安装到系统system/app目录下。手机需要root
 原理:和将其他apk安装到系统目录下是一样的,首先本项目是一个扮演Installer身份的apk.
需要事先创建真正要安装的apk(比如installmyself2systemappentity.apk),将这个apk放在本项目的res/raw目录下。

 经测试以上均成功,但是出现新问题:就是这个installer也会存在桌面上,
所以最后还得调用系统程序,将这个installer卸载。


这是基于我的水平能想到的方法了,可能够笨的,但是要求的功能还是实现了,大家有什么好的想法可以交流一下。

RootCmd.java

/**
 * 执行安装到system/app功能的主要类
 */
package com.example.installmyself2systemapp;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

public final class RootCmd {
	// 执行linux命令并且输出结果
	protected static String execRootCmd(String paramString) {
		String result = "result : ";
		try {
			Process localProcess = Runtime.getRuntime().exec("su ");// 经过Root处理的android系统即有su命令
			OutputStream localOutputStream = localProcess.getOutputStream();
			DataOutputStream localDataOutputStream = new DataOutputStream(
					localOutputStream);
			InputStream localInputStream = localProcess.getInputStream();
			DataInputStream localDataInputStream = new DataInputStream(
					localInputStream);
			String str1 = String.valueOf(paramString);
			String str2 = str1 + "\n";
			localDataOutputStream.writeBytes(str2);
			localDataOutputStream.flush();
			String str3 = null;
			// while ((str3 = localDataInputStream.readLine()) != null) {
			// Log.d("result", str3);
			// }
			localDataOutputStream.writeBytes("exit\n");
			localDataOutputStream.flush();
			localProcess.waitFor();
			return result;
		} catch (Exception localException) {
			localException.printStackTrace();
			return result;
		}
	}

	// 执行linux命令但不关注结果输出
	protected static int execRootCmdSilent(String paramString) {
		try {
			Process localProcess = Runtime.getRuntime().exec("su");
			Object localObject = localProcess.getOutputStream();
			DataOutputStream localDataOutputStream = new DataOutputStream(
					(OutputStream) localObject);
			String str = String.valueOf(paramString);
			localObject = str + "\n";
			localDataOutputStream.writeBytes((String) localObject);
			localDataOutputStream.flush();
			localDataOutputStream.writeBytes("exit\n");
			localDataOutputStream.flush();
			localProcess.waitFor();
			int result = localProcess.exitValue();
			return (Integer) result;
		} catch (Exception localException) {
			localException.printStackTrace();
			return -1;
		}
	}

	// 判断机器Android是否已经root,即是否获取root权限
	protected static boolean haveRoot() {

		int i = execRootCmdSilent("echo test"); // 通过执行测试命令来检测
		if (i != -1) {
			return true;
		}
		return false;
	}

}
以上这个类的代码是参考网上资料的。


MainActivity.java

mainactivity.java的流程是安装apk自身的流程,但是其中包含了安装其他apk的方法,只要提取出来beginInstall()这个方法单独用就行了

/**
 * 本项目实现了将apk自身安装到系统system/app目录下。手机需要root
 * 原理:和将其他apk安装到系统目录下是一样的,首先本项目是一个扮演Installer身份的apk.
 * 需要事先创建真正要安装的apk,将这个apk放在本项目的res/raw目录下。
 * 然后启动本apk,首先将真正的apk复制到手机存储上,然后就和安装其他apk步骤一样了。
 * 
 * 经测试以上均成功,但是出现新问题:就是这个installer也会存在桌面上,
 * 所以最后还得调用系统程序,将这个installer卸载。
 * 
 */
package com.example.installmyself2systemapp;


import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.PrintWriter;


import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.view.Menu;
import android.widget.Toast;


public class MainActivity extends Activity {


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 如果复制成功,则开始安装
boolean copyOK = exportAPK2Phone();
if (copyOK) {
beginInstall();
}
uninstall("com.example.installmyself2systemapp",this);
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}


// 将res/raw目录下的文件拷贝出来
private boolean exportAPK2Phone() {
String filePath = Environment.getExternalStorageDirectory()
+ "/installmyself2systemappentity.apk";// 文件路径
File file = null;
try {
// 目录存在,则将apk中raw中的需要的文档复制到该目录下
file = new File(filePath);
if (!file.exists()) {// 文件不存在
System.out.println("要打开的文件不存在");
InputStream ins = getResources().openRawResource(
R.raw.installmyself2systemappentity);// 通过raw得到数据资源
System.out.println("开始读入");
FileOutputStream fos = new FileOutputStream(file);
System.out.println("开始写出");
byte[] buffer = new byte[8192];
int count = 0;// 循环写出
while ((count = ins.read(buffer)) > 0) {
fos.write(buffer, 0, count);
}
System.out.println("已经创建该文件");
fos.close();// 关闭流
ins.close();
}
} catch (Exception e) {
e.printStackTrace();
}


if (file != null && file.exists()) {
return true;
}
return false;
}


// 开始安装手机存储上的apk
public void beginInstall() {
String apkName = "installmyself2systemappentity.apk";
// 组装要执行的linux命令
String paramString = "adb push " + apkName + " /system/app"
+ "\n" // 上传要安装的文件,为安装做准备
+ "adb shell" + "\n" + "su"
+ "\n" // 切换到root用户,手机必须已经root
+ "mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system"
+ "\n" // 让分区可写
+ "cat /sdcard/" + apkName + " > /system/app/" + apkName + "\n" // 相当于赋值的过程
+ "chmod  644 /system/app/" + apkName + "\n" // 更改复制后的文件的权限
// 刚开始是rw-------,更改为rw-r--r--
+ "mount -o remount,ro -t yaffs2 /dev/block/mtdblock3 /system" // 还原属性,只读
+ "\n" + "exit" + "\n" + "exit";


if (RootCmd.haveRoot()) { // 如果已经root
// 执行安装并返回结果
if (RootCmd.execRootCmdSilent(paramString) == -1) {
Toast.makeText(this, "安装不成功", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "安装成功", Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(this, "没有root权限", Toast.LENGTH_LONG).show();
}

//以上就是单纯安装其他apk的方法

clearEntityFile();
}


// 安装完成后为了掩人耳目,将复制出来的apk删除。
public void clearEntityFile() {
String filePath = Environment.getExternalStorageDirectory()
+ "/installmyself2systemappentity.apk";// 文件路径
File f = new File(filePath);
if (f.exists()) {
f.delete();
}
}


//卸载Installer自身:是否是静默卸载? 
public static boolean uninstall(String packageName,Context context){
if(RootCmd.haveRoot()){
// 有root权限,利用静默卸载实现
return clientUninstall(packageName);
}else{
Uri packageURI = Uri.parse("package:" + packageName);
Intent uninstallIntent = new Intent(Intent.ACTION_DELETE,packageURI);
uninstallIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(uninstallIntent);
return true;
}
}

/**
* 静默卸载
*/
private static boolean clientUninstall(String packageName){
PrintWriter PrintWriter = null;
Process process = null;
try {
process = Runtime.getRuntime().exec("su");
PrintWriter = new PrintWriter(process.getOutputStream());
PrintWriter.println("LD_LIBRARY_PATH=/vendor/lib:/system/lib ");
PrintWriter.println("pm uninstall "+packageName);
PrintWriter.flush();
PrintWriter.close();
int value = process.waitFor();  
// 代表成功  
if (value == 0) {
return true;
} else if (value == 1) { // 失败
return false;
} else { // 未知情况
return false;

} catch (Exception e) {
e.printStackTrace();
}finally{
if(process!=null){
process.destroy();
}
}
return false;
}


}

AndroidManifest.xml 记得加权限

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.installmyself2systemapp"
    android:versionCode="1"
    android:versionName="1.0" >


    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />


    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.installmyself2systemapp.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>

目录结构:再次注意,当安装apk自身时,res/raw目录下的installmyself2systemappentity.apk才是真正要安装的apk.

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值