有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Android:下载/创建和共享文件问题导致太多崩溃,主要是在Android 10(Android Q)上

我有一个安卓应用程序,允许用户创建、下载和共享图像、视频等内容

最近,我提供了API版本29的更新版本,在下载和共享文件时,它在我的应用程序上造成了太多崩溃。他们中的大多数人

Fatal Exception: java.lang.NullPointerException Attempt to invoke virtual method 'java.lang.String 安卓.net.Uri.toString()' on a null object reference

Fatal Exception: java.lang.NullPointerException Attempt to invoke virtual method 'java.lang.String java.io.File.getAbsolutePath()' on a null object reference

我总共使用两个类来下载和共享文件,一个是用java编写的,另一个是用kotlin编写的,所以基本上我会获取文件的URL,将其传递给我的下载任务,然后在下载完成后共享URI/位图到我的ShareUtil类,从那里我共享文件

下面是我开始下载任务的代码:

                if (!UserStatus.isStoragePermissionGranted(DetailImageNew.this)) {
                    checkPermission();
                } else if (!UserStatus.isNetworkConnected(DetailImageNew.this)) {
                    Toasty.warning(DetailImageNew.this.getApplicationContext(), DetailImageNew.this.getResources().getString(R.string.downloadingoffline), Toast.LENGTH_SHORT, true).show();
                    mainImage.setDrawingCacheEnabled(true);
                    Bitmap scaledBitmap = mainImage.getDrawingCache();

                    other = 1;
                    ShareUtil.shareImage(scaledBitmap, DetailImageNew.this, catshare);
                } else {

                    if (!maindownloading) {
                        maindownloading = true;
                        MyDownloadTask.DownloadListener downloadListener = new MyDownloadTask.DownloadListener() {
                            @Override
                            public void status(boolean downloading) {
                                ((Activity) DetailImageNew.this).runOnUiThread(new Runnable() {
                                    public void run() {
                                        if (downloading) {
                                            relative_layout_progress_fragement_video.setVisibility(View.VISIBLE);
                                        } else {
                                            relative_layout_progress_fragement_video.setVisibility(View.GONE);
                                        }
                                    }
                                });

                            }

                            @Override
                            public void downlodedFile(@NotNull File file) {
                                sharefile = file;
                                DetailImageNew.this.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(sharefile)));
                            }

                            @Override
                            public void onDownloadComplete(boolean download, int pos) {
                                maindownloading = false;
                                other = 1;
                                ShareUtil.share(DetailImageNew.this, sharefile,catshare);
                                Toasty.success(getApplicationContext(), getResources().getString(R.string.images_downloaded), Toast.LENGTH_SHORT, true).show();

                            }

                            @Override
                            public void downloadProgress(int status) {

                                ((Activity) DetailImageNew.this).runOnUiThread(new Runnable() {
                                    public void run() {
                                        progress_bar_fragement_video.setProgress(status);
                                        text_view_progress_fragement_video.setText(DetailImageNew.this.getResources().getString(R.string.downloading) + " " + status + " %");
                                    }
                                });

                            }
                        };
                        String basename = FilenameUtils.getName(statusRead.getStatus());
                        new MyDownloadTask(DetailImageNew.this, statusRead.getStatus(), basename, 1, downloadListener).execute(true);

                    } else {
                        Toasty.warning(DetailImageNew.this.getApplicationContext(), DetailImageNew.this.getResources().getString(R.string.downloadingoffline), Toast.LENGTH_SHORT, true).show();

                    }
                }

因此,我在这里使用MyDownloadTask kotlin类共享该文件,MyDownloadTask的代码如下:

class MyDownloadTask ( @SuppressLint("StaticFieldLeak") val context: Context,
val yourUrl: String,
val fileName: String,
val position: Int,
val listener: DownloadListener
) : AsyncTask<Boolean, Void, Boolean>() {
    override fun doInBackground(vararg booleans: Boolean?): Boolean {

        var lenghtOfFile: Long = 0
        var status = 0
        val client = OkHttpClient()
        val request = Request.Builder()
                .url(yourUrl)
                .build()
        var response: Response? = null


        try {
            response = client.newCall(request).execute()

        } catch (e: IOException) {
            e.printStackTrace()
        }

        val inputStream: InputStream
        try {
            lenghtOfFile = response!!.body!!.contentLength()
        } catch (e: Exception) {
        }

        try {
            assert(response!!.body != null)
            inputStream = response!!.body!!.byteStream()

            val buff = ByteArray(1024 * 4)
            var downloaded: Long = 0


            val folder =
                    File(Environment.getExternalStorageDirectory().toString() + "/APPNAME/")
            if (!folder.exists()) {
                folder.mkdir()
            }

            val documentFile = File("$folder/$fileName")
            documentFile.parentFile.mkdirs()
            try {
                documentFile.createNewFile()
            } catch (e: IOException) {
                e.printStackTrace()
            }

            var output: OutputStream? = null
            try {
                output = FileOutputStream(documentFile, false)
            } catch (e: FileNotFoundException) {
                e.printStackTrace()
            }

            while (true) {

                val readed = inputStream.read(buff)

                if (readed == -1) {
                    break
                }
                if (isCancelled) {
                    break
                }
                downloaded += readed.toLong()
                status = (downloaded * 100 / lenghtOfFile).toInt()

                listener.downloadProgress(status)

                output!!.write(buff, 0, readed)

            }

            output!!.flush()
            val file: File
            listener.downlodedFile(documentFile)
            listener.status(false)
            output.close()
            return true

        } catch (e: Exception) {
            e.printStackTrace()
            return false
        }

    }


    override fun onPreExecute() {
        super.onPreExecute()
        listener.status(true)

    }


    override fun onProgressUpdate(vararg values: Void) {
        super.onProgressUpdate(*values)
    }

    override fun onPostExecute(objects: Boolean?) {
        super.onPostExecute(objects)
        if (objects!!) {
            listener.onDownloadComplete(true, position)
        } else {
            listener.onDownloadComplete(false, position)
        }
    }

    override fun onCancelled(aBoolean: Boolean?) {
        super.onCancelled(aBoolean)
        val folder = File(Environment.getExternalStorageDirectory().toString() + "/APPNAME/")
        val documentFile = File("$folder/$fileName")
        documentFile.delete()
    }

    override fun onCancelled() {
        super.onCancelled()


    }


  public  interface DownloadListener {
        fun onDownloadComplete(download: Boolean, pos: Int)
        fun downloadProgress(status: Int)
        fun downlodedFile(file: File)
        fun status(state: Boolean)
    }
}

文件下载完成后,我将文件共享到我的ShareUtil类,如下所示:

   public static void share(Context context, File file, String catshare) {
    Bitmap image = BitmapFactory.decodeFile(file.getAbsolutePath());
    shareImage(image, context, catshare);
}



 public static String shareImage(Bitmap image, Context mContext, String shareurl) {
    Bitmap picture = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.ic_launcher);
    image = overlayCustom(image, mContext, 0, 0);

    String savedImagePath = null;
    Uri bmpUri = null;
    String imageFileName = "EHS_" + new Date().getTime() + ".jpg";
    File storageDir = new File(
            Environment.getExternalStorageDirectory().getAbsolutePath() + "/APPNAME");
    boolean success = true;
    if (!storageDir.exists()) {
        success = storageDir.mkdirs();
    }
    if (success) {
        File imageFile = new File(storageDir, imageFileName);
        savedImagePath = imageFile.getAbsolutePath();
        try {
            OutputStream fOut = new FileOutputStream(imageFile);
            image.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
            fOut.close();
            bmpUri = FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID, imageFile);

        } catch (Exception e) {
            e.printStackTrace();
        }
        Intent shareIntent = new Intent();
        shareIntent.setAction(Intent.ACTION_SEND);

        shareIntent.putExtra(Intent.EXTRA_TEXT, "" + "" +
                "\n\n" + UserStatus.getConfig(mContext).getSharestring() + " :- " + shareurl);
        shareIntent.putExtra(Intent.EXTRA_STREAM, bmpUri);
        shareIntent.setType("image/*");
        shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        mContext.startActivity(Intent.createChooser(shareIntent, "APPNAME"));
    }
    return savedImagePath;
}




 public static Bitmap overlayCustom(Bitmap bmp1, Context context, int ci, int what) {
    String appname = "";
    if (what == 0)
        appname = context.getResources().getString(R.string.kanmani);
    else
        appname = context.getResources().getString(R.string.kanmani);
    Bitmap picture = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher_white);
    bmp1 = overlayBitmapToBottom(bmp1, picture, context, bmp1.getConfig(), appname);
    Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(), bmp1.getConfig());
    Canvas canvas = new Canvas(bmOverlay);
    canvas.drawBitmap(bmp1, new Matrix(), null);
    return bmOverlay;
}

在没有internet代码的情况下共享文件的方法如下:

  public static String shareImage(Bitmap image, Context mContext, String shareurl) {
    Bitmap picture = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.ic_launcher);
    image = overlayCustom(image, mContext, 0, 0);

    String savedImagePath = null;
    Uri bmpUri = null;
    String imageFileName = "EHS_" + new Date().getTime() + ".jpg";
    File storageDir = new File(
            Environment.getExternalStorageDirectory().getAbsolutePath() + "/APPNAME");
    boolean success = true;
    if (!storageDir.exists()) {
        success = storageDir.mkdirs();
    }
    if (success) {
        File imageFile = new File(storageDir, imageFileName);
        savedImagePath = imageFile.getAbsolutePath();
        try {
            OutputStream fOut = new FileOutputStream(imageFile);
            image.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
            fOut.close();
            bmpUri = FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID, imageFile);

        } catch (Exception e) {
            e.printStackTrace();
        }
        Intent shareIntent = new Intent();
        shareIntent.setAction(Intent.ACTION_SEND);

        shareIntent.putExtra(Intent.EXTRA_TEXT, "" + "" +
                "\n\n" + UserStatus.getConfig(mContext).getSharestring() + " :- " + shareurl);
        shareIntent.putExtra(Intent.EXTRA_STREAM, bmpUri);
        shareIntent.setType("image/*");
        shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        mContext.startActivity(Intent.createChooser(shareIntent, "APPNAME"));
    }
    return savedImagePath;
}

我已经遵循了安卓Q的文件共享指南,比如:

Added line for requestLegacyExternalStorage in the manifest file. Using FileProvider

同样的错误在10(Q)以下的安卓版本上也发生过很多次

在测试过程中,我从来没有遇到过这些错误,但无论如何,这些错误都会出现在生产中,我无法在最后重现它们

请帮助我,因为这些错误在我的生产版本中造成了太多的崩溃


共 (0) 个答案