Programowo instaluj aplikację na Androidzie

Interesuje mnie, czy można programowo zainstalować dynamicznie pobrany apk z niestandardowej aplikacji na Androida.

 170
Author: Simon MᶜKenzie, 2011-01-05

14 answers

Możesz łatwo uruchomić link market lub monit instalacyjny:

Intent promptInstall = new Intent(Intent.ACTION_VIEW)
    .setDataAndType(Uri.parse("file:///path/to/your.apk"), 
                    "application/vnd.android.package-archive");
startActivity(promptInstall); 

Źródło

Intent goToMarket = new Intent(Intent.ACTION_VIEW)
    .setData(Uri.parse("market://details?id=com.package.name"));
startActivity(goToMarket);

Źródło

Nie można jednak zainstalować .apks bez użytkownika wyraźnej zgody ; nie, chyba że urządzenie i program jest zakorzenione.

 210
Author: Lie Ryan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:12
File file = new File(dir, "App.apk");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
startActivity(intent);

Miałem ten sam problem i po kilku próbach wyszło mi to w ten sposób. Nie wiem dlaczego, ale ustawienie danych i typu osobno spieprzyło mój zamiar.

 54
Author: Horaceman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-28 14:31:05

Cóż, kopałem głębiej i znalazłem źródła aplikacji PackageInstaller ze źródła Android.

Https://github.com/android/platform_packages_apps_packageinstaller

Z manifestu stwierdziłem, że wymaga pozwolenia:

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

I rzeczywisty proces instalacji następuje po potwierdzeniu

Intent newIntent = new Intent();
newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mPkgInfo.applicationInfo);
newIntent.setData(mPackageURI);
newIntent.setClass(this, InstallAppProgress.class);
String installerPackageName = getIntent().getStringExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME);
if (installerPackageName != null) {
   newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, installerPackageName);
}
startActivity(newIntent);
 26
Author: Alkersan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-13 13:05:13

Rozwiązania przedstawione w tym pytaniu mają zastosowanie do targetSdkVersion s z 23 i poniżej. API na poziomie 24 i wyższym, jednak nie działają i ulegają awarii z następującym wyjątkiem:

android.os.FileUriExposedException: file:///storage/emulated/0/... exposed beyond app through Intent.getData()

Wynika to z faktu, że począwszy od Androida 24, zmieniono {[6] } adresowanie pobranego pliku. Na przykład plik instalacyjny o nazwie appName.apk przechowywany w głównym zewnętrznym systemie plików aplikacji o nazwie pakietu com.example.test byłby as

file:///storage/emulated/0/Android/data/com.example.test/files/appName.apk

Dla API 23 i poniżej, natomiast coś w rodzaju

content://com.example.test.authorityStr/pathName/Android/data/com.example.test/files/appName.apk

Dla API 24 i powyżej.

Więcej szczegółów na ten temat można znaleźć tutaj i nie zamierzam przez to przechodzić.

Aby odpowiedzieć na pytanie targetSdkVersion z 24 i wyżej, należy wykonać następujące kroki: Dodaj następujące do AndroidManifest.xml:

<application
        android:allowBackup="true"
        android:label="@string/app_name">
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.authorityStr"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/paths"/>
        </provider>
</application>

2. Dodaj następujący plik paths.xml do folderu xml na res W src, main:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="pathName"
        path="pathValue"/>
</paths>

pathName jest to pokazane w przykładowym przykładzie Uri treści powyżej i {[18] } jest rzeczywistą ścieżką w systemie. Dobrze byłoby umieścić"."(bez cudzysłowów) dla pathValue w powyższym przykładzie, jeśli nie chcesz dodawać żadnego dodatkowego podkatalogu.

  1. Napisz następujący kod, aby zainstalować plik apk o nazwie appName.apk na głównym zewnętrznym systemie plików:

    File directory = context.getExternalFilesDir(null);
    File file = new File(directory, fileName);
    Uri fileUri = Uri.fromFile(file);
    if (Build.VERSION.SDK_INT >= 24) {
        fileUri = FileProvider.getUriForFile(context, context.getPackageName(),
                file);
    }
    Intent intent = new Intent(Intent.ACTION_VIEW, fileUri);
    intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
    intent.setDataAndType(fileUri, "application/vnd.android" + ".package-archive");
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    context.startActivity(intent);
    activity.finish();
    

Nie jest również konieczne pozwolenie podczas pisania do prywatnego katalogu Twojej aplikacji na zewnętrznym system plików.

Napisałem bibliotekę AutoUpdate tutaj , w której użyłem powyższego.

 25
Author: Ali Nem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-16 07:55:14

Chcę tylko podzielić się faktem, że mój plik apk został zapisany w katalogu "Data" mojej aplikacji i że musiałem zmienić uprawnienia do pliku apk, aby był czytelny dla świata, aby umożliwić jego instalację w ten sposób, w przeciwnym razie system rzucał "Parse error: there is a Problem Parsing the Package"; więc używając rozwiązania z @ Horaceman, który sprawia, że:

File file = new File(dir, "App.apk");
file.setReadable(true, false);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
startActivity(intent);
 17
Author: user1604240,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-11 15:00:11

Wykonaj następujące kroki:

1 - Dodaj do AndroidManifest.xml:

<provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/paths"/>
    </provider>

2 - Dodaj następujące ścieżki.plik xml do folderu xml (jeśli nie istnieje utwórz go) na res w src, main

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
    name="external_file"
    path="."/>
</paths>

Nazwa ścieżki jest pokazana w przykładowym przykładzie Uri zawartości powyżej, a pathValue jest rzeczywistą ścieżką w systemie. Dobrze byłoby umieścić"."dla pathValue w powyższym przykładzie, jeśli nie chcesz dodawać żadnego dodatkowego podkatalogu.

3 - Pisz poniższy kod do uruchamiania plików Apk:

File file = "path of yor apk file";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri fileUri = FileProvider.getUriForFile(getBaseContext(), getApplicationContext().getPackageName() + ".provider", file);
Intent intent = new Intent(Intent.ACTION_VIEW, fileUri);
intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
intent.setDataAndType(fileUri, "application/vnd.android" + ".package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);

} else {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}

I dzięki Ali Nemati Hayati jako pierwszy napisać rozwiązanie profil ali-nemati-hayati

 7
Author: Lila saad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-16 13:20:27

Tak, to możliwe. Ale do tego potrzebujesz telefonu, aby zainstalować niezweryfikowane źródła. Na przykład slideMe tak robi. Myślę, że najlepszą rzeczą, jaką możesz zrobić, to sprawdzić, czy aplikacja jest obecna i wysłać intencję do Android Market. powinieneś użyć czegoś schematu url dla android Market.

market://details?id=package.name

Nie wiem dokładnie, jak rozpocząć aktywność, ale jeśli zaczniesz aktywność z tego rodzaju adresem url. Powinien otworzyć android market i dać ci wybór, aby zainstalować aplikacje.

 4
Author: Loïc Faure-Lacroix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-06 17:21:44

Warto zauważyć, że jeśli użyjesz DownloadManager do rozpoczęcia pobierania, pamiętaj, aby zapisać go w zewnętrznej lokalizacji, np. setDestinationInExternalFilesDir(c, null, "<your name here>).apk";. Intent z typem package-archive nie wydaje się podobać schematowi content: używanemu przy pobieraniu plików do wewnętrznej lokalizacji, ale podoba się file:. (Próba zawinięcia wewnętrznej ścieżki do obiektu File, a następnie uzyskanie ścieżki również nie działa, mimo że skutkuje to adresem URL file:, ponieważ aplikacja nie przetworzy apk; wygląda na to, że musi być zewnętrzne.)

Przykład:

int uriIndex = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI);
String downloadedPackageUriString = cursor.getString(uriIndex);
File mFile = new File(Uri.parse(downloadedPackageUriString).getPath());
Intent promptInstall = new Intent(Intent.ACTION_VIEW)
        .setDataAndType(Uri.fromFile(mFile), "application/vnd.android.package-archive")
        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
appContext.startActivity(promptInstall);
 4
Author: qix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-27 09:27:03

Inne rozwiązanie, które nie wymaga twardego kodowania aplikacji odbierającej i dlatego jest bezpieczniejsze:

Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setData( Uri.fromFile(new File(pathToApk)) );
startActivity(intent);
 4
Author: Hartok,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-22 21:30:52

Tylko rozszerzenie, jeśli ktoś potrzebuje biblioteki to to może pomóc. Dzięki

 2
Author: IronBlossom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:23

Spróbuj tego

String filePath = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
String title = filePath.substring( filePath.lastIndexOf('/')+1, filePath.length() );
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(filePath)), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // without this flag android returned a intent error!
MainActivity.this.startActivity(intent);
 2
Author: Joolah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-22 11:08:20

UpdateNode zapewnia API dla Androida do instalowania pakietów APK z poziomu innej aplikacji.

Możesz po prostu zdefiniować swoją aktualizację online i zintegrować API z aplikacją - to wszystko.
Obecnie API jest w stanie Beta, ale możesz już wykonać kilka testów samodzielnie.

Poza tym, UpdateNode oferuje również wyświetlanie wiadomości przez system - całkiem przydatne, jeśli chcesz powiedzieć coś ważnego użytkownikom.

Jestem częścią client dev team i jestem korzystając przynajmniej z funkcji wiadomości dla mojej własnej aplikacji na Androida.

Zobacz tutaj opis jak zintegrować API

 1
Author: sarahara,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-17 20:20:23

Spróbuj tego - Zapis na manifeście:

uses-permission android:name="android.permission.INSTALL_PACKAGES"
        tools:ignore="ProtectedPermissions"

Wpisz kod:

File sdCard = Environment.getExternalStorageDirectory();
String fileStr = sdCard.getAbsolutePath() + "/Download";// + "app-release.apk";
File file = new File(fileStr, "app-release.apk");
Intent promptInstall = new Intent(Intent.ACTION_VIEW).setDataAndType(Uri.fromFile(file),
                        "application/vnd.android.package-archive");

startActivity(promptInstall);
 0
Author: Phuoc-Loc Truong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-23 14:37:49

Najpierw dodaj następujący wiersz do AndroidManifest.xml:

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

Następnie użyj następującego kodu, aby zainstalować apk:

File sdCard = Environment.getExternalStorageDirectory();
            String fileStr = sdCard.getAbsolutePath() + "/MyApp";// + "app-release.apk";
            File file = new File(fileStr, "TaghvimShamsi.apk");
            Intent promptInstall = new Intent(Intent.ACTION_VIEW).setDataAndType(Uri.fromFile(file),
                    "application/vnd.android.package-archive");
            startActivity(promptInstall);
 0
Author: Abbas.moosavi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-22 14:26:03