Моя Android активность / приложение использует DownloadManager и PackageInstaller для обновления. Я опубликую соответствующий код здесь, но суть в том, что файл успешно загружается, но не устанавливается, и в LogCat нет полезной информации, которая бы помогла мне понять, почему.
Если с моим кодом что-то не так, я Мне бы очень хотелось это знать, но, насколько я знаю, я поступаю так, как говорят все примеры. Я попытался сделать это с и без установки DeviceOwner, и вижу то же самое поведение в любом случае. Ничего не происходит, и в LogCat нет ничего, что указывало бы на то, что пошло не так.
Я попытался подключить метод обратного вызова сеанса, но не могу получить какую-либо информацию, потому что мой 'sessionInfo' всегда равен NULL. Как это вообще возможно?
pkgInstaller.registerSessionCallback(new PackageInstaller.SessionCallback() {
PackageInstaller.SessionInfo sessionInfo = pkgInstaller.getSessionInfo(sID);
}
Часть загрузки работает успешно, поэтому я просто покажу соответствующую строку здесь.
File downloadFile = new File(getExternalFilesDir(null),"myapp-update.apk");
apk была построена в Android Studio с использованием «Build -> Build Bundle (s) -> APK (s) -> Build APK (s)», который выдает «отладочный» APK (так же, как если бы я собирал и развертывал в устройство из IDE). Он был создан с НОВЫМИ VersionID и VersionName, а затем загружен на мой файловый сервер. Мое Android приложение загружает его с помощью DownloadManager, и оно работает.
Вот что происходит после загрузки APK.
private BroadcastReceiver onDownloadComplete = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
// Get our download record, verify it, etc.
// ......
// Get URI of downloaded file
int uriIndex = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI);
String apkStr = cursor.getString(uriIndex);
// Install APK update
Uri apkUri = Uri.parse(apkStr);
installApk(Objects.requireNonNull(apkUri.getPath()));
}
}
Вот метод, который устанавливает APK после загрузки.
public static final String ACTION_INSTALL_COMPLETE = BuildConfig.APPLICATION_ID + ".INSTALL_COMPLETE";
private void installApk(String apkFilePath)
{
try
{
// Create package manager installation params
PackageInstaller pkgInstaller = getBaseContext().getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
params.setAppPackageName(this.getPackageName());
// Create package manager installation session
int sessionId = pkgInstaller.createSession(params);
PackageInstaller.Session session = pkgInstaller.openSession(sessionId);
// Get size of downloaded APK
long sizeBytes = 0;
final File file = new File(apkFilePath);
if (file.isFile())
sizeBytes = file.length();
// Stream downloaded APK file to package manager session
InputStream in = new FileInputStream(apkFilePath);
OutputStream out = session.openWrite("konektv_update_session", 0, -1);
byte[] buffer = new byte[65536];
int bytesRead = in.read(buffer);
while (bytesRead != -1)
{
out.write(buffer, 0, bytesRead);
bytesRead = in.read(buffer);
}
// Close streams
session.fsync(out);
out.close();
in.close();
// Close session
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, sessionId, new Intent(ACTION_INSTALL_COMPLETE),0);
session.commit(pendingIntent.getIntentSender());
session.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
Мой специальный приемник вещания для установки APK выглядит следующим образом. Он никогда не вызывается, и загруженный APK не установлен. Я могу сказать, потому что ничего не происходит, но даже если это так, я отображаю номер версии, и он не меняется.
public class UpdateReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
final String LOG_TAG = "myapp-updated";
if (intent == null)
return;
String action = intent.getAction();
if ((action == null) || !action.equalsIgnoreCase(Intent.ACTION_MY_PACKAGE_REPLACED))
return;
// Start main activity
Intent intentMain = new Intent(context, MainActivity.class);
intentMain.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intentMain.putExtra(KonekTvApplication.IS_BOOT_AUTOSTART, true);
context.startActivity(intentMain);
}
}
Вот соответствующие биты из моего файла AndroidManifest. xml.
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
<application
android:testOnly="true"
android:name=".MyApplication">
<receiver
android:name=".UpdateReceiver">
<intent-filter >
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
</intent-filter>
</receiver>
Единственный другой код связан с DeviceOwner, но эта методология должна работать независимо от владельца устройства. Единственная разница заключается в том, является ли обновление тихим или требует взаимодействия с пользователем.
public class DeviceOwnerReceiver extends DeviceAdminReceiver
{
private static final String LOG_TAG = "my-owner-receiver";
@Override
public void onEnabled(Context context, Intent intent) {
Log.w(LOG_TAG,"Device owner enabled");
}
public static ComponentName getComponentName(Context context) {
return new ComponentName(context.getApplicationContext(), DeviceOwnerReceiver.class);
}
}
Вот информация о владельце устройства из AndroidManifest. xml.
<receiver
android:name=".DeviceOwnerReceiver"
android:label="@string/app_name"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/device_admin" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
А вот device_admin. xml file.
<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-policies>
</uses-policies>
</device-admin>
Большое спасибо за любую помощь, которую вы можете предоставить.