Saya mencoba menginstal apk secara diam-diam ke dalam sistem. Aplikasi saya terletak di / system / app dan berhasil mendapatkan izin "android.permission.INSTALL_PACKAGES"
Namun saya tidak dapat menemukan cara menggunakan izin ini di mana pun. Saya mencoba menyalin file ke / data / app dan tidak berhasil. Saya juga mencoba menggunakan kode ini
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(
Uri.parse("file:///sdcard/app.apk"),
"application/vnd.android.package-archive");
startActivity(intent);
Tetapi kode ini membuka dialog penginstalan standar. Bagaimana saya bisa menginstal aplikasi secara diam-diam tanpa root dengan diberikan android.permission.INSTALL_PACKAGES
?
PS Saya sedang menulis sebuah aplikasi yang akan menginstal banyak apks dari folder ke dalam sistem pada awal pertama (ganti Setup Wizard). Saya membutuhkannya untuk membuat firmware lebih ringan.
Jika Anda mengira saya sedang menulis virus: Semua program diinstal ke / data / app. Izin Install_packages hanya dapat diberikan ke program tingkat sistem yang terletak di / system / app atau ditandatangani dengan kunci sistem. Jadi virus tidak bisa sampai ke sana.
Seperti yang dikatakan http://www.mail-archive.com/[email protected]/msg06281.html aplikasi DAPAT diinstal secara diam-diam jika mereka memiliki izin install_packages. Selain itu, Anda tidak memerlukan izin Install_packages untuk menginstal paket secara tidak diam-diam. Ditambah http://www.androidzoom.com/android_applications/tools/silent-installer_wgqi.html
sumber
Jawaban:
Taruhan pertama Anda adalah melihat PackageInstaller asli Android . Saya akan merekomendasikan untuk memodifikasi aplikasi itu sesuka Anda, atau hanya mengekstrak fungsionalitas yang diperlukan.
Secara khusus, jika Anda melihat PackageInstallerActivity dan metodenya
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(); } }
Kemudian Anda akan melihat bahwa penginstal sebenarnya terletak di kelas InstallAppProgress . Memeriksa bahwa kelas Anda akan menemukan bahwa
initView
adalah fungsi inti installer, dan hal terakhir yang dilakukannya adalah panggilan untukPackageManager
'sinstallPackage
fungsi:public void initView() { ... pm.installPackage(mPackageURI, observer, installFlags, installerPackageName); }
Langkah selanjutnya adalah memeriksa PackageManager , yang merupakan kelas abstrak. Anda akan menemukan
installPackage(...)
fungsi di sana. Kabar buruknya adalah itu ditandai dengan @hide. Ini berarti itu tidak tersedia secara langsung (Anda tidak akan dapat mengkompilasi dengan panggilan ke metode ini)./** * @hide * .... */ public abstract void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,String installerPackageName);
Tetapi Anda akan dapat mengakses metode ini melalui refleksi.
Jika Anda tertarik pada bagaimana
PackageManager
'sinstallPackage
fungsi diimplementasikan, lihatlah PackageManagerService .Ringkasan
Anda harus mendapatkan objek manajer paket melalui
Context
'sgetPackageManager()
. Kemudian Anda akan memanggilinstallPackage
fungsi melalui refleksi.sumber
LogCat
log terkait izin.Saya telah memeriksa bagaimana ADB menginstal aplikasi.
- Ini menyalin APK ke / data / local / tmp
- menjalankan 'shell: pm install /data/local/tmp/app.apk'
Saya telah mencoba untuk meniru perilaku ini dengan melakukan: (di pc, menggunakan kabel usb)
adb push app.apk /sdcard/app.apk
adb shell
$ pm install /sdcard/app.apk
Ini berfungsi. Aplikasi sudah terpasang.
Saya membuat aplikasi (bernama AppInstall) yang seharusnya menginstal aplikasi lain.
(diinstal secara normal, perangkat yang tidak di-rooting)
Memang:
Runtime.getRuntime().exec("pm install /sdcard/app.apk").waitFor();
Tapi ini memberikan kesalahan:
java.lang.SecurityException: Neither user 10019 nor current process has android.permission.INSTALL_PACKAGES.
Sepertinya kesalahan dilemparkan oleh pm, bukan oleh AppInstall.
Karena SecurityException tidak ditangkap oleh AppInstall dan aplikasi tidak mogok.
Saya telah mencoba hal yang sama pada perangkat yang di-rooting (aplikasi dan AppInstall yang sama) dan itu bekerja dengan sangat baik.
(Juga biasanya diinstal, bukan di / sistem atau apa pun)
AppInstall bahkan tidak meminta izin root.
Tapi thats karena shell selalu
#
bukan$
pada perangkat itu.Btw, Anda perlu root untuk menginstal aplikasi di / system, benar?
Saya mencoba adb remount pada perangkat yang tidak di-rooting dan mendapatkan:
remount failed: Operation not permitted.
Itulah mengapa saya tidak dapat mencoba hal / sistem pada perangkat yang tidak di-rooting.
Kesimpulan: Anda harus menggunakan perangkat yang di-rooting
Semoga ini membantu :)
sumber
su
)Saya telah menerapkan penginstalan tanpa izin pengguna baru-baru ini - ini adalah aplikasi kios untuk API level 21+ di mana saya memiliki kendali penuh atas lingkungan.
Persyaratan dasarnya adalah
Metode berikut membaca dan menginstal APK dari 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; }
Kode berikut memanggil penginstalan
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(); }
agar semuanya bekerja, Anda sangat membutuhkan
INSTALL_PACKAGES
izin, atau kode di atas akan gagal secara diam-diam<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
untuk mendapatkan izin ini, Anda harus menginstal APK Anda sebagai aplikasi Sistem yang MEMBUTUHKAN root (namun SETELAH Anda menginstal aplikasi pembaru, tampaknya berfungsi TANPA root)
Untuk menginstal sebagai aplikasi sistem saya membuat APK yang ditandatangani dan mendorongnya dengan
adb push updater.apk /sdcard/updater.apk
dan kemudian memindahkannya ke
system/priv-app
- yang membutuhkan pemasangan ulang FS (inilah mengapa root diperlukan)adb shell su mount -o rw,remount /system mv /sdcard/updater.apk /system/priv-app chmod 644 /system/priv-app/updater.apk
untuk beberapa alasan itu tidak berfungsi dengan versi debug sederhana, tetapi logcat menampilkan info berguna jika aplikasi Anda
priv-app
tidak diambil karena alasan tertentu.sumber
Anda harus mendefinisikan
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
dalam manifes Anda, jika Anda berada di partisi sistem (/ system / app) atau aplikasi Anda ditandatangani oleh pabrikan, Anda akan memiliki izin INSTALL_PACKAGES.
Saran saya adalah membuat proyek android kecil dengan tingkat kompatibilitas 1,5 yang digunakan untuk memanggil installPackages melalui refleksi dan mengekspor jar dengan metode untuk menginstal paket dan memanggil metode yang sebenarnya. Kemudian, dengan mengimpor jar di proyek Anda, Anda akan siap untuk memasang paket.
sumber
Saya mencoba di Android 4.2.2 yang di-root dan metode ini berfungsi untuk saya:
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(); } } }
sumber
Saya tidak tahu bagaimana melakukan ini, karena tidak ada yang menjawab saat itu, dan saya tidak menemukan dokumentasi tentang izin ini. Jadi saya menemukan solusi saya sendiri. Ini lebih buruk dari milik Anda, tetapi ini adalah solusi.
Saya menginstal busybox, yang menetapkan 777 izin ke / data / app (Saya tidak peduli dengan keamanan). Kemudian jalankan saja "busybox install" dari aplikasi. Ini berfungsi, tetapi memiliki kebocoran keamanan yang besar. Jika Anda mengatur izin 777, tidak diperlukan root.
sumber
Process install; install = Runtime.getRuntime().exec("/system/bin/busybox install " + myAPK.getAbsolutePath()); int iSuccess = install.waitFor();
Anda dapat menggunakan API tersembunyi
android.content.pm.IPackageInstallObserver
dengan refleksi: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(); } } }
Impor
android.content.pm.IPackageInstallObserver
ke dalam proyek Anda. Aplikasi Anda harus sistem. Anda harus mengaktifkan izinandroid.permission.INSTALL_PACKAGES
dalam file manifes Anda.sumber
Anda cukup menggunakan perintah adb install untuk menginstal / memperbarui APK secara diam-diam. Kode sampel ada di bawah
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(); } } }
sumber
Prasyarat:
APK Anda perlu ditandatangani oleh sistem seperti yang ditunjukkan dengan benar sebelumnya. Salah satu cara untuk mencapainya adalah dengan membuat gambar AOSP sendiri dan menambahkan kode sumber ke dalam build.
Kode:
Setelah diinstal sebagai aplikasi sistem, Anda dapat menggunakan metode pengelola paket untuk menginstal dan menghapus APK sebagai berikut:
Install:
public boolean install(final String apkPath, final Context context) { Log.d(TAG, "Installing apk at " + apkPath); try { final Uri apkUri = Uri.fromFile(new File(apkPath)); final String installerPackageName = "MyInstaller"; context.getPackageManager().installPackage(apkUri, installObserver, PackageManager.INSTALL_REPLACE_EXISTING, installerPackageName); return true; } catch (Exception e) { e.printStackTrace(); return false; } }
Copot pemasangan:
public boolean uninstall(final String packageName, final Context context) { Log.d(TAG, "Uninstalling package " + packageName); try { context.getPackageManager().deletePackage(packageName, deleteObserver, PackageManager.DELETE_ALL_USERS); return true; } catch (Exception e) { e.printStackTrace(); return false; } }
Untuk mendapatkan panggilan balik setelah APK Anda diinstal / di-uninstal, Anda dapat menggunakan ini:
/** * Callback after a package was installed be it success or failure. */ private class InstallObserver implements IPackageInstallObserver { @Override public void packageInstalled(String packageName, int returnCode) throws RemoteException { if (packageName != null) { Log.d(TAG, "Successfully installed package " + packageName); callback.onAppInstalled(true, packageName); } else { Log.e(TAG, "Failed to install package."); callback.onAppInstalled(false, null); } } @Override public IBinder asBinder() { return null; } } /** * Callback after a package was deleted be it success or failure. */ private class DeleteObserver implements IPackageDeleteObserver { @Override public void packageDeleted(String packageName, int returnCode) throws RemoteException { if (packageName != null) { Log.d(TAG, "Successfully uninstalled package " + packageName); callback.onAppUninstalled(true, packageName); } else { Log.e(TAG, "Failed to uninstall package."); callback.onAppUninstalled(false, null); } } @Override public IBinder asBinder() { return null; } } /** * Callback to give the flow back to the calling class. */ public interface InstallerCallback { void onAppInstalled(final boolean success, final String packageName); void onAppUninstalled(final boolean success, final String packageName); }
===> Diuji pada Android 8.1 dan bekerja dengan baik.
sumber
Saya membuat aplikasi uji untuk penginstalan diam-diam, menggunakan metode PackageManager.installPackage.
Saya mendapatkan metode installPackage melalui refleksi, dan membuat antarmuka android.content.pm.IPackageInstallObserver di folder src saya (karena tersembunyi di paket android.content.pm).
Ketika saya menjalankan installPackage, saya mendapat SecurityException dengan indikasi string, bahwa aplikasi saya tidak memiliki android.permission.INSTALL_PACKAGES, tetapi didefinisikan di AndroidManifest.xml.
Jadi, menurut saya, tidak mungkin menggunakan metode ini.
PS. Saya mengujinya di Android SDK 2.3 dan 4.0. Mungkin itu akan bekerja dengan versi sebelumnya.
sumber
Coba ini
LD_LIBRARY_PATH=/vendor/lib:/system/lib
sebelum menginstal. Ini bekerja dengan baik.sumber
Aplikasi pihak ketiga tidak dapat menginstal Aplikasi Android secara diam-diam. Namun, aplikasi pihak ke-3 dapat meminta OS Android untuk menginstal aplikasi.
Jadi Anda harus mendefinisikan ini:
Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.parse("file:///sdcard/app.apk", "application/vnd.android.package-archive"); startActivity(intent);
Anda juga dapat mencoba menginstalnya sebagai aplikasi sistem untuk memberikan izin dan mengabaikan definisi ini. (Diperlukan Root)
Anda dapat menjalankan perintah berikut pada aplikasi pihak ketiga Anda untuk menginstal aplikasi pada perangkat yang di-rooting.
Kodenya adalah:
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(); } } }
Saya harap jawaban ini bermanfaat untuk Anda.
sumber
Dimungkinkan untuk melakukan penginstalan diam-diam di Android 6 ke atas. Menggunakan fungsi yang disediakan dalam jawaban oleh Boris Treukhov, abaikan semua yang lain di pos, root juga tidak diperlukan.
Pasang aplikasi Anda sebagai admin perangkat, Anda dapat memiliki mode kios penuh dengan pemasangan pembaruan diam-diam di latar belakang.
sumber
Saya memeriksa semua jawaban, kesimpulannya tampaknya Anda harus memiliki akses root ke perangkat terlebih dahulu untuk membuatnya berfungsi.
Tapi kemudian saya menemukan artikel ini sangat berguna. Karena saya membuat perangkat "milik perusahaan".
Cara Memperbarui Aplikasi Android Secara Diam-diam Tanpa Interaksi Pengguna
Pemilik Perangkat Android - Aplikasi Minimal
Berikut adalah dokumentasi Google tentang "perangkat-terkelola"
Perangkat yang dikelola sepenuhnya
sumber
Anda dapat menggunakan ini di terminal atau shell
adb shell install -g MyApp.apk
lihat lebih lanjut di develope google
sumber
! / bin / bash
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
Ini berhasil untuk saya. Saya menjalankan ini di ubuntu 12.04, di terminal shell.
sumber