Android PDF Load Timing - java

The requirements: ensure that the PDF document is deleted from the device after the user has left the PDF viewing screen
The problem: on certain devices (Samsung 4.4.2 and Samsung 4.1.2 for sure, but not Asus 4.2.1) only the first time that the PDF is requested after restarting the application an error message is displayed stating "This document cannot be opened". Thereafter the PDF will load normally. I'm thinking this is a timing issue due to processes that need to be started the first time, but are running after the first attempted load.
The code: note that createFile() is called first, then startActivityForIntentResult()
private File file;
private ArrayList<Uri> uriList = new ArrayList<Uri>();
private void createFile() {
int fileNameLength = pdfFileName[0].length();
String fileName = pdfFileName[0].substring(0, fileNameLength - 4) + DateTime.now();
String fileExtension = pdfFileName[0].substring(fileNameLength - 4, fileNameLength);
byte[] content = Base64.decodeBase64(pdfData[0].getBytes());
BufferedOutputStream outputStream = null;
try {
File path = new File(getExternalFilesDir(null).getAbsolutePath(), "temp");
if (!path.exists()) {
path.mkdirs();
}
file = new File(path, fileName + fileExtension);
outputStream = new BufferedOutputStream(new FileOutputStream(file));
outputStream.write(content);
file.deleteOnExit();
uriList.add(Uri.fromFile(file));
}
catch (FileNotFoundException ex) {
ex.printStackTrace();
}
catch (IOException ex) {
ex.printStackTrace();
}
finally {
try {
if (outputStream != null) {
outputStream.flush();
outputStream.close();
}
}
catch (IOException ex) {
ex.printStackTrace();
}
}
}
private static int REQUEST_CODE = 1;
private Intent intent;
private void startActivityForIntentResult() {
if (file.exists()) {
Uri targetUri = uriList.get(0);
intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(targetUri, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
try {
startActivityForResult(intent, REQUEST_CODE);
}
catch (ActivityNotFoundException e) {
toastTitle = "Error Displaying PDF";
toastMessage = "Please make sure you have an application for viewing PDFs installed on your device and try again.";
toast = new GenericCustomToast();
toast.show(toastTitle, toastMessage, QueryForPDF.this);
}
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (resultCode == RESULT_CANCELED && requestCode == REQUEST_CODE) {
if(!file.delete()) {
file.delete();
}
}
searchAgain();
}
#Override
public void onBackPressed() {
super.onBackPressed();
if(!file.delete()) {
file.delete();
}
searchAgain();
}
#Override
public void onStop() {
super.onStop();
if(!file.delete()) {
file.delete();
}
}
#Override
public void onDestroy() {
super.onDestroy();
if(!file.delete()) {
file.delete();
}
}
EDIT: I have also tried implementing a callback to be absolutely certain that createFile() has finished it's work. I even tried adding delays (of different time increments) as well as adding (the completely unnecessary) flags for Intent.FLAG_GRANT_READ_URI_PERMISSION, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, and Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION.

I still don't know why this works, but here's the solution in case anyone else runs into this issue:
It's the directory where the file is created. For some reason on the two Samsung devices there was something different in how the files were either accessed or created versus the Asus device. So File path = new File(getExternalFilesDir(null).getAbsolutePath(), "temp"); becomes File path = new File(getExternalCacheDir().getAbsolutePath()); and the problem goes away.

Related

Download pdf in android 11

I have upgraded to android 11. I am having an issue downloading PDF files.
I have used this code:
private void createFile(Uri pickerInitialUri, String title) {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("application/pdf");
intent.putExtra(Intent.EXTRA_TITLE, title);
// Optionally, specify a URI for the directory that should be opened in
// the system file picker when your app creates the document.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri);
}
startActivityForResult(intent, CREATE_FILE);
}
The file is created but the file is empty. I am still unable to save the downloaded pdf file.
I used to use DownloadManager request to download the pdf file from web.
DownloadManager downloadManager = (DownloadManager) this.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(uri);
if (SDK_INT > Build.VERSION_CODES.Q) {
// Uri uri1 = Uri.fromFile(new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "")); //before android 11 this was working fine
// Uri uri1 = Uri.fromFile(new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), ""));
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(true).setTitle(title + strDate + ".pdf")
.setDescription(description)
//.setDestinationUri(uri1) // before android 11 it was working fine.
.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, title + strDate + ".pdf") // file is not saved on this directory.
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);//to show the DOWNLOAD notification when completed
// createFile(uri , title + strDate + ".pdf"); // for new scoped storage
} else {
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(true).setTitle(title + strDate + ".pdf")
.setDescription(description)
.setDestinationInExternalPublicDir(FileUtils.downloadPdfDestination(), title + strDate + ".pdf")
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); //to show the DOWNLOAD notification when completed
}
long PDF_DOWNLOAD_ID = downloadManager.enqueue(request);```
ACTION_CREATE_DOCUMENT is used to create a new document. If one already existed, it will be overwritten. If you want to view an existing document, use ACTION_VIEW.
Of course none of the code you posted actually downloads a PDF. If you need help with that, post your DownloadManager code.
Check this code snippet:
override fun startDownload(url: String, onError: (e: Exception) -> Unit) {
try {
val request = DownloadManager.Request(Uri.parse(url))
request.setDestinationInExternalPublicDir(
Environment.DIRECTORY_DOWNLOADS,
UUID.randomUUID().toString()
)
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION)
(context.getSystemService(DOWNLOAD_SERVICE) as DownloadManager).enqueue(request)
} catch (e: Exception) {
e.printStackTrace()
onError.invoke(e)
}
}
It's working fine on Android 11 by using DownloadManger API.
Use below code to download & view pdf.
First you need to apply rxjava dependency for background task.
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
Don't forgot to check WRITE_EXTERNAL_STORAGE permission before call below method. Also check INTERNET permission as well.
Then use below method to perform operation in background.
private void downloadAndOpenInvoice() {
mDialog.show();
Observable.fromCallable(() -> {
String pdfName = "Invoice_"+ Calendar.getInstance().getTimeInMillis() + ".pdf";
String pdfUrl = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf";
File file = CommonUtils.downloadFile(mActivity, pdfUrl, pdfName,mDialog);
return file;
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(file -> {
CommonUtils.viewPdf(file, mActivity, mDialog);
});
}
To download file from url use below snippet
public static File downloadFile(Activity mActivity, String url, String fileName, CustomDialog mDialog) {
// write the document content
File fileDir = new File(CommonUtils.getAppDir(mActivity, "Invoice")); //Invoice folder inside your app directory
if (!fileDir.exists()) {
boolean mkdirs = fileDir.mkdirs();
}
File pdfFile = new File(CommonUtils.getAppDir(mActivity, "Invoice"), fileName); //Invoice folder inside your app directory
try {
URL u = new URL(url);
URLConnection conn = u.openConnection();
int contentLength = conn.getContentLength();
DataInputStream stream = new DataInputStream(u.openStream());
byte[] buffer = new byte[contentLength];
stream.readFully(buffer);
stream.close();
DataOutputStream fos = new DataOutputStream(new FileOutputStream(pdfFile));
fos.write(buffer);
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
if (mDialog.isShowing()) {
mDialog.dismiss();
}
Toast.makeText(mActivity, "Something wrong: " + e.toString(), Toast.LENGTH_LONG).show();
}
return pdfFile;
}
for app directory
public static String getAppDir(Context context, String folderName) {
return context.getExternalFilesDir(null).getAbsolutePath() + File.separator + folderName + File.separator;
}
Use below code to view pdf
public static void viewPdf(File pdfFile, Activity mActivity, CustomDialog mDialog) {
Uri uri = FileProvider.getUriForFile(mActivity, mActivity.getApplicationContext().getPackageName() + ".provider", pdfFile);
// Setting the intent for pdf reader
Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
pdfIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
pdfIntent.setDataAndType(uri, "application/pdf");
//pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
mActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
if (mDialog.isShowing()) {
mDialog.dismiss();
}
}
});
mActivity.startActivity(pdfIntent);
Log.e("Invoice - PDF", pdfFile.getPath());
} catch (ActivityNotFoundException e) {
mActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
if (mDialog.isShowing()) {
mDialog.dismiss();
}
}
});
e.printStackTrace();
Log.e("Invoice - PDF", "Can't read pdf file");
Toast.makeText(mActivity, "Can't read pdf file", Toast.LENGTH_SHORT).show();
}
}

APK not being deleted from download folder

I have set up a Broadcast that starts up when Application is installed with startActivityForResult(). The installation Intent is created here.
private static Intent getOpenDownloadedApkIntent(Context context, File file) {
String name = getPackageNameForAPK(file.getPath(), context);
if (name != null) {
INSTALL_APK_INFO.put(name, file);
}
// The type of intent to use to open the downloaded apk changed in Android N (7.0)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri path = FileProvider.getUriForFile(context,
context.getApplicationContext().getPackageName() + ".utils.DownloadedFileProvider",
file);
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
intent.setData(path);
return intent;
} else {
Uri uri = Uri.fromFile(file);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
return intent;
}
}
private static String getPackageNameForAPK(final String archiveFilePath, Context context) {
try {
PackageInfo info = context.getPackageManager().getPackageArchiveInfo(archiveFilePath, PackageManager.GET_META_DATA);
return info.packageName;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
Now if it is Android 7 or higher, then the uninstall works, but if it is Android 6 or lower, then it just seems to delete the icon of the APK but not the APK itself.
Here is the code that should delete the APK:
private static BroadcastReceiver onInstallComplete = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
ApplicationInfo info = null;
try {
info = context.getPackageManager().getApplicationInfo(intent.getDataString().split(":")[1], PackageManager.GET_META_DATA);
} catch (PackageManager.NameNotFoundException ex) {
}
try {
if (info != null) {
File file = INSTALL_APK_INFO.get(info.packageName);
if (file != null) {
file.delete();
INSTALL_APK_INFO.remove(info.packageName);
}
}
} catch (NullPointerException ex) {
}
}
};
I am guessing that is has something to do with the path, but at the same time it seems to delete the icon of the APK. By icon I mean that if i remove the file.delete() then the APK is with icon in downloads folder but if I run the file.delete() then the APK is without the icon.
What am I doing wrong?
Do u mean to say that app is getting installed but without launcher icon?

in Android API 23 - why can I not programmatically alter ringtones?

I am trying to programmatically change a ringtone in API 23.
I have looked at a lot of examples on Stack Overflow and they all seem to "work" (i.e. not crash) but they do not "work" as in the mp3 doesn't become the ringtone - instead the ringtone becomes simply zero noise. So obviously /something/ happened. (no crash, now no ringtone noise)
I have split this off into a small side project to try to isolate it because it's driving me up the wall - I hope maybe you guys can see something I can't!
I have:
placed the mp3 in \res\raw
I have verified I can play the mp3 fine with this code
MediaPlayer mPlayer = MediaPlayer.create(me, R.raw.meepmeep);
mPlayer.start();
added <uses-permission android:name="android.permission.WRITE_SETTINGS"/> to the manifest
managed the api 22 permission scenario in java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.System.canWrite(this)) {
new AlertDialog.Builder(this)
.setMessage("Please Assign Meep Meep Write Permissions")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
startActivity(intent);
} catch (Exception e) {
Log.e("MainActivity", "error starting permission intent", e);
}
}
})
.show();
return;
}
used a method to carefully fetch the mp3 path from the assets folder
public String LoadFile(String fileName, boolean loadFromRawFolder) throws IOException
{
InputStream iS;
if (loadFromRawFolder)
{
int rID = resources.getIdentifier("meep.example.com.meep:raw/"+fileName, null, null);
iS = resources.openRawResource(rID);
}
else
{
iS = resources.getAssets().open(fileName);
}
byte[] buffer = new byte[iS.available()];
iS.read(buffer);
ByteArrayOutputStream oS = new ByteArrayOutputStream();
oS.write(buffer);
oS.close();
iS.close();
return oS.toString();
}
tried to carefully copy the file to the local storage (as a desperate attempt to get it to work as well as tried to assign it from the raw assets lib
String path = "";
try {
LoadFile("meepmeep", true);
} catch (IOException e) {
//display an error toast message
Toast toast = Toast.makeText(me, "File: not found!", Toast.LENGTH_LONG);
toast.show();
}
//copy file to device
File newSoundFile = new File(path);
//Uri mUri = Uri.parse("android.resource://meep.example.com.meep/R.raw.meepmeep");
Uri mUri = MediaStore.Audio.Media.getContentUriForPath(newSoundFile.getAbsolutePath());
ContentResolver mCr = getContentResolver();
AssetFileDescriptor soundFile;
try {
soundFile= mCr.openAssetFileDescriptor(mUri, "r");
try {
byte[] readData = new byte[1024];
FileInputStream fis = soundFile.createInputStream();
FileOutputStream fos = new FileOutputStream(newSoundFile);
int i = fis.read(readData);
while (i != -1) {
fos.write(readData, 0, i);
i = fis.read(readData);
}
fos.close();
} catch (IOException io) {
}
} catch (FileNotFoundException e) {
soundFile=null;
}
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, newSoundFile.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, "Meep Meep");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.MediaColumns.SIZE, newSoundFile.length());
values.put(MediaStore.Audio.Media.ARTIST, "RoadRunner");
//values.put(MediaStore.Audio.Media.DURATION, 230);
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, true);
values.put(MediaStore.Audio.Media.IS_ALARM, true);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
//Insert it into the database
Uri uri = MediaStore.Audio.Media.getContentUriForPath(newSoundFile.getAbsolutePath());
Uri newUri = mCr.insert(uri, values);
try {
RingtoneManager.setActualDefaultRingtoneUri(
me,
RingtoneManager.TYPE_RINGTONE,
newUri
);
}
catch (Throwable t){
setMessage("meepmeep error");
}
setMessage("meepmeep set");
}
but nothing seems to work. It always fails becuase either soundFile= mCr.openAssetFileDescriptor(mUri, "r"); returns null or if I decline to use that code block and try to change ringtone direct from \res\raw\ folder then it simply gives a blank sound for ringtone.
I am totally stuck for ideas?

How to forbide to kill the app while writing to file continue

My app uses the serialization to store data. Save() function is called in Activity the onStop() method. Since the data was small, everything was fine. Today serialization takes a time, and I was surpised to find a way to corrupt the data.
If I exit from the app by Home button, then quickly manually kill the app form backround activities screen (on long home button tap), my data seems to be lost. I think its because app was written to file and was interrupted.
Is there an opportunity to forbide to kill the process until my save() method works? I was thinking to rewrite serialisation by myself, and it can be faster in times, but as I understand sometimes this problem will happen again.
Thank you.
// Activity code:
#Override
protected void onStop(){
try {
ms.save();
} catch (IOException e) {
e.printStackTrace();
}
super.onStop();
}
// Singleton save fucntion
public void save() throws IOException {
Runnable r = new Runnable()
{
#Override
public void run()
{
try {
FileOutputStream fos;
ObjectOutputStream os;
if (data != null){
fos = context.openFileOutput("Data.dat", Context.MODE_PRIVATE);
os = new ObjectOutputStream(fos);
os.writeObject(data);
os.flush();
os.close();
fos.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
};
Thread t = new Thread(r);
t.start();
}
Ok, I got it using the IntentService in Background. Thanks to RyanB for the help.
save() in Singleton:
Intent mServiceIntent = new Intent(context, ServiceDatastore.class);
mServiceIntent.setData(Uri.parse("dsf"));
context.startService(mServiceIntent);
ServiceDatastore.java
#Override
protected void onHandleIntent(Intent workIntent) {
final int myID = 1234;
Intent intent = new Intent(); // empty Intent to do nothing in case we click on notification.
PendingIntent pendIntent = PendingIntent.getActivity(this, 0, intent, 0);
Notification notice = new Notification(R.drawable.icon, getString(R.string.saving), System.currentTimeMillis());
notice.setLatestEventInfo(this, "Saving...", "", pendIntent);
notice.flags |= Notification.FLAG_NO_CLEAR;
startForeground(myID, notice);
try {
Singleton ms = Singleton.getInstance(this);
FileOutputStream fos;
ObjectOutputStream os;
//copy settings
if (ms.data != null) {
fos = this.openFileOutput("Data.dat", Context.MODE_PRIVATE);
os = new ObjectOutputStream(fos);
os.writeObject(ms.data);
os.flush();
os.close();
fos.close();
}
}
catch (Exception e){
e.printStackTrace();
}
stopForeground(true); // to kill the process if the app was killed.
}

Uri.parse(path) return null in Android 4.4.2

I have an app that allow user to upload a photo on wall.
The code works well for the majority of users, but I have reported that the application crashes sometimes when uploading photo.
The problem is not in taking the pictures from the camera, but it is when you have to take the path of the picture.
The version of Android that is causing this problem is 4.4.2, but I do not understand how to fix it.
post some code:
activityResult:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == CAMERA_PIC_REQUEST) {
try {
//picUri is a global variable Uri
picUri = data.getData();
cropImage();
} catch (Exception e) {
e.printStackTrace();
}
}
else if(requestCode == PIC_CROP) {
try{
//thumbnail is a global variable Bitmap
thumbnail = MediaStore.Images.Media.getBitmap(context.getContentResolver(), cropImageUri);
setImage();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}
hot to crop image:
public void cropImage() {
try {
Intent cropIntent = new Intent("com.android.camera.action.CROP");
//indicate image type and Uri
cropIntent.setDataAndType(picUri, "image/*");
//set crop properties
cropIntent.putExtra("crop", "true");
//indicate aspect of desired crop
cropIntent.putExtra("aspectX", 1);
cropIntent.putExtra("aspectY", 1);
cropIntent.putExtra("scale", true);
//indicate output X and Y
cropIntent.putExtra("outputX", 700);
cropIntent.putExtra("outputY", 700);
//retrieve data on return
cropIntent.putExtra("return-data", false);
File f = createNewFile("CROP_");
try{
f.createNewFile();
}
catch (IOException e) {
e.printStackTrace();
}
//cropImageUri is a global variable Uri
cropImageUri = Uri.fromFile(f);
cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, cropImageUri);
//start the activity - we handle returning in onActivityResult
startActivityForResult(cropIntent, PIC_CROP);
}
catch(ActivityNotFoundException anfe){
anfe.printStackTrace();
}
}
create new File:
private File createNewFile(String prefix) {
if (prefix== null) {
prefix="IMG_";
}
else if("".equalsIgnoreCase(prefix)) {
prefix="IMG_";
}
File newDirectory = new File(Environment.getExternalStorageDirectory()+"/mypics/");
if (!newDirectory.exists()) {
if (newDirectory.mkdir()) {
}
}
File file = new File(newDirectory,(prefix+System.currentTimeMillis()+".jpg"));
if (file.exists()) {
file.delete();
try {
file.createNewFile();
}catch (IOException e) {
e.printStackTrace();
}
}
return file;
}
then when a user click on "send" method preUploadImage is called:
public void preUploadImage() {
UploadImage uploadImage = new UploadImage();
Uri newUri = getImageUri(thumbnail);
try{
// System.out.println("uri = "+picUri);
uploadImage.upload(getRealPathFromURI(newUri));
}
catch (IOException e) {
e.printStackTrace();
}
}
public Uri getImageUri(Bitmap inImage) {
String path = MediaStore.Images.Media.insertImage(context.getContentResolver(), inImage, "Title", null);
return Uri.parse(path);
}
and in the last row the error appears.
return Uri.parse(path);
this row cause a NullPointerException
java.lang.NullPointerException: uriString
at android.net.Uri$StringUri.<init>(Uri.java:468)
at android.net.Uri$StringUri.<init>(Uri.java:458)
at android.net.Uri.parse(Uri.java:430)
at com.delsorboilario.verdebio.ScriviDomanda.getImageUri(ScriviDomanda.java:584)
at com.delsorboilario.verdebio.ScriviDomanda.preUploadImage(ScriviDomanda.java:608)
at com.delsorboilario.verdebio.ScriviDomanda$6$4$2.run(ScriviDomanda.java:292)
I have not attempted to use insertImage(), and in this case, it is not quite clear why you would need it.
Primarily, it seems like you are looking to upload the photo. For that, all you need is the File that you created in createNewFile(). If you are uploading it yourself (e.g., HttpUrlConnection, some third-party library), you should be able to just use the File or an InputStream on it. Even if the upload code really needs a Uri, you can try Uri.fromFile() to get a Uri from your File and see if that works.
Where MediaStore does come into play is making your file be indexed and therefore accessible to apps (ones that query the MediaStore for images) and to users (via their MTP connection through their USB cable). MediaScannerConnection and its static scanFile() method are a fairly straightforward way to get the file indexed. Just make sure your file is fully written to disk first (e.g., if you are writing the file yourself, call getFD().sync() on your FileOutputStream after flush() and before close()).
Looks like MediaStore.Images.Media.insertImage(context.getContentResolver(), inImage, "Title", null); return null.
Form the documentation of MediaStore.Images.Media
Insert an image and create a thumbnail for it.
Parameters
cr The content resolver to use
source The stream to use for the image
title The name of the image
description The description of the image
Returns The URL to the newly created image, or null if the image
failed to be stored for any reason

Categories

Resources