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) 个答案