Cài đặt ứng dụng theo chương trình trên Android


211

Tôi muốn biết liệu có thể cài đặt apk được tải xuống một cách linh hoạt từ một ứng dụng Android tùy chỉnh hay không.


Tôi không biết "trình tải động, phụ thuộc vào môi trường người dùng hiện tại" nghĩa là gì. Câu trả lời được cung cấp bởi @Lie Ryan cho thấy cách bạn có thể cài đặt APK được tải xuống bằng bất kỳ phương tiện nào bạn chọn.
CommonsWare

Câu trả lời:


240

Bạn có thể dễ dàng khởi chạy một liên kết cửa hàng chơi hoặc lời nhắc cài đặt:

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

hoặc là

Intent goToMarket = new Intent(Intent.ACTION_VIEW)
    .setData(Uri.parse("https://play.google.com/store/apps/details?id=com.package.name"));
startActivity(goToMarket);

Tuy nhiên, bạn không thể cài đặt .apks mà không có sự cho phép rõ ràng của người dùng ; trừ khi thiết bị và chương trình của bạn được root.


35
Câu trả lời tốt, nhưng không mã hóa cứng /sdcard, vì đó là sai trên Android 2.2+ và các thiết bị khác. Sử dụng Environment.getExternalStorageDirectory()thay thế.
CommonsWare

3
Thư mục / nội dung / chỉ tồn tại trong máy phát triển của bạn, khi ứng dụng được biên dịch thành APK, thư mục / nội dung / không còn tồn tại do tất cả các tài sản được nén trong APK. Nếu bạn muốn cài đặt từ thư mục / nội dung / của bạn, trước tiên bạn cần trích xuất nó vào một thư mục khác.
Lie Ryan

2
@LieRyan. Rất vui khi thấy câu trả lời của bạn. Tôi có thiết bị đã root với ROM tùy chỉnh. Tôi muốn cài đặt các chủ đề một cách linh hoạt mà không yêu cầu người dùng nhấn nút cài đặt. Tôi có thể làm điều đó.
Sharanabasu Angadi

1
Điều này dường như không còn hoạt động nữa khi targetSdk ở mức 25. nó đưa ra một ngoại lệ: "android.os.FileUriExposedException: ... apk được hiển thị ngoài ứng dụng thông qua Intent.getData () ...". Làm thế nào mà?
nhà phát triển Android

4
Nhà phát triển @android: Hiện tại tôi không thể kiểm tra điều này, nhưng trên targetSdkVersion> = 24, áp dụng như sau: stackoverflow.com/questions/38200282/ để bạn phải sử dụng FileProvider.
Lie Ryan

56
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);

Tôi đã có cùng một vấn đề và sau nhiều lần thử, nó đã giải quyết được cho tôi theo cách này. Tôi không biết tại sao, nhưng cài đặt dữ liệu và gõ riêng rẽ đã làm hỏng ý định của tôi.


Tôi không thể đưa ra câu trả lời này đủ. Vì một số lý do, việc đặt riêng dữ liệu mục đích và loại MIME gây ra ActivityNotFoundException ở cấp API 17.
Brent M. Spell

Tôi chỉ bỏ phiếu này quá. Hình thức này là hình thức duy nhất tôi có thể làm việc. Vẫn những năm sau đó .. lỗi freakin này là gì? Giờ lãng phí. Tôi đang sử dụng Eclipse (Helios), BTW.
Tâm

10
@ BrentM.Spell và những người khác: nhìn vào tài liệu, bạn sẽ thấy rằng bất cứ khi nào bạn chỉ đặt loại dữ liệu HOẶC, dữ liệu khác sẽ tự động bị vô hiệu hóa, ví dụ: setData()sẽ khiến tham số loại bị xóa. Bạn PHẢI sử dụng setDataAndType()nếu bạn muốn đưa ra giá trị cho cả hai. Tại đây: developer.android.com/reference/android/content/
Mạnh

41

Các giải pháp được cung cấp cho câu hỏi này đều áp dụng cho targetSdkVersions từ 23 trở xuống. Tuy nhiên, đối với Android N, tức là API cấp 24 trở lên, chúng không hoạt động và gặp sự cố với Ngoại lệ sau:

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

Điều này là do thực tế là bắt đầu từ Android 24, việc Urigiải quyết các tệp đã tải xuống đã thay đổi. Chẳng hạn, một tệp cài đặt có tên appName.apkđược lưu trữ trên hệ thống tệp bên ngoài chính của ứng dụng có tên gói com.example.testsẽ là

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

cho API 23và bên dưới, trong khi một cái gì đó như

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

cho API 24và trên.

Thông tin chi tiết về điều này có thể được tìm thấy ở đây và tôi sẽ không đi qua nó.

Để trả lời các câu hỏi cho targetSdkVersioncác 24trở lên, người ta phải làm theo các bước sau: Thêm sau vào 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. Thêm paths.xmltệp sau vào xmlthư mục trên restrong 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>

Cái pathNameđược thể hiện trong ví dụ uri nội dung mẫu mực ở trên và pathValuelà đường dẫn thực tế trên hệ thống. Nó sẽ là một ý tưởng tốt để đặt một "." (không có dấu ngoặc kép) cho pathValue ở trên nếu bạn không muốn thêm bất kỳ thư mục con phụ nào.

  1. Viết đoạn mã sau để cài đặt apk với tên appName.apktrên hệ thống tệp bên ngoài chính:

    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();

Không có quyền cũng cần thiết khi ghi vào thư mục riêng của ứng dụng của bạn trên hệ thống tệp bên ngoài.

Tôi đã viết một thư viện AutoUpdate ở đây mà tôi đã sử dụng ở trên.


2
Tôi đã làm theo phương pháp này. Tuy nhiên, nó nói tập tin bị hỏng khi tôi nhấn nút cài đặt. Tôi có thể cài đặt cùng một tệp bằng cách chuyển qua bluetooth. tại sao vậy?

HI Khi bạn gặp lỗi tệp, chế độ vận chuyển bạn đã cung cấp cho ứng dụng của mình để mang APK là gì, nếu bạn đang tải xuống từ phương tiện máy chủ, hãy kiểm tra để xóa luồng tại tệp sao chép từ máy chủ? Kể từ khi cài đặt APK được chuyển bằng Bluetooth, điều đó có nghĩa là vấn đề tôi đoán.
Sridhar S

2
java.lang.NullPointerException: Cố gắng gọi phương thức ảo 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData (android.content.pm.PackageManager, java.lang.String)' trên một tài liệu tham khảo đối tượng null
Makvin

Thư viện của bạn cuối cùng có thể có readme đơn giản với các hướng dẫn đơn giản về cách sử dụng ...;)
Renetik

2
Cảm ơn bạn rất nhiều, sau một tuần đấu tranh với câu trả lời này tôi đã giải quyết được vấn đề của mình! @SridharS, tôi biết đã lâu rồi, như tôi thấy, nhưng nếu bạn quan tâm, trên dòng 5, bạn nên thêm .authorityStrsau context.getPackageName()đó thì nó sẽ hoạt động.
sehrob

30

Chà, tôi đã đào sâu hơn và tìm thấy các nguồn ứng dụng PackageInstaller từ Nguồn Android.

https://github.com/android/pl platform_packages_apps_packageinstaller

Từ bảng kê khai tôi thấy rằng nó cần có sự cho phép:

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

Và quá trình cài đặt thực tế xảy ra sau khi xác nhận

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);

33
ERIC.INSTALL_PACKAGES chỉ khả dụng cho các ứng dụng đã ký hệ thống. Vì vậy, điều này sẽ không giúp được gì nhiều
Hubert Liberacki

21

Tôi chỉ muốn chia sẻ sự thật rằng tệp apk của tôi đã được lưu vào thư mục "Dữ liệu" của ứng dụng và tôi cần thay đổi các quyền trên tệp apk để có thể đọc được trên thế giới để cho phép cài đặt theo cách đó, nếu không thì hệ thống đã ném "Lỗi phân tích cú pháp: Có một vấn đề phân tích gói"; Vì vậy, sử dụng giải pháp từ @Horaceman mà thực hiện:

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);

Tôi đang nhận được cùng một lỗi trình phân tích cú pháp! Tôi không biết làm thế nào để giải quyết nó? Tôi đã đặt file.setReadable (đúng, sai) nhưng nó không hoạt động với tôi
Jai

15

Điều này có thể giúp đỡ người khác rất nhiều!

Đầu tiên:

private static final String APP_DIR = Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyAppFolderInStorage/";

private void install() {
    File file = new File(APP_DIR + fileName);

    if (file.exists()) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        String type = "application/vnd.android.package-archive";

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            Uri downloadedApk = FileProvider.getUriForFile(getContext(), "ir.greencode", file);
            intent.setDataAndType(downloadedApk, type);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        } else {
            intent.setDataAndType(Uri.fromFile(file), type);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        }

        getContext().startActivity(intent);
    } else {
        Toast.makeText(getContext(), "ّFile not found!", Toast.LENGTH_SHORT).show();
    }
}

Thứ hai: Đối với Android 7 trở lên, bạn nên xác định một nhà cung cấp trong bảng kê khai như bên dưới!

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

Thứ ba: Xác định path.xml trong thư mục res / xml như bên dưới! Tôi đang sử dụng đường dẫn này để lưu trữ nội bộ nếu bạn muốn thay đổi nó thành một thứ khác, có một vài cách! Bạn có thể vào liên kết này: FileProvider

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

Forth: Bạn nên thêm quyền này trong tệp kê khai:

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

Cho phép một ứng dụng yêu cầu cài đặt các gói. Các API nhắm mục tiêu ứng dụng lớn hơn 25 phải có quyền này để sử dụng Intent.ACTION_INSTALL_PACKAGE.

Hãy chắc chắn rằng các cơ quan cung cấp là như nhau!



3
Cảm ơn, bước thứ tư là những gì còn thiếu trong tất cả chúng.
Amin Keshavarzian

1
Thật vậy, điểm thứ 4 là hoàn toàn cần thiết. Tất cả các câu trả lời khác đã bỏ lỡ nó hoàn toàn.
whiteagle

Không phải là ERIC.REQUEST_INSTALL_PACKAGES chỉ dành cho các ứng dụng hệ thống hoặc ứng dụng được ký với kho khóa hệ thống hay bất cứ thứ gì?
pavi2410

@Pavitra Cho phép ứng dụng yêu cầu cài đặt các gói. Các API nhắm mục tiêu ứng dụng lớn hơn 25 phải có quyền này để sử dụng Intent.ACTION_INSTALL_PACKAGE. Cấp độ bảo vệ: chữ ký
Hadi Note

Mã này không sử dụng Intent.ACTION_INSTALL_PACKAGE. Vậy tại sao lại có sự cho phép này ??
Alexander Dyagilev

5

Một giải pháp khác không yêu cầu mã hóa ứng dụng nhận và do đó an toàn hơn:

Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setData( Uri.fromFile(new File(pathToApk)) );
startActivity(intent);

4

Vâng nó có thể. Nhưng để làm được điều đó, bạn cần điện thoại để cài đặt các nguồn chưa được xác minh. Ví dụ, slideMe làm điều đó. Tôi nghĩ rằng điều tốt nhất bạn có thể làm là kiểm tra xem ứng dụng có mặt hay không và gửi ý định cho Android Market. bạn nên sử dụng một cái gì đó lược đồ url cho Android Market.

market://details?id=package.name

Tôi không biết chính xác làm thế nào để bắt đầu hoạt động nhưng nếu bạn bắt đầu một hoạt động với loại url đó. Nó sẽ mở ra thị trường Android và cung cấp cho bạn sự lựa chọn để cài đặt các ứng dụng.


Theo tôi thấy, giải pháp này là gần nhất với sự thật :). Nhưng nó không thích hợp cho trường hợp của tôi. Tôi cần bộ tải động, phụ thuộc vào môi trường người dùng hiện tại và đi vào thị trường - không phải là một giải pháp tốt. Nhưng dù sao, cảm ơn bạn.
Alkersan

4

Điều đáng chú ý là nếu bạn sử dụng DownloadManagerđể khởi động quá trình tải xuống của mình, hãy nhớ lưu nó vào một vị trí bên ngoài, vd setDestinationInExternalFilesDir(c, null, "<your name here>).apk";. Mục đích với loại lưu trữ gói dường như không thích content:lược đồ được sử dụng với các tải xuống đến một vị trí nội bộ, nhưng thực sự thích file:. (Cố gắng bọc đường dẫn nội bộ vào một đối tượng Tệp và sau đó nhận đường dẫn cũng không hoạt động, mặc dù nó dẫn đến một file:url, vì ứng dụng sẽ không phân tích apk; có vẻ như nó phải ở bên ngoài.)

Thí dụ:

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);

3

Đừng quên yêu cầu quyền:

android.Manifest.permission.WRITE_EXTERNAL_STORAGE 
android.Manifest.permission.READ_EXTERNAL_STORAGE

Thêm vào AndroidManifest.xml nhà cung cấp và quyền:

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

Tạo nhà cung cấp tệp XML res / xml / Carrier_paths.xml

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

Sử dụng mã ví dụ dưới đây:

   public class InstallManagerApk extends AppCompatActivity {

    static final String NAME_APK_FILE = "some.apk";
    public static final int REQUEST_INSTALL = 0;

     @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // required permission:
        // android.Manifest.permission.WRITE_EXTERNAL_STORAGE 
        // android.Manifest.permission.READ_EXTERNAL_STORAGE

        installApk();

    }

    ...

    /**
     * Install APK File
     */
    private void installApk() {

        try {

            File filePath = Environment.getExternalStorageDirectory();// path to file apk
            File file = new File(filePath, LoadManagerApkFile.NAME_APK_FILE);

            Uri uri = getApkUri( file.getPath() ); // get Uri for  each SDK Android

            Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
            intent.setData( uri );
            intent.setFlags( Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_NEW_TASK );
            intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
            intent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
            intent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, getApplicationInfo().packageName);

            if ( getPackageManager().queryIntentActivities(intent, 0 ) != null ) {// checked on start Activity

                startActivityForResult(intent, REQUEST_INSTALL);

            } else {
                throw new Exception("don`t start Activity.");
            }

        } catch ( Exception e ) {

            Log.i(TAG + ":InstallApk", "Failed installl APK file", e);
            Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG)
                .show();

        }

    }

    /**
     * Returns a Uri pointing to the APK to install.
     */
    private Uri getApkUri(String path) {

        // Before N, a MODE_WORLD_READABLE file could be passed via the ACTION_INSTALL_PACKAGE
        // Intent. Since N, MODE_WORLD_READABLE files are forbidden, and a FileProvider is
        // recommended.
        boolean useFileProvider = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;

        String tempFilename = "tmp.apk";
        byte[] buffer = new byte[16384];
        int fileMode = useFileProvider ? Context.MODE_PRIVATE : Context.MODE_WORLD_READABLE;
        try (InputStream is = new FileInputStream(new File(path));
             FileOutputStream fout = openFileOutput(tempFilename, fileMode)) {

            int n;
            while ((n = is.read(buffer)) >= 0) {
                fout.write(buffer, 0, n);
            }

        } catch (IOException e) {
            Log.i(TAG + ":getApkUri", "Failed to write temporary APK file", e);
        }

        if (useFileProvider) {

            File toInstall = new File(this.getFilesDir(), tempFilename);
            return FileProvider.getUriForFile(this,  BuildConfig.APPLICATION_ID, toInstall);

        } else {

            return Uri.fromFile(getFileStreamPath(tempFilename));

        }

    }

    /**
     * Listener event on installation APK file
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if(requestCode == REQUEST_INSTALL) {

            if (resultCode == Activity.RESULT_OK) {
                Toast.makeText(this,"Install succeeded!", Toast.LENGTH_SHORT).show();
            } else if (resultCode == Activity.RESULT_CANCELED) {
                Toast.makeText(this,"Install canceled!", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this,"Install Failed!", Toast.LENGTH_SHORT).show();
            }

        }

    }

    ...

}

2

Chỉ cần một phần mở rộng, nếu bất cứ ai cần một thư viện thì điều này có thể giúp đỡ. Cảm ơn Raghav


2

thử cái này

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);

1

Trước tiên, thêm dòng sau vào AndroidManifest.xml:

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

Sau đó sử dụng đoạn mã sau để cài đặt 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

UpdateNode cung cấp API cho Android để cài đặt các gói APK từ bên trong Ứng dụng khác.

Bạn chỉ có thể xác định Cập nhật trực tuyến và tích hợp API vào Ứng dụng của mình - đó là nó.
Hiện tại API đang ở trạng thái Beta, nhưng bạn đã có thể tự mình thực hiện một số thử nghiệm.

Bên cạnh đó, UpdateNode cung cấp cũng hiển thị các thông báo mặc dù hệ thống - khá hữu ích nếu bạn muốn nói điều gì đó quan trọng với người dùng của mình.

Tôi là một phần của nhóm nhà phát triển khách hàng và đang sử dụng ít nhất chức năng tin nhắn cho Ứng dụng Android của riêng tôi.

Xem ở đây một mô tả cách tích hợp API


Có một số vấn đề với trang web. Tôi không thể lấy api_key và tôi không thể tiếp tục đăng ký.
infinite_loop_

Xin chào @infinite_loop_ bạn có thể tìm thấy khóa API trong phần tài khoản người dùng của mình: updatenode.com/profile/view_keys
sarahara

0

Hãy thử điều này - Viết trên Bản kê khai:

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

Viết mã:

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);

1
Bạn không cần quyền chỉ dành cho hệ thống để khởi chạy hoạt động Trình cài đặt gói
Clocker
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.