package org.acra.util;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.acra.ACRA;
import static org.acra.ACRA.LOG_TAG;
/**
* Responsible for wrapping calls to PackageManager to ensure that they always complete without throwing RuntimeExceptions.
* Depending upon the state of the application it is possible that
* <ul>
* <li>Context has no PackageManager.</li>
* <li>PackageManager returned by Context throws RuntimeException("Package manager has died")
* because it cannot contact the remote PackageManager service.
* </li>
* </ul>
* I suspect that PackageManager death is caused during app installation.
* But we need to make ACRA bullet proof, so it's better to handle the condition safely so that the error report itself doesn't fail.
*
* @author William Ferguson
* @since 4.3.0
*/
public final class PackageManagerWrapper {
private final Context context;
public PackageManagerWrapper(@NonNull Context context) {
this.context = context;
}
/**
* @param permission Manifest.permission to check whether it has been granted.
* @return true if the permission has been granted to the app, false if it hasn't been granted or the PackageManager could not be contacted.
*/
public boolean hasPermission(@NonNull String permission) {
final PackageManager pm = context.getPackageManager();
if (pm == null) {
return false;
}
try {
return pm.checkPermission(permission, context.getPackageName()) == PackageManager.PERMISSION_GRANTED;
} catch (Throwable e) {
// To catch RuntimeException("Package manager has died") that can occur on some version of Android,
// when the remote PackageManager is unavailable. I suspect this sometimes occurs when the App is being reinstalled.
return false;
}
}
/**
* @return PackageInfo for the current application or null if the PackageManager could not be contacted.
*/
@Nullable
public PackageInfo getPackageInfo() {
final PackageManager pm = context.getPackageManager();
if (pm == null) {
return null;
}
try {
return pm.getPackageInfo(context.getPackageName(), 0);
} catch (PackageManager.NameNotFoundException e) {
ACRA.log.w(LOG_TAG, "Failed to find PackageInfo for current App : " + context.getPackageName());
return null;
} catch (Throwable e) {
// To catch RuntimeException("Package manager has died") that can occur on some version of Android,
// when the remote PackageManager is unavailable. I suspect this sometimes occurs when the App is being reinstalled.
return null;
}
}
}