为了让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 ; } } }