Устанавливайте приложения без помощи разрешения INSTALL_PACKAGES

Я пытаюсь тихо установить apk в систему. Мое приложение расположено в / system / app и успешно предоставлено разрешение «android.permission.INSTALL_PACKAGES»

Однако я не могу найти, как использовать это разрешение. Я попытался скопировать файлы в / data / app и не имел успеха. Также я попытался использовать этот код

Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType( Uri.parse("file:///sdcard/app.apk"), "application/vnd.android.package-archive"); startActivity(intent); 

Но этот код открывает стандартный диалог установки. Как я могу установить приложение без использования root с предоставленным android.permission.INSTALL_PACKAGES ?

PS Я пишу приложение, которое установит много apks из папки в систему при первом запуске (замените Мастер установки). Мне нужно, чтобы упростить прошивку.

Если вы думаете, что я пишу вирус: все программы установлены в / data / app. Разрешение Install_packages может быть предоставлено только программам системного уровня, расположенным в / system / app или подписанным с системным ключом. Таким образом, вирус не может попасть туда.

Как сказано в http://www.mail-archive.com/android-porting@googlegroups.com/msg06281.html приложениях МОЖЕТ быть установлена ​​без установки, если у них есть разрешение install_packages. Кроме того, вам не требуется разрешение Install_packages для установки пакетов не тихо. Плюс http://www.androidzoom.com/android_applications/tools/silent-installer_wgqi.html

Ваша первая ставка – посмотреть на собственный пакет PackageInstaller от Android. Я бы рекомендовал изменить это приложение так, как вам нравится, или просто извлечь требуемую функциональность.


В частности, если вы посмотрите на PackageInstallerActivity и его метод onClickListener :

  public void onClick(View v) { if(v == mOk) { // Start subactivity to actually install the application Intent newIntent = new Intent(); ... newIntent.setClass(this, InstallAppProgress.class); ... startActivity(newIntent); finish(); } else if(v == mCancel) { // Cancel and finish finish(); } } 

Затем вы заметите, что фактический установщик находится в классе InstallAppProgress . initView этот класс, вы обнаружите, что initView является основной установкой, и последнее, что он делает, это вызвать функцию installPackage :

 public void initView() { ... pm.installPackage(mPackageURI, observer, installFlags, installerPackageName); } 

Следующий шаг – проверить PackageManager , который является абстрактным классом. Здесь вы найдете installPackage(...) . Плохая новость в том, что она отмечена знаком @hide. Это означает, что он не доступен напрямую (вы не сможете скомпилировать его с помощью вызова этого метода).

  /** * @hide * .... */ public abstract void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,String installerPackageName); 

Но вы сможете получить доступ к этим методам посредством отражения.

Если вас интересует, как installPackage функция installPackage , взгляните на PackageManagerService .

Резюме

Вам нужно будет получить объект менеджера пакетов через getPackageManager() Context . Затем вы вызываете функцию installPackage через отражение.

Я проверил, как ADB устанавливает приложения.
– Он копирует APK в / data / local / tmp
– он запускает оболочку: pm install /data/local/tmp/app.apk '

Я попытался воспроизвести это поведение, выполнив: (на ПК, используя usb-кабель)
adb push app.apk /sdcard/app.apk
adb shell
$ pm install /sdcard/app.apk
Это работает. Приложение установлено.

Я сделал приложение (с именем AppInstall), которое должно установить другое приложение.
(Установленное нормально, не закрепленное устройство)
Оно делает:
Runtime.getRuntime().exec("pm install /sdcard/app.apk").waitFor();
Но это дает ошибку:
java.lang.SecurityException: Neither user 10019 nor current process has android.permission.INSTALL_PACKAGES.
Похоже, что ошибка порождается pm, а не AppInstall.
Поскольку SecurityException не улавливается AppInstall, и приложение не сбой.

Я пробовал то же самое на корневом устройстве (такое же приложение и AppInstall), и он работал как шарм.
(Также обычно устанавливается, а не в / система или что-то еще)
AppInstall даже не попросил разрешения root.
Но это потому, что оболочка всегда # вместо $ на этом устройстве.

Кстати, вам нужно root для установки приложения в / system, правильно?
Я попробовал adb remount на неуправляемом устройстве и получил:
remount failed: Operation not permitted.
Вот почему я не мог попробовать / system на не-корневом устройстве.

Вывод: вы должны использовать укорененное устройство
Надеюсь это поможет 🙂

Вы должны определить

 <uses-permission android:name="android.permission.INSTALL_PACKAGES" /> 

В вашем манифесте, тогда, если вы находитесь в системном разделе (/ system / app) или у вас есть приложение, подписанное производителем, у вас будет разрешение INSTALL_PACKAGES.

Мое предложение состоит в том, чтобы создать небольшой проект андроида с 1,5 уровня совместимости, используемый для вызова installPackages через отражение и для экспорта банку с помощью методов для установки пакетов и вызова реальных методов. Затем, импортируя банку в свой проект, вы будете готовы к установке пакетов.

Я понятия не имел, как это сделать, потому что никто не отвечал в то время, и я не нашел документацию об этом разрешении. Поэтому я нашел свое решение. Это хуже, чем ваше, но это решение в любом случае.

Я установил busybox, который установил разрешение 777 / data / app (я не забочусь о безопасности). Затем просто выполните «busybox install» из приложения. Это работает, но имеет большую утечку безопасности. Если вы устанавливаете разрешения 777, root не требуется.

Вот очень хороший пост на эту тему. Это мне очень помогло.

Вы можете просто использовать команду adb install для установки / обновления APK. Пример кода ниже

 public static void InstallAPK(String filename){ File file = new File(filename); if(file.exists()){ try { String command; filename = StringUtil.insertEscape(filename); command = "adb install -r " + filename; Process proc = Runtime.getRuntime().exec(new String[] { "su", "-c", command }); proc.waitFor(); } catch (Exception e) { e.printStackTrace(); } } } 

Я пробовал на корневом Android 4.2.2, и этот метод работает для меня:

 private void installApk(String filename) { File file = new File(filename); if(file.exists()){ try { final String command = "pm install -r " + file.getAbsolutePath(); Process proc = Runtime.getRuntime().exec(new String[] { "su", "-c", command }); proc.waitFor(); } catch (Exception e) { e.printStackTrace(); } } } 

Вы можете использовать скрытый API android.content.pm.IPackageInstallObserver путем отражения:

 public class PackageManagement { public static final int INSTALL_REPLACE_EXISTING = 0x00000002; public static final int INSTALL_SUCCEEDED = 1; private static Method installPackageMethod; private static Method deletePackageMethod; static { try { installPackageMethod = PackageManager.class.getMethod("installPackage", Uri.class, IPackageInstallObserver.class, Integer.TYPE, String.class); } catch (NoSuchMethodException e) { e.printStackTrace(); } } public static void installPackage(PackageManager pm, Uri mPackageUri, IPackageInstallObserver observer, int installFlags, String installerPackageName) { try { installPackageMethod.invoke(pm, mPackageUri, observer, installFlags, installerPackageName); } catch (Exception e) { e.printStackTrace(); } } } 

Импортируйте файл android.content.pm.IPackageInstallObserver в свой проект. Ваше приложение должно быть системным. Вы должны активировать разрешение android.permission.INSTALL_PACKAGES в вашем файле манифеста.

Я недавно внедрял установку без согласия пользователя – это приложение для киоска для уровня API 21+, где у меня был полный контроль над средой.

Основные требования

  • Уровень API 21+
  • Root для установки обновления в качестве приложения с привилегиями системы.

Следующий метод считывает и устанавливает APK из InputStream:

 public static boolean installPackage(Context context, InputStream in, String packageName) throws IOException { PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller(); PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( PackageInstaller.SessionParams.MODE_FULL_INSTALL); params.setAppPackageName(packageName); // set params int sessionId = packageInstaller.createSession(params); PackageInstaller.Session session = packageInstaller.openSession(sessionId); OutputStream out = session.openWrite("COSU", 0, -1); byte[] buffer = new byte[65536]; int c; while ((c = in.read(buffer)) != -1) { out.write(buffer, 0, c); } session.fsync(out); in.close(); out.close(); Intent intent = new Intent(context, MainActivity.class); intent.putExtra("info", "somedata"); // for extra data if needed.. Random generator = new Random(); PendingIntent i = PendingIntent.getActivity(context, generator.nextInt(), intent,PendingIntent.FLAG_UPDATE_CURRENT); session.commit(i.getIntentSender()); return true; } 

Следующий код вызывает установку

  try { InputStream is = getResources().openRawResource(R.raw.someapk_source); installPackage(MainActivity.this, is, "com.example.apk"); } catch (IOException e) { Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show(); } 

Для всего, что нужно работать, вам отчаянно требуется разрешение INSTALL_PACKAGES , или код выше не будет работать молча

 <uses-permission android:name="android.permission.INSTALL_PACKAGES" /> 

Для получения этого разрешения вы должны установить APK в качестве системного приложения, которое НЕОБХОДИМО использовать root (однако ПОСЛЕ того, как вы установили приложение для обновления, оно, похоже, работает WITHOUT root)

Для установки в качестве системного приложения я создал подписанный APK и нажал его

 adb push updater.apk /sdcard/updater.apk 

А затем переместил его в system/priv-app – для чего требуется перезагрузка FS (поэтому необходим корень)

 adb shell su mount -o rw,remount /system mv /sdcard/updater.apk /system/priv-app chmod 644 /system/priv-app/updater.apk 

По какой-то причине он не работал с простой отладочной версией, но logcat показывает полезную информацию, если по priv-app то причине ваше приложение в priv-app не подхвачено.

Я сделал тестовое приложение для бесшумной установки, используя метод PackageManager.installPackage.

Я получаю метод installPackage через отражение, и сделал интерфейс android.content.pm.IPackageInstallObserver в моей папке src (потому что он скрыт в пакете android.content.pm).

Когда я запускаю installPackage, я получил SecurityException со строковой индикацией, что у моего приложения нет файла android.permission.INSTALL_PACKAGES, но он определен в AndroidManifest.xml.

Поэтому, я думаю, использовать этот метод невозможно.

PS. Я тестировал Android SDK 2.3 и 4.0. Возможно, он будет работать с более ранними версиями.

Попробуйте это LD_LIBRARY_PATH=/vendor/lib:/system/lib до pm install. Это работает хорошо.

! / Bin / Баш

 f=/home/cox/myapp.apk #or $1 if input from terminal. #backup env var backup=$LD_LIBRARY_PATH LD_LIBRARY_PATH=/vendor/lib:/system/lib myTemp=/sdcard/temp.apk adb push $f $myTemp adb shell pm install -r $myTemp #restore env var LD_LIBRARY_PATH=$backup 

Это работает для меня. Я запускаю это на ubuntu 12.04, на терминале оболочки.

Intereting Posts
Получение ошибки: не удалось найти класс «android.app.AppOpsManager», на который ссылается метод com.google.android.gms.common.GooglePlayServicesUtil.zza Корпоративная разработка мобильных приложений React native интегрируется с существующим сбоем приложения: «Невозможно найти переменную: __fbBatchedBridge» Как я могу сказать, что андроидная пусковая установка перезагружает свои значки? Сохранить класс в firebase Android API Google Drive «соединение не выполнено» Как подключить одно устройство OnePlus к Ubuntu через MTP? Проблема эмулятора после нового обновления ADT Отображение фотографий в ListView, как получить адаптер для предварительной загрузки, прежде чем пользователи смогут увидеть список? Отправка файла cookie с помощью http post android Ящик навигации не работает, когда startActivity используется в первом случае selectItem Не удалось подключиться на сервере xmpp в android Исключение Saxparser в Android Как получить список доступных / установленных шрифтов в android? Добавление AAR в IntelliJ IDEA без градиента