Android:下载/创建和共享文件问题,导致大多数Android 10Android Q崩溃过多

问题描述

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

最近,我提供了API版本29的更新,它在下载和共享文件时导致我的应用崩溃太多。他们大多数都像

致命异常:java.lang.NullPointerException尝试在null上调用虚拟方法'java.lang.String android.net.Uri.toString()' 对象引用

致命异常:java.lang.NullPointerException尝试调用 虚拟方法'java.lang.String java.io.File.getAbsolutePath()' 空对象引用

我总共使用两个类来下载和共享文件一个是用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),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(),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,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);

    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,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,"APPNAME"));
    }
    return savedImagePath;
}

我已经遵循了Android Q的文件共享指南,例如:

清单文件中为requestLegacyExternalStorage添加了一行。 使用FileProvider

同一版本在少于10(Q)的Android版本上也会发生多次错误

虽然进行测试,但我根本没有遇到这些错误,但是无论如何这些错误都会产生,并且最终无法重现。

请帮助我,因为这些错误在我的生产版本中导致太多崩溃。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)