为了让APP能够顺利升级,分为有内存卡状态和无内存卡状态(内置内存卡状态下的路径难以确定,通过反射获取必须是3.0以上,暂时不予以考虑)。
无内存卡的情况下,手机中的哪些空间可以使用呢 ?
data/data/pkgname/files/
data/data/pkgname/cache/
于是将新版本的app(文件名为update-1.1.0.apk)下载到files下,然后进行install,结果提示解析错误
Why?将这个apk文件copy到sdcard上,点击,能够安装,排除apk文件不完整的问题。
进到shell,执行ls命令查看权限情况
可以看到update-1.1.0.apk只有自己读写权限。安装apk都是通过调用的系统的打包安装程序(PackageInstaller.apk)进行安装,很显然PackageInstalller打包安装程序没有相关的执行权限。
执行chmod命令将其权限改为606
然后再进行安装,成功。
所以无内存卡升级(没有root权限的情况下)的步骤如下:
1.下载到升级文件到/data/data/pkgname/files/
2.代码执行shell命令,修改升级文件的执行权限:chmod 607 filepath/filename
3.进行安装
上代码:
package com.example.insatllapkfrominternalstorage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
private Button btn_cpy,btn_install,btn_chmod;
private InputStream in=null;
private OutputStream out= null;
String path = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_cpy=(Button)findViewById(R.id.cpy);
btn_install= (Button)findViewById(R.id.install);
btn_chmod = (Button)findViewById(R.id.chmod);
path = MainActivity.this.getFilesDir().toString()+File.separator+"update-1.1.0.apk";
btn_cpy.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {new Thread(){public void run() {
new File(path).deleteOnExit();
try {
in = MainActivity.this.getAssets().open("update-1.1.0.apk");
out = new FileOutputStream(new File(path));
byte[] buffer = new byte[1024];
int offset =0;
while ((offset = in.read(buffer, 0, 1024)) != -1) {
out.write(buffer, 0, offset);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(null!=out){
try {
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(null!=in){
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Log.i("cpy", "cpy end");
}
};}.start();}
});
btn_install.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(null==path)return;
File f = new File(path);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file://" + f),
"application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainActivity.this.startActivity(intent);
}
});
btn_chmod.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
if(null==path)return;
ShellExecute ex = new ShellExecute();
String[] cmd = {"chmod","607",path};
try {
ex.execute(cmd, "/");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
private class ShellExecute {
/*
* args[0] : shell 命令 如"ls" 或"ls -1";
* args[1] : 命令执行路径 如"/" ;
*/
public String execute ( String [] cmmand,String directory)
throws IOException {
String result = "" ;
try {
ProcessBuilder builder = new ProcessBuilder(cmmand);
if ( directory != null )
builder.directory ( new File ( directory ) ) ;
builder.redirectErrorStream (true) ;
Process process = builder.start ( ) ;
//得到命令执行后的结果
InputStream is = process.getInputStream ( ) ;
byte[] buffer = new byte[1024] ;
while ( is.read(buffer) != -1 ) {
result = result + new String (buffer) ;
}
is.close ( ) ;
} catch ( Exception e ) {
e.printStackTrace ( ) ;
}
return result ;
}
}
}
转载于:https://blog.51cto.com/vincenttung/1318716