Android development and learning path-plugin installation, check whether the application is installed with a solution, and android path
When using Bmob, if you need to use the payment function, you need to have the application install a payment plug-in. The general practice is to place the plug-in the assets Directory. When the user needs to pay, check whether the plug-in can be paid. If not, prompt to install the plug-in. Code:
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 }
We cannot directly execute the installation package under assets. Therefore, we first obtain the input stream of the Assets Directory. Create a file to store the content of the installation package that we read from the assets Directory. In the 12 and 13 lines of the above Code, we use getExternalCacheDir () to obtain the primary directory, and then use File. separator to insert a path separator, and finally fill in the file name as the absolute path of the entire file. Here is a description. Let's take a look at the following two methods:
GetExternalCacheDir (): gets the cache directory under the application directory. The read and write permissions are not required and will be deleted when the application is deleted.
GetExternalStorageDirectory (): Get the root directory of the primary external store. read and write permissions are required. Deleting an application will not be deleted.
Because this plug-in does not need to be shared with other applications, we need to use the first method. If the second one is used, the directory structure stored externally by the user will be damaged. After all, a file is added without reason, and the user may feel bad.
Then determine whether the file exists. If yes, create a new one. Create a byte array to help read and write data. It constantly reads data from the input stream and writes it to the file. However, there is a problem here. We transmit an installation package, as long as the final file transmitted is a little different from the installation package under the assets Directory, the installation package cannot be used (a parsing error is prompted during installation ). The note here is 22 rows. This write method cannot be written incorrectly.
If we use:
Fos. write (bytes); // equivalent to fos. write (bytes, 0, bytes. length), that is, write the entire bytes array to the output stream
This transmission is incorrect. Here, let's first think about why? We can see that we define a local variable I to get the size of each read, as long as the value of this I is not-1, the loop continues. However, if we assume that there are only 500 bytes in the last loop, we call fos directly. write (bytes) is equivalent to writing the entire bytes array into the output stream, but in fact we only need the first 500.
When the read and write operations are complete, you can use Intent to open the installation package.
The other content is to check whether an application has been installed. For example, when we call share, if the user's mobile phone does not exist, the App will not respond, this is not what we want to see, so we usually determine whether the installation is successful (similar to other applications ).
To determine whether an App has been installed, many of the methods I have seen in StackOverFlow use PackageManager to obtain PackageInfo corresponding to all activities. The Code is as follows:
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; }
In fact, this cannot be done. The reason is that there are many packages corresponding to the application Activity in the system. If you Package the information in a short time, an exception will be thrown and the processing will be terminated (generally, it will be automatically terminated after about 30 processes). Because this exception is not a RuntimeException, our App will not Crash it, but the result is incorrect.
The correct method should be as follows:
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; }
Obtain the PackageInfo object based on the package name. If the object does not exist, return false in the thrown exception.