zoukankan      html  css  js  c++  java
  • Android开发学习之路-插件安装、检查应用是否安装解决方案

    使用Bmob的时候,如果需要用到支付功能,就需要让应用去安装一个支付插件。而一般的做法是将插件放置在assets目录中,当用户需要支付,先检查是否能支付,不能的话,提示安装插件。代码:

     1 public class InstallHelper {
     2     private static final String TAG = "InstallHelper";
     3     private Context mContext;
     4 
     5     InstallHelper(Context context) {
     6         mContext = context;
     7     }
     8 
     9     void installAssetApk(String fileName) {
    10         try {
    11             InputStream is = this.mContext.getAssets().open(fileName);
    12             File file = new File(mContext.getExternalCacheDir()+ File.separator +
    13                     "demo.apk");
    14             if (file.exists()) {
    15                 file.delete();
    16             }
    17             file.createNewFile();
    18             FileOutputStream fos = new FileOutputStream(file);
    19             byte[] bytes = new byte[1024];
    20             int i;
    21             while ((i = is.read(bytes)) > 0) {
    22                 fos.write(bytes, 0, i);
    23             }
    24             fos.close();
    25             is.close();
    26             Intent intent = new Intent(Intent.ACTION_VIEW);
    27             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    28             intent.setDataAndType(Uri.parse("file://" + file), "application/vnd.android" + "" +
    29                     ".package-archive");
    30             mContext.startActivity(intent);
    31         } catch (IOException e) {
    32             e.printStackTrace();
    33         }
    34     }
    35 }

    我们不能直接执行assets下的安装包,所以这里的做法是先获得Assets目录的输入流。接着创建一个文件,这个文件用来存放我们从assets目录下读出的安装包内容。上述代码中的12和13行中,我们通过getExternalCacheDir()来获取主要存放的目录,再通过File.separator来插入一个路径分隔符,最后填上文件名来作为整个文件的绝对路径。这里有一个地方要说明,先看下面两个方法:

    getExternalCacheDir():获取应用目录下的cache目录,不需要读写权限,应用删除时也会删除

    getExternalStorageDirectory():获取主外部储存的根目录,需要读写权限,应用删除不会删除

    因为这个插件不需要共享给其他应用,所以我们需要使用第一个方法。如果使用了第二个,则会破坏掉用户外部储存的目录结构,毕竟无端的多出了一个文件,用户感觉当然是不好的。

    接着判断文件是否存在,若存在则重新建立。再创建一个byte数组来进行数据读写操作的辅助,不断地从输入流中读入数据,写到文件中。但是这里有一个问题要注意,我们传输的是一个安装包,只要最后传输的文件和assets目录下的安装包有一点不同,那么这个安装包都是不能使用的(安装会提示解析出错)。这里要留意的地方就是22行,这个write方法不能写错。

    如果我们直接使用:

    fos.write(bytes); // 相当于fos.write(bytes, 0, bytes.length),也就是把整个bytes数组写入输出流

     则这个传输就不正确了,这里先想想为什么?可以看到,我们定义了一个局部变量i来获取每次读入的大小,只要这个i的值不为-1,则循环一直进行。但是试想最后一次循环的时候,假设数据只有500个byte,那么我们直接调用fos.write(bytes)则是相当于把整一个bytes数组都写进输出流,但是实际上我们只需要前500个。

    当读写完全后,我们可以通过Intent来打开这个安装包,写法就是上面那样。


    另一个内容就是检查一个应用是否已经安装,例如我们在调用微信分享的时候,如果用户手机中没有微信,那么App将会没任何反应,这不会是是我们希望看到的,所以一般会先判断微信是否已经安装(其他应用类似)。

    判断一个App是否已经安装,我在StackOverFlow中看到的很多方法都是直接的使用PackageManager来获取所有Activity对应的PackageInfo,代码如下:

        private boolean isWechatInstall() {
            List<PackageInfo> installedPackages = getPackageManager().getInstalledPackages
                    (PackageManager.GET_ACTIVITIES);
            for (PackageInfo p : installedPackages) {
                if (p.packageName.equals("com.tencent.mm")) {
                    return true;
                }
            }
            return false;
        }

     实际上这样做是不行的。原因是系统中的应用Activity对应的Package是很多的,如果在短时间内对这些信息进行包装,则会抛出异常并终止处理(一般处理30个左右就会自动终止),因为这个异常不是RuntimeException,所以我们的App也不会Crash掉,只是结果不正确。 

    正确的做法应该是这样:

        private boolean isAppInstalled(String packageName) {
            PackageManager pm = getPackageManager();
            boolean installed;
            try {
                pm.getPackageInfo(packageName, PackageManager
                        .GET_ACTIVITIES);
                installed = true;
            } catch (PackageManager.NameNotFoundException e) {
                installed = false;
            }
            return installed;
        }

    直接根据包名获取其PackageInfo对象,如果不存在,则在抛出的异常中返回false即可。 

  • 相关阅读:
    第3关:求三位数各位数字的和
    第4关:求三角形的面积
    第6关:输出杨辉三角
    最短路 模板 【bellman-ford,dijkstra,floyd-warshall】
    hdu 1874 畅通工程 【spfa and dijkstra实现】
    01背包问题 总结关于为什么01背包优化成1维数组后,内层循环是逆序的?
    Stein算法求最大公约数
    hdu 1576 A/B 【扩展欧几里德】
    树状数组之 ——区间更新,单点查询;区间更新,区间查询;
    差分数组
  • 原文地址:https://www.cnblogs.com/Fndroid/p/5708981.html
Copyright © 2011-2022 走看看