情景:最近项目当中遇到一个问题,在A应用当中下载打开cebx文件,在6.0系统以下的手机当中正常打开,可在6.0以上的手机中总是报错闪退。打开厂家提供的demo运行在本地打开又没有问题,于是就想到直接把厂家提供的demo改改打包一个B应用,然后通过A应用调用B应用打开。没想到问题解决了,现在把问题记录一下,以供备用。
B应用设置:
首先:将B应用的activity的Manifest.xml文件
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
然后打包成APK文件
A应用设置:
1.获取手机安装应用列表
private void initpackagNameList() { // 初始化小模块列表 packagNameList = new ArrayList<String>(); PackageManager manager = this.getPackageManager(); List<PackageInfo> pkgList = manager.getInstalledPackages(0); for (int i = 0; i < pkgList.size(); i++) { PackageInfo pI = pkgList.get(i); packagNameList.add(pI.packageName.toLowerCase()); } }
2.设置监听广播
/** * * 设置广播监听 * */ private class MyReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED)) { String packName = intent.getDataString().substring(8); Log.e(intent.getDataString() + "====", packName); // package:cn.oncomm.activity cn.oncomm.activity // packName为所安装的程序的包名 packagNameList.add(packName.toLowerCase()); // 删除file目录下的所有以安装的apk文件 File file = getFilesDir(); File[] files = file.listFiles(); for (File f : files) { if (f.getName().endsWith(".apk")) { f.delete(); } } } } }
3.检查应是否安装
/** * 检测是否已经安装 * * @param packageName * @return true已安装 false未安装 */ private boolean detectApk(String packageName) { return packagNameList.contains(packageName.toLowerCase()); }
4.提示用户安装程序
5.捆绑安装/** *提示用户安装程序 */ public void showInstallConfirmDialog(final Context context, final String filePath) { AlertDialog.Builder tDialog = new AlertDialog.Builder(context); tDialog.setIcon(R.drawable.ic_launcher); tDialog.setTitle("cebx插件未安装"); tDialog.setMessage("请先安装cebx插件!!"); tDialog.setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // 修改apk权限 try { String command = "chmod " + "777" + " " + filePath; Runtime runtime = Runtime.getRuntime(); runtime.exec(command); } catch (IOException e) { e.printStackTrace(); } // install the apk. Intent intent = new Intent(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setDataAndType(Uri.parse("file://" + filePath), "application/vnd.android.package-archive"); context.startActivity(intent); } }); tDialog.setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { } }); tDialog.show(); }
关键代码:public boolean retrieveApkFromAssets(Context context, String fileName, String path) { boolean bRet = false; try { File file = new File(path); if (file.exists()) { return true; } else { file.createNewFile(); InputStream is = context.getAssets().open(fileName); FileOutputStream fos = new FileOutputStream(file); byte[] temp = new byte[1024]; int i = 0; while ((i = is.read(temp)) != -1) { fos.write(temp, 0, i); } fos.flush(); fos.close(); is.close(); bRet = true; } } catch (IOException e) { Toast.makeText(context, e.getMessage(), Toast.LENGTH_LONG).show(); AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setMessage(e.getMessage()); builder.show(); e.printStackTrace(); } return bRet; }
initpackagNameList(); receiver = new MyReceiver(); IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);// 注册广播机制 filter.addDataScheme("package"); // 必须添加这项,否则拦截不到广播 registerReceiver(receiver, filter); boolean installed = detectApk("com.gqoa.cebx"); if (installed) {// 已经安装直接起动 ComponentName componetName = new ComponentName( //这个是另外一个应用程序的包名 "com.gqoa.cebx", //这个参数是要启动的Activity "com.gqoa.cebx.CebxActivity"); Intent intent= new Intent("chroya.foo"); //Intent intent= new Intent(); //我们给他添加一个参数表示从apk1传过去的 Bundle bundle = new Bundle(); bundle.putString("file_path", file.getPath()); intent.putExtras(bundle); intent.setComponent(componetName); startActivity(intent); } else {// 未安装先安装 // // get the cacheDir. File fileDir = getFilesDir(); final String cachePath = fileDir.getAbsolutePath() + "/GqFlightView.apk"; retrieveApkFromAssets(FilesActivity.this, "GqFlightView.apk", cachePath); showInstallConfirmDialog(FilesActivity.this, cachePath); } }
注意:将apk文件放在assets目录下,如果需要将B应用设置为隐藏
<category android:name="android.intent.category.DEFAULT" />