簡體   English   中英

Android - 嘗試從服務器下載和安裝 .apk 時下載不成功和解析錯誤

[英]Android - Download Unsuccessful and Parsing Error while trying to download and install .apk from server

目標是在不使用 Google Play 商店的情況下更新我的應用程序。 我正在嘗試從服務器下載 .apk 文件,然后以編程方式安裝它。 我目前收到一個錯誤,即下載不成功並且解析包時出錯。 我有運行時請求的 READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE 權限。 我必須進入平板電腦的設置才能授予“安裝未知應用程序”的權限。 我無法在運行時請求 REQUEST_INSTALL_PACKAGES。

如果我更改文件名並更新 URL 以獲取我存儲在服務器上與 .apk 相同文件夾中的 .txt 並注釋掉“.setMimeType()”,我可以下載並查看 .txt 文件。

  • Android Studio 的更新是否使舊的教程或示例過時了?
  • 有沒有一種新的或更好的方式以編程方式從服務器下載 .apk?
  • 運行時缺少 REQUEST_INSTALL_PACKAGES 權限是什么阻止了我的 .apk 下載?
  • 關於如何修復我的代碼的任何建議?

這里有一些代碼片段可以幫助

畢業:應用

android {
    compileSdk 31
    buildToolsVersion "30.0.3"

    defaultConfig {
        applicationId "farrpro.project"
        minSdk 28
        targetSdk 30
    }

AndroidManifest.xml

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
    <uses-permission android:name="android.permission.ACTION_INSTALL_PACKAGE"/>

MainActivity.java


private void hasInstallPermission() { // runs in onCreate() 
        if (getApplicationContext().checkSelfPermission(Manifest.permission.REQUEST_INSTALL_PACKAGES) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES}, 1);
        }
    }


void downloadAndInstallUpdate(){ // runs when users accepts request to download update
        String fileName = "update.apk";
    // example of update’s string
        update = “https://myserver.net/update.apk”;

        //set download manager
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(update));
        request.setTitle(fileName)
                .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
                .setDescription("Downloading")
                //.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE)
                .setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName)
                .setMimeType("application/vnd.android.package-archive");


        // get download service and enqueue file
        final DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
        final long downloadId = manager.enqueue(request);
        System.out.println("Max Bytes: "+DownloadManager.getMaxBytesOverMobile(this)); //returns null


        //set BroadcastReceiver to install app when .apk is downloaded
        BroadcastReceiver onComplete = new BroadcastReceiver() {
            public void onReceive(Context ctxt, Intent intent) {
                System.out.println("Is download successful: "+ manager.getUriForDownloadedFile(downloadId)); //returns null
                System.out.println("Mime: "+manager.getMimeTypeForDownloadedFile(downloadId)); //returns application/vnd.android.package-archive

                Intent install = new Intent(Intent.ACTION_VIEW);
                File file = new File(ctxt.getExternalFilesDir(null) + fileName);
                Uri downloadedApk = FileProvider.getUriForFile(ctxt, "farrpro.project.provider", file);

                install.setDataAndType(downloadedApk,
                        manager.getMimeTypeForDownloadedFile(downloadId));
                install.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                        .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                try {
                    startActivity(install); 
                } catch (ActivityNotFoundException e) {
                    e.printStackTrace();
                    Log.e("TAG", "Error in opening the file!");// this never prints 
                }

                unregisterReceiver(this);
                finish();
            }
        };

        //register receiver for when .apk download is complete
        registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    }

問題是服務器限制了下載類型。 在更改該設置后,我的代碼或多或少地工作了。 我最終需要更改廣播接收器中的意圖,以便在下載完成后立即安裝新的 .apk。 這是我為使發布的代碼正常工作所做的更改。

 final long downloadId = manager.enqueue(request);

BroadcastReceiver onComplete = new BroadcastReceiver() {
            public void onReceive(Context ctxt, Intent intent1) {

                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setDataAndType(manager.getUriForDownloadedFile(downloadId), "application/vnd.android.package-archive");
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                try {
                    getApplicationContext().startActivity(intent);
                } catch (ActivityNotFoundException e) {
                    e.printStackTrace();
                    Log.e("TAG", "Error in opening the file!");
                }

                unregisterReceiver(this);
                finish();
            }
        };

如果您的應用在 Android O 或更新版本上運行,您必須允許應用的未知應用來源。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    if (!context.packageManager.canRequestPackageInstalls()) {
        val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).apply {
            data = Uri.parse(String.format("package:%s", context.packageName))
            addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        }
        context.startActivity(intent)
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM