I need to be able to push out updates to a private app (doesn't exist on Play Store) by checking for a newer version (via versionCode/versionName) of an apk hosted somewhere*.
I believe I've got all the code I need- connect to Dropbox, download the file, trigger broadcast receiver to check the version and install the app if newer than current is available.
My issue is that getPackageArchiveInfo always returns null on the downloaded apk.
Note: I am able to manually install the app after it has been downloaded (the file is not corrupt), but I need this process to be automated.
*using Dropbox in this example, but this will not be what prod uses.
I've used a few different resources to build and try to debug my issues, see:
Android: install .apk programmatically
Android install apk with Intent.VIEW_ACTION not working with File provider
The compileSdkVersion is 27, minSdkVersion and targetSdkVersion are 23. This configuration is crucial and cannot be changed.
I am primarily testing on an emulator set to the specific configuration that the production device will be using, but I also am using a Galaxy S6 to test.
MainActivity:
public void onCheckClick(View view) {
try {
String versionName = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
txtCurrent.setText("Current: " + versionName);
String url = apkLocation;
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDescription("description");
request.setTitle("app-debug.apk");
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "app-debug.apk");
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
public void onUpdateClick(View view) {
Intent installIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
installIntent.setDataAndType(Uri.parse("file:///storage/emulated/0/Download/app-debug.apk"), "application/vnd.android.package-archive");
startActivity(installIntent);
}
DownloadBroadcastReceiver:
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)){
//do stuff
PackageManager pm = context.getPackageManager();
String apkName = "app-debug.apk";
String fullPath = Environment.DIRECTORY_DOWNLOADS + "/" + apkName;
PackageInfo info = pm.getPackageArchiveInfo(fullPath, 0);
Toast.makeText(context, info.packageName, Toast.LENGTH_LONG).show();
}
}
AndroidManifest:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".DownloadBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
</intent-filter>
</receiver>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
</application>
Expected: Grab the version information from the downloaded apk, then be able to install that apk if it has a newer version.
Actual: Version information is null, and therefore cannot continue the process.