为了让APP能够顺利升级,分为有内存卡状态和无内存卡状态(内置内存卡状态下的路径难以确定,通过反射获取必须是3.0以上,暂时不予以考虑)。


无内存卡的情况下,手机中的哪些空间可以使用呢 ?


data/data/pkgname/files/


data/data/pkgname/cache/



于是将新版本的app(文件名为update-1.1.0.apk)下载到files下,然后进行install,结果提示解析错误


190322748.png

Why?将这个apk文件copysdcard上,点击,能够安装,排除apk文件不完整的问题。


进到shell,执行ls命令查看权限情况

190344738.png



可以看到update-1.1.0.apk只有自己读写权限。安装apk都是通过调用的系统的打包安装程序(PackageInstaller.apk)进行安装,很显然PackageInstalller打包安装程序没有相关的执行权限。


执行chmod命令将其权限改为606


190419633.png

然后再进行安装,成功。



所以无内存卡升级(没有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 ; 
        } 
    } 
}