Android开发学习之路-插件安装、检查应用是否安装解决方案
使用Bmob的时候,如果需要用到支付功能,就需要让应用去安装一个支付插件。而一般的做法是将插件放置在assets目录中,当用户需要支付,先检查是否能支付,不能的话,提示安装插件。代码:
public class InstallHelper {
private static final String TAG = "InstallHelper";
private Context mContext;
InstallHelper(Context context) {
mContext = context;
}
void installAssetApk(String fileName) {
try {
InputStream is = this.mContext.getAssets().open(fileName);
File file = new File(mContext.getExternalCacheDir()+ File.separator +
"demo.apk");
if (file.exists()) {
file.delete();
}
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
byte[] bytes = new byte[1024];
int i;
while ((i = is.read(bytes)) > 0) {
fos.write(bytes, 0, i);
}
fos.close();
is.close();
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.parse("file://" + file), "application/vnd.android" + "" +
".package-archive");
mContext.startActivity(intent);
} catch (IOException e) {
e.printStackTrace();
}
}
}
我们不能直接执行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即可。
Android开发学习之路-插件安装、检查应用是否安装解决方案的更多相关文章
- Android开发学习之路--Android Studio cmake编译ffmpeg
最新的android studio2.2引入了cmake可以很好地实现ndk的编写.这里使用最新的方式,对于以前的android下的ndk编译什么的可以参考之前的文章:Android开发学习之路– ...
- Android开发学习之路--网络编程之xml、json
一般网络数据通过http来get,post,那么其中的数据不可能杂乱无章,比如我要post一段数据,肯定是要有一定的格式,协议的.常用的就是xml和json了.在此先要搭建个简单的服务器吧,首先呢下载 ...
- Android开发学习之路--Android系统架构初探
环境搭建好了,最简单的app也运行过了,那么app到底是怎么运行在手机上的,手机又到底怎么能运行这些应用,一堆的电子元器件最后可以运行这么美妙的界面,在此还是需要好好研究研究.这里从芯片及硬件模块-& ...
- Android开发学习之路--MAC下Android Studio开发环境搭建
自从毕业开始到现在还没有系统地学习android应用的开发,之前一直都是做些底层的驱动,以及linux上的c开发.虽然写过几个简单的app,也对android4.0.3的源代码做过部分的分析,也算入门 ...
- Android开发学习之路-RecyclerView滑动删除和拖动排序
Android开发学习之路-RecyclerView使用初探 Android开发学习之路-RecyclerView的Item自定义动画及DefaultItemAnimator源码分析 Android开 ...
- Android开发学习之路--基于vitamio的视频播放器(二)
终于把该忙的事情都忙得差不多了,接下来又可以开始good good study,day day up了.在Android开发学习之路–基于vitamio的视频播放器(一)中,主要讲了播放器的界面的 ...
- Android开发学习之路--Activity之初体验
环境也搭建好了,android系统也基本了解了,那么接下来就可以开始学习android开发了,相信这么学下去肯定可以把android开发学习好的,再加上时而再温故下linux下的知识,看看androi ...
- Android开发学习之路-Android Studio开发小技巧
上一次发过了一个介绍Studio的,这里再发一个补充下. 我们都知道,Android Studio的功能是非常强大的,也是很智能的.如果有人告诉你学Android开发要用命令行,你可以告诉他Andro ...
- Android开发学习之路--React-Native之初体验
近段时间业余在学node.js,租了个阿里云准备搭建后端,想用node.js,偶尔得知react-native可以在不同平台跑,js在iOS和android上都可以运行ok,今天就简单学习下rea ...
随机推荐
- TDD在Unity3D游戏项目开发中的实践
0x00 前言 关于TDD测试驱动开发的文章已经有很多了,但是在游戏开发尤其是使用Unity3D开发游戏时,却听不到特别多关于TDD的声音.那么本文就来简单聊一聊TDD如何在U3D项目中使用以及如何使 ...
- 使用JSONObject.fromObject的时候出现“There is a cycle in the hierarchy”异常 的解决办法
在使用JSONObject.fromObject的时候,出现“There is a cycle in the hierarchy”异常. 意思是出现了死循环,也就是Model之间有循环包含关系: ...
- C语言 · 整数平均值
编写函数,求包含n个元素的整数数组中元素的平均值.要求在函数内部使用指针操纵数组元素,其中n个整数从键盘输入,输出为其平均值. 样例输入: (输入格式说明:5为输入数据的个数,3 4 0 0 2 是以 ...
- input[tyle="file"]样式修改及上传文件名显示
默认的上传样式我们总觉得不太好看,根据需求总想改成和上下结构统一的风格…… 实现方法和思路: 1.在input元素外加a超链接标签 2.给a标签设置按钮样式 3.设置input[type='file' ...
- Hawk 5.1 数据导入和导出
除了一般的数据库导入导出,Hawk还支持从文件导入和导出,支持的文件类型包括: Excel CSV(逗号分割文本文件) TXT (制表符分割文本文件) Json xml Excel 目前来看,Exce ...
- H5坦克大战之【画出坦克】
今天是个特殊的日子,圣诞节,也是周末,在这里先祝大家圣诞快乐!喜庆的日子,我们可以稍微放松一下,扯一扯昨天雷霆对战凯尔特人的比赛,这场比赛大威少又双叒叕拿下三双,而且是一个45+11+11的超级三双, ...
- 著名ERP厂商的SSO单点登录解决方案介绍一
SSO英文全称Single Sign On,单点登录.SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.它包括可以将这次主要的登录映射到其他应用中用于同一个用户 ...
- 《CPU的工作过程》
本文转载自inter官方网址:https://software.intel.com/zh-cn/articles/book-Processor-Architecture_CPU_work_proces ...
- Linux.NET学习手记(8)
上一回合中,我们讲解了Linux.NET面对OWIN需要做出的准备,以及介绍了如何将两个支持OWIN协议的框架:SignalR以及NancyFX以OwinHost的方式部署到Linux.NET当中.这 ...
- 戴尔灵越15-5000/3558等系列修改BIOS设置U盘启动
今天在电脑群遇到一个群友的机型是戴尔灵越15-5000,他问我这款机器怎么设置U盘启动. 看到它的BIOS界面之后,我来了点兴趣.. 本文供图:辽宁沈阳-打老虎(921407164) 电脑群:电脑爱好 ...