File Path Not Working for Sharing Audio File Via Intent - android

I am trying to this for 3 days and whole I want to do is that send audio files which are on firebase storage. But before send it I have to download it. There is no problem about downloading but unfortunatelly I cant share it by using intent. Here is the code to downloading->
private void getFileUrl() {
final StorageReference refGulus = storage.getReference().child("gulus.mp3");
refGulus.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
downloadFiles(context, "Mobile", ".mp3",Environment.DIRECTORY_DOWNLOADS, uri);
}
});
}
public void downloadFiles(Context context, String fileName, String fileExtention, String destinationDirectory, Uri uri)
{
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(uri);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalFilesDir(context, destinationDirectory, fileName+fileExtention);
downloadManager.enqueue(request);
//Maybe the problem is in these 2 lines in below I dont know.
final File file1 = new File(Environment.getExternalStorageDirectory().getAbsolutePath(),""+fileName+fileExtention);
myUri = Uri.fromFile(file1); // (myUri is declarated as static in upper so no problem to use it to other classes)
}
And here is the DownloadBroadcastReceiver to understand the download is finished and ready to sharing ->
import static dem.ersin.idrisustaa.Adapters.FirebaseToRecyclerAdapter.myUri;
public class DownloadBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("audio/*");
share.putExtra(Intent.EXTRA_STREAM, myUri);
context.startActivity(Intent.createChooser(share, "Share Sound File"));
}
}
And here is the error for Whatsapp and gmail:
File format is not supported
This error from vlc media player when I try to open it
file:///Android/data/dem.ersin.idrisustaa/files/Download/Mobile.mp3 location cannot be played
When I manually go to phone's storage and try to play the Mobile.mp3 it plays well. There is a problem about path in my opinion.
Where is the problem? What do you think?

Related

How to delete a file from external storage android studio, using only Uri

So I have taken a look at examples from other people and implemented this.
File delete= new File(uri.getPath());
if(delete.exists()){
Log.d("Delete", "File Exists");
if(delete.delete()){
Log.d("Deleted", ""+uri);
}
else{
Log.d("Unable to delete", ""+uri);
}
}
else{
Log.d("Delete", "File is not found");
}
Now the only problem is that the path name i get is "content://downloads/all_downloads/644", and according to my printed logcat, This file could not be found. Note: This file does exist and I used the same uri to actually play the video. Thank you for your help. EDIT: OK This is how I got my URI.
BroadcastReceiver onComplete = new BroadcastReceiver() {
public void onReceive(Context ctxt, Intent intent) {
Log.d("REFERENCE", "E"+"Entering Broadcast");
long referenceId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
uri=( manager.getUriForDownloadedFile(referenceId));
}
};
Now I appreciate very much for the suggestions given bellow, but I am still stuck even after reading the documentation. Suppose I cannot delete using a Uri, is there a way to convert my uri into something useful instead. I don't want to manually enter the address to the location of my files.
#Here is my entire code...
public class Cacher {
private DownloadManager manager;
private Uri uri;
public Cacher(String urlIn , Context context){
Log.d("REFERENCE", "A1- casher");
manager= (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
Log.d("REFERENCE", "A");
Uri temp=Uri.parse(urlIn);
Log.d("REFERENCE", "B");
DownloadManager.Request request= new DownloadManager.Request(temp);
//
request.setNotificationVisibility(Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
Long reference=manager.enqueue(request);
// Toast.makeText(this,""+reference,Toast.LENGTH_LONG);
Log.d("REFERENCE", "C"+"Downloading video");
Log.d("REFERENCE", "D"+"Setting broadcast");
context.registerReceiver(onComplete,
new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
Log.d("REFERENCE", "F"+"Now Setting the uri table with");
}
BroadcastReceiver onComplete = new BroadcastReceiver() {
public void onReceive(Context ctxt, Intent intent) {
Log.d("REFERENCE", "E"+"Entering Broadcast");
long referenceId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
uri=( manager.getUriForDownloadedFile(referenceId));
}
};
//TODO: Add Utility to remove all Cached Videos
//TODO: Add Utility to delete a single cached video after it has been watched.
public Uri getUri() {
return uri;
}
}
So I have taken a look at examples from other people and implemented this.
That would only work if the Uri has a file scheme and you have write access to the directory that holds the file.
How to delete a file from external storage android studio, using only Uri
Most likely, you don't.
If you get the Uri from ACTION_OPEN_DOCUMENT or ACTION_CREATE_DOCUMENT, wrap the Uri in a DocumentFile using fromSingleUri(), then call delete() on the DocumentFile.
For any other content Uri, you are welcome to try calling delete() on a ContentResolver, but do not expect it to work. There is no requirement that a ContentProvider offer you any way to delete a piece of content. The app that supplies the ContentProvider should have its own way of allowing users to delete things.
So here is the solution to my problem for those who do not want to read through our comments. First, chose a directory to download to. Then use that files path and use the delete() functionality. Keep in mind that once you create a directory with a folder name, you only need to reference the folder name and not the entire path. Here is the code I hope it helps:
String in= GenerateDirectory.createVideoDirectory(context);// Might be useless here.
manager= (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
Uri temp=Uri.parse(urlIn);
Ringtone r= RingtoneManager.getRingtone(context, temp);
String filename=(r.getTitle(context));
DownloadManager.Request request= new DownloadManager.Request(temp);
request.setDestinationInExternalPublicDir("/secretVideos", filename);
uri=Uri.parse(in+"/"+filename);
Log.d("REFERENCE", "Uri that is returned "+uri);
request.setNotificationVisibility(Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
manager.enqueue(request);
// And then
public void removeCache(){
//TODO: Fix this. For some reason the Uri used gives invalid path name.
Log.d("Delete", "Directory to find ... "+uri);
File delete= new File(uri.getPath());
if(delete.exists()){
Log.d("Delete", "File Exists");
if(delete.delete()){
Log.d("Deleted", ""+uri);
}
}
}
// Where I create the directory
private int RESULT=0;
public static String createVideoDirectory(Context context){
String pathToExternalStorage = Environment.getExternalStorageDirectory().toString();
File appDirectory = new File(pathToExternalStorage + "/" + "secretVideos");
if(!appDirectory.exists()){
Log.d("Directory","Directory DNE");
if(appDirectory.mkdir()) {
Log.d("Directory", "Directory Created");
//Log.d("Directory","Unable to create directory, using default directory");
}
else if(appDirectory.canWrite()){
Log.d("Directory", "Permission given");
}
else{
Log.d("Directory", "Lack of permission");
}
}
else{
Log.d("Directory","Already Exists");
}
return appDirectory.toString();
}
private void writeAndReadPermissions(Context context){
if(ContextCompat.checkSelfPermission(context, permission.WRITE_EXTERNAL_STORAGE)!=PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions((Activity) context, new String[]{permission.WRITE_EXTERNAL_STORAGE, permission.READ_EXTERNAL_STORAGE}, RESULT);
}
}

Store media in internal storage using download manager

Want to store music file inside getFilesDir() using Uri. I had tried to store by this way
Uri Download_Uri = Uri.parse(songBean.vSongsFileName);
DownloadManager.Request request = new DownloadManager.Request(Download_Uri);
mDownloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
request.setAllowedOverRoaming(false);
request.setTitle(songBean.vTitle);
request.setDescription("Downloading File");
try {
request.setDestinationUri(Uri.parse(createDirectory("tmp.mp3").getPath()));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
downloadReference = mDownloadManager.enqueue(request);
registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
}
}, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
Method for the create directory inside internal storage
public File createDirectory(String filename) throws FileNotFoundException {
File file = new File(context.getFilesDir(), filename);
Log.i("Tag", "createDirectory: " + file.getAbsolutePath());
return file;
}
Not able to store the file in internal storage.request.setDestinationUri(Uri.parse(createDirectory("tmp.mp3").getPath())); throwing not a file uri error.Please help me out for this
The getFilesDir() is private internal storage for your app only. You cannot ask another app to put files there as it has no access.
For DownloadManager use external storage.

WebView Direct Download returns HTML which use the original file extension

I am trying to perform a direct download inside the WebView, not linking to the browser.
webview.setDownloadListener(new DownloadListener() {
#SuppressLint("DefaultLocale")
#Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
MimeTypeMap mtm = MimeTypeMap.getSingleton();
DownloadManager downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
Uri downloadUri = Uri.parse(url);
// get file name. if filename exists in contentDisposition, use it. otherwise, use the last part of the url.
String fileName = downloadUri.getLastPathSegment();
int pos = 0;
if ((pos = contentDisposition.toLowerCase().lastIndexOf("filename=")) >= 0) {
fileName = contentDisposition.substring(pos + 9);
pos = fileName.lastIndexOf(";");
if (pos > 0) {
fileName = fileName.substring(0, pos - 1);
}
}
// predict MIME Type
String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()).toLowerCase();
String mimeType = mtm.getMimeTypeFromExtension(fileExtension);
// request saving in Download directory
Request request = new DownloadManager.Request(downloadUri);
request.setTitle(fileName);
request.setDescription(url);
request.setMimeType(mimeType);
request.setDestinationInExternalPublicDir( Environment.DIRECTORY_DOWNLOADS, fileName);
Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_DOWNLOADS).mkdirs();
// request in download manager
downloadManager.enqueue(request);
}
});
And to open it,
// download complete toast
private BroadcastReceiver completeReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Resources res = context.getResources();
// make toast
Toast.makeText(context, res.getString(R.string.download_complete), Toast.LENGTH_SHORT).show();
// go to download finished window
startActivity(new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS));
}
};
#Override
protected void onPause() {
super.onPause();
// if app stops, stop reciever
unregisterReceiver(completeReceiver);
}
#Override
protected void onResume() {
// app start, start reciever
IntentFilter completeFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
registerReceiver(completeReceiver, completeFilter);
super.onResume();
}
}
However, the result is not the original file, but the HTML format of the source using the original file extension; e.g. it uses .pdf, but is a HTML file.
What is causing this problem, and How can I fix it?
Files I get
First of all, it is impossible to open with a normal PDF viewer, and when I don't open it as PDF, I get a normal HTML document:
<!DOCTYPE html>
<html>
…
</html>
There is NOTHING SPECIAL in the HTML document.
I found that your filename is coming with quote so just replace it.
fileName=fileName.replaceAll("\"", "");
you will get the proper file. I have also used that code in mine and it's successfully worked.

Launch Adobe Reader in Android App

I have an Android app where I intercept a PDF file download event in the WebView, download it using the DownloadManager, and launch a new intent with the Adobe Reader to display the file. It works fine, except that when the Adobe Reader starts, it displays the following message prior to displaying the actual file:
Read-only document | To modify this document save a copy on your device.
Save | View Read-only
After I dismiss this prompt, the document gets displayed correctly. How can I get rid of the Read-only prompt?
Here is my code:
public class MyDownloadListener implements DownloadListener {
MainActivity activity;
BroadcastReceiver receiver;
DownloadManager downloadManager;
public MyDownloadListener(MainActivity a) {
activity = a;
downloadManager = (DownloadManager) activity.getSystemService(Context.DOWNLOAD_SERVICE);
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
Query query = new Query();
query.setFilterById(downloadId);
Cursor c = downloadManager.query(query);
if (c.moveToFirst()) {
int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
String uriString = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
File fileSrc = new File(uriString);
Intent intentPdf = new Intent(Intent.ACTION_VIEW);
intentPdf.setDataAndType(Uri.fromFile(fileSrc), "application/pdf");
intentPdf.setPackage("com.adobe.reader");
intentPdf.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
activity.startActivity(intentPdf);
}
}
}
}
};
activity.registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
#Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
Request request = new Request(Uri.parse(url));
downloadManager.enqueue(request);
}
}
As per the official documentation of class DownloadManager.Request
This class contains all the information necessary to request a new
download. The URI is the only required parameter. Note that the
default download destination is a shared volume where the system might
delete your file if it needs to reclaim space for system use. If this
is a problem, use a location on external storage (see
setDestinationUri(Uri).
So default location is more of a cache location and system can delete the file if it require more space. So if you want to kep the file then you can use setDestinationUri to provide the path in the SD card..
And it looks like the default space does not allow any other thread/process other then the download manager to write file in that space, hence the read only message from the adobe reader..

Retrieving a Content Uri from Camera Intent

I am firing an Intent for the camera to take a photo as follows:
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
Uri myPhoto = Uri.fromFile(new File(Environment.getExternalStorageDirectory(),
"the_photo.jpg"));
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, myPhoto);
startActivityForResult(cameraIntent, INTENT_GET_PICTURE_FROM_CAMERA);
Now I want to get the thumbnail for this photo to show. If I store the "myPhoto" Uri, I can see exactly the file on the file system. However, to use the Media Store API, I need the Uri on the Content Uri form. Is there anyway to retrieve this from the intent the camera gives back and if not how can I convert my file system Uri to the android content Uri.
Note, I know I can just take the bitmap and decode it, downsampling as I go. This is not what I want. I can query all the thumbnails and I see it exists, so I want to get it from the system.
Thanks
I resolved it by performing a Media Scan on the item. From there I could get the content Uri (the extra complication of the handler in the code below is because I needed my result to be handled on the UI thread as it manipulated views):
private Uri mCameraFilePath;
private Context mContext;
...
private void handlePictureFromCamera(Intent data) {
MyMediaScannerClient client = new MyMediaScannerClient(
mCameraFilePath.getPath(), new Handler(), new OnMediaScanned() {
#Override
public void mediaScanned(Uri contentUri) {
//Here I have the content uri as its now in the media store
}
});
MediaScannerConnection connection = new MediaScannerConnection(mContext, client);
client.mConnection = connection;
connection.connect();
}
private interface OnMediaScanned {
public void mediaScanned(Uri contentUri);
}
/**
* This is used to scan a given file (image in this case) to ensure it is added
* to the media store thus making its content uri available. It returns the
* content form Uri by means of a callback on the supplied handler's thread.
*/
private class MyMediaScannerClient implements MediaScannerConnectionClient {
private final String mPath;
private MediaScannerConnection mConnection;
private final OnMediaScanned mFileScannedCallback;
private final Handler mHandler;
public MyMediaScannerClient(String path, Handler handler, OnMediaScanned fileScannedCallback) {
mPath = path;
mFileScannedCallback = fileScannedCallback;
mHandler = handler;
}
#Override
public void onMediaScannerConnected() {
mConnection.scanFile(mPath, null);
}
#Override
public void onScanCompleted(String path, final Uri uri) {
mConnection.disconnect();
mHandler.post(new Runnable() {
#Override
public void run() {
mFileScannedCallback.mediaScanned(uri);
}
});
}
}
AS i commented, i needed something similar (to get " content://media/external/images/xxx " uri format) and your solution worked pretty well. Thanks you!
But i found a shorter way to do it (maybe it doesn't work for you, but for someone else).
Using the same intent formulation as yours (first post), but with the "CAMERA_REQUEST"
inside onActivityResult
getContentResolver().notifyChange(mCapturedImageURI, null);
ContentResolver cr = getContentResolver();
Uri uriContent = Uri.parse(MediaStore.Images.Media.insertImage(getContentResolver(), photo.getAbsolutePath(), null, null));
and getting the 'uriContent' in 'content://media/external/images/xxx' format.

Categories

Resources