Aplikasi saya menginstal aplikasi lain, dan perlu melacak aplikasi apa yang telah diinstal. Tentu saja, ini dapat dicapai dengan hanya menyimpan daftar aplikasi yang diinstal. Tapi ini seharusnya tidak perlu! Seharusnya menjadi tanggung jawab PackageManager untuk mempertahankan hubungan yang diinstal oleh (a, b). Bahkan, menurut API itu adalah:
public abstrak String getInstallerPackageName (String packageName) - Ambil nama paket aplikasi yang menginstal paket. Ini mengidentifikasi dari pasar mana paket itu berasal.
Pendekatan saat ini
Instal APK menggunakan Intent
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
startActivity(intent);
Copot pemasangan APK menggunakan Intent:
Intent intent = new Intent(Intent.ACTION_DELETE, Uri.fromParts("package",
getPackageManager().getPackageArchiveInfo(apkUri.getPath(), 0).packageName,null));
startActivity(intent);
Ini jelas bukan cara misal Android Market menginstal / mencopot paket. Mereka menggunakan versi PackageManager yang lebih kaya. Ini dapat dilihat dengan mengunduh kode sumber Android dari repositori Android Git. Di bawah ini adalah dua metode tersembunyi yang sesuai dengan pendekatan Intent. Sayangnya mereka tidak tersedia untuk pengembang eksternal. Tapi mungkin mereka akan ada di masa depan?
Pendekatan yang lebih baik
Menginstal APK menggunakan PackageManager
/**
* @hide
*
* Install a package. Since this may take a little while, the result will
* be posted back to the given observer. An installation will fail if the calling context
* lacks the {@link android.Manifest.permission#INSTALL_PACKAGES} permission, if the
* package named in the package file's manifest is already installed, or if there's no space
* available on the device.
*
* @param packageURI The location of the package file to install. This can be a 'file:' or a
* 'content:' URI.
* @param observer An observer callback to get notified when the package installation is
* complete. {@link IPackageInstallObserver#packageInstalled(String, int)} will be
* called when that happens. observer may be null to indicate that no callback is desired.
* @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
* {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
* @param installerPackageName Optional package name of the application that is performing the
* installation. This identifies which market the package came from.
*/
public abstract void installPackage(
Uri packageURI, IPackageInstallObserver observer, int flags,
String installerPackageName);
Menghapus instalasi APK menggunakan PackageManager
/**
* Attempts to delete a package. Since this may take a little while, the result will
* be posted back to the given observer. A deletion will fail if the calling context
* lacks the {@link android.Manifest.permission#DELETE_PACKAGES} permission, if the
* named package cannot be found, or if the named package is a "system package".
* (TODO: include pointer to documentation on "system packages")
*
* @param packageName The name of the package to delete
* @param observer An observer callback to get notified when the package deletion is
* complete. {@link android.content.pm.IPackageDeleteObserver#packageDeleted(boolean)} will be
* called when that happens. observer may be null to indicate that no callback is desired.
* @param flags - possible values: {@link #DONT_DELETE_DATA}
*
* @hide
*/
public abstract void deletePackage(
String packageName, IPackageDeleteObserver observer, int flags);
Perbedaan
Saat menggunakan maksud, manajer paket lokal tidak mengetahui dari aplikasi mana asalnya. Secara khusus, getInstallerPackageName (...) mengembalikan nol.
Metode tersembunyi installPackage (...) menggunakan nama paket installer sebagai parameter, dan kemungkinan besar mampu mengatur nilai ini.
Pertanyaan
Apakah mungkin untuk menentukan nama pemasang paket menggunakan maksud? (Mungkin nama paket penginstal dapat ditambahkan sebagai tambahan untuk maksud instalasi?)
Tip: Jika Anda ingin mengunduh kode sumber Android, Anda dapat mengikuti langkah-langkah yang dijelaskan di sini: Mengunduh Source Tree. Untuk mengekstrak file * .java dan meletakkannya di folder sesuai dengan hierarki paket, Anda dapat memeriksa skrip yang rapi ini: Lihat Kode Sumber Android di Eclipse .
Jawaban:
Saat ini tidak tersedia untuk aplikasi pihak ketiga. Perhatikan bahwa menggunakan refleksi atau trik lain untuk mengakses installPackage () tidak akan membantu, karena hanya aplikasi sistem yang dapat menggunakannya. (Ini karena ini adalah mekanisme pemasangan tingkat rendah, setelah izin disetujui oleh pengguna, sehingga tidak aman bagi aplikasi reguler untuk memiliki akses.)
Juga argumen fungsi installPackage () sering berubah di antara rilis platform, sehingga apa pun yang Anda coba akses akan gagal pada berbagai versi platform lainnya.
EDIT:
Juga patut untuk menunjukkan bahwa installerPackage ini hanya ditambahkan cukup baru ke platform (2.2?) Dan pada awalnya tidak benar-benar digunakan untuk melacak siapa yang menginstal aplikasi - ini digunakan oleh platform untuk menentukan siapa yang akan diluncurkan ketika melaporkan bug dengan aplikasi, untuk mengimplementasikan Umpan Balik Android. (Ini juga merupakan salah satu kali argumen metode API berubah.) Untuk setidaknya lama setelah diperkenalkan, Market masih tidak menggunakannya untuk melacak aplikasi yang telah diinstal (dan mungkin masih tidak menggunakannya) ), tetapi alih-alih hanya menggunakan ini untuk mengatur aplikasi Android Umpan Balik (yang terpisah dari Market) sebagai "pemilik" untuk menangani umpan balik.
sumber
Android P + memerlukan izin ini di AndroidManifest.xml
Kemudian:
untuk menghapus. Tampak lebih mudah ...
sumber
onDestroy()
metode?API level 14 memperkenalkan dua tindakan baru: ACTION_INSTALL_PACKAGE dan ACTION_UNINSTALL_PACKAGE . Tindakan tersebut memungkinkan Anda untuk melewati EXTRA_RETURN_RESULT ekstra boolean untuk mendapatkan notifikasi hasil instalasi (tidak).
Kode contoh untuk menjalankan dialog penghapusan instalasi:
Dan terima pemberitahuan dalam metode Activity # onActivityResult Anda :
sumber
ACTION_INSTALL_PACKAGE
akan memerlukanREQUEST_INSTALL_PACKAGES
izin tingkat tanda tangan . Demikian juga, dimulai dengan API 28 (Android P), panggilanACTION_UNINSTALL_PACKAGE
akan memerlukanREQUEST_DELETE_PACKAGES
izin yang tidak berbahaya . Setidaknya menurut dokumen.Jika Anda memiliki izin Pemilik Perangkat (atau pemilik profil, saya belum mencoba), Anda dapat menginstal / menghapus paket secara diam-diam menggunakan API pemilik perangkat.
untuk menghapus instalasi:
dan untuk menginstal paket:
sumber
Satu-satunya cara untuk mengakses metode-metode itu adalah melalui refleksi. Anda bisa mendapatkan pegangan pada suatu
PackageManager
objek dengan memanggilgetApplicationContext().getPackageManager()
dan menggunakan refleksi mengakses metode ini. Lihat tutorial ini .sumber
Menurut kode sumber Froyo, kunci tambahan Intent.EXTRA_INSTALLER_PACKAGE_NAME diminta untuk nama paket penginstal di PackageInstallerActivity.
sumber
Pada perangkat yang di-rooting, Anda dapat menggunakan:
Util.sudo()
didefinisikan di sini.sumber
Jika Anda meneruskan nama paket sebagai parameter ke salah satu fungsi yang ditentukan pengguna Anda, gunakan kode di bawah ini:
sumber
Jika Anda menggunakan Kotlin, API 14+, dan hanya ingin menampilkan dialog uninstall untuk aplikasi Anda:
Anda dapat mengubah
packageName
ke nama paket lain jika Anda ingin meminta pengguna untuk menghapus aplikasi lain di perangkatsumber
Prasyarat:
APK Anda harus ditandatangani oleh sistem seperti yang ditunjukkan sebelumnya dengan benar. Salah satu cara untuk mencapai itu adalah membangun gambar AOSP sendiri dan menambahkan kode sumber ke dalam build.
Kode:
Setelah diinstal sebagai aplikasi sistem, Anda dapat menggunakan metode manajer paket untuk menginstal dan menghapus instalan APK sebagai berikut:
Install:
Copot pemasangan:
Untuk memiliki panggilan balik setelah APK diinstal / dihapus, Anda dapat menggunakan ini:
sumber