Open pdf file url which is stored in Firebase storage - android

I have uploaded a Pdf file to firebase storage, after uploading the pdf file to firebase storage, I am getting the download url. Now I want to open the pdf file from this download url in my application.
Below is the url I am getting after uploading the pdf file to firebase storage.
https://firebasestorage.googleapis.com/v0/b/realtime-chat-46f4c.appspot.com/o/documents%2Fbf307aa5-79ae-4532-8128-ee394537b357.pdf?alt=media&token=2d0c5329-4717-4adc-9418-6614913e5bfa
Now I want to open an intent to view this pdf file, I've used the below code for this :
String url = "https://firebasestorage.googleapis.com/v0/b/realtime-chat-46f4c.appspot.com/o/documents%2Fbf307aa5-79ae-4532-8128-ee394537b357.pdf?alt=media&token=2d0c5329-4717-4adc-9418-6614913e5bfa";
Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(url), "application/pdf");
startActivity(Intent.createChooser(intent, "Choose an Application:"));
My phone is having applications which can open this pdf file, still it says there are no applications installed to view this file.
If I convert this url in File and use the below code, then the chooser of applications get opened but it gives error that the file can't be opened.
Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
File file = new File(name);
intent.setDataAndType(Uri.fromFile(file), "aplication/pdf");
I've seen many answers that says first download the file and then open it, but I don't want to download the file, I just want to view it.
Please help me if anyone have any idea about this.
Thanks a lot in advanced.

You should use the Intent Chooser
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(url), "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Intent newIntent = Intent.createChooser(intent, "Open File");
try {
startActivity(newIntent);
} catch (ActivityNotFoundException e) {
// Instruct the user to install a PDF reader here, or something
}

Your phone is not detecting the PDF because the URL you are using is a String object and not a PDF object. Technically, it should never open from the phone as PDF unless you download the PDF. PDF viewers on a phone only get activated once the Android OS tells them that it has a valid PDF file. Please take a look at source code of any of the PDF libraries to understand this better -> https://android-arsenal.com/tag/72?sort=created
However, to answer your problem, you should try opening your URL as a URL. It will activate the browser on your phone which in turn will detect that it needs a PDF reader and will activate the appropriate reader.
Something like
String url = "https://firebasestorage.googleapis.com/v0/b/realtime-chat-46f4c.appspot.com/o/documents%2Fbf307aa5-79ae-4532-8128-ee394537b357.pdf?alt=media&token=2d0c5329-4717-4adc-9418-6614913e5bfa";
public void openWebPage(String url) {
Uri webpage = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, webpage);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
However, I am thinking that you want to just validate if the file got uploaded successfully. And if there is a local copy on the phone then just open the local copy instead of downloading another copy. If that is the case, then I recommend using file metadata to achieve that. Something like:
// Create file metadata including the content type
StorageMetadata metadata = new StorageMetadata.Builder()
        .setCustomMetadata("myPDFfile", "localPDFfileName")
        .build();
// Upload the file and metadata
uploadTask = storageRef.child("pdf/localPDFfileName.pdf").putFile(file, metadata);
And on your success listener, retrieve the file metadata. If it is downloaded and looks complete, then open the PDF from your local phone storage. If not, then try downloading from the downloadURL as I mention at the start of the post. That should cover the validations you are trying to do.
Do elaborate more if I did not understand your problem, correctly. I will pick it up and amend my reply accordingly.

Please add following files/method to your project
PdfDownloader.java
PDFDownloaderAsyncTask.java
and then using following method handleViewPdf to view pdf:
private void handleViewPdf () {
File folder = getAppDirectory(context);
String fileName = "test.pdf";// getPdfFileName(pdfUrl);
File pdfFile = new File(folder, fileName);
if (pdfFile.exists () && pdfFile.length () > 0) {
openPDFFile (context, Uri.fromFile(pdfFile));
}
else {
if (pdfFile.length () == 0) {
pdfFile.delete ();
}
try {
pdfFile.createNewFile ();
}
catch (IOException e) {
e.printStackTrace ();
}
ArrayList<String> fileNameAndURL = new ArrayList<> ();
fileNameAndURL.add (pdfFile.toString ());
fileNameAndURL.add (pdfUrl);
fileNameAndURL.add (fileName);
if (pdfDownloaderAsyncTask == null) {
pdfDownloaderAsyncTask = new PDFDownloaderAsyncTask (context, pdfFile);
}
if (hasInternetConnection (context)) {
if (!pdfDownloaderAsyncTask.isDownloadingPdf ()) {
pdfDownloaderAsyncTask = new PDFDownloaderAsyncTask (context, pdfFile);
pdfDownloaderAsyncTask.execute (fileNameAndURL);
}
}
else {
//show error
}
}
}
PDFDownloaderAsyncTask.java
import java.io.File;
import java.util.ArrayList;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
import android.text.TextUtils;
import android.widget.Toast;
public class PDFDownloaderAsyncTask extends AsyncTask<ArrayList<String>, Void, String> {
private boolean isDownloadingPdf = false;
private File file;
private Context context;
public PDFDownloaderAsyncTask (Context context, File file) {
this.file = file;
this.context = context;
this.isDownloadingPdf = false;
}
public boolean isDownloadingPdf () {
return this.isDownloadingPdf;
}
#Override
protected void onPreExecute () {
super.onPreExecute ();
//show loader etc
}
#Override
protected String doInBackground (ArrayList<String>... params) {
isDownloadingPdf = true;
File file = new File (params[0].get (0));
String fileStatus = PdfDownloader.downloadFile (params[0].get (1), file);
return fileStatus;
}
#Override
protected void onPostExecute (String result) {
super.onPostExecute (result);
Loader.hideLoader ();
if (!TextUtils.isEmpty (result) && result.equalsIgnoreCase (context.getString (R.string.txt_success))) {
showPdf ();
}
else {
isDownloadingPdf = false;
Toast.makeText (context, context.getString (R.string.error_could_not_download_pdf), Toast.LENGTH_LONG).show ();
file.delete ();
}
}
#Override
protected void onCancelled () {
isDownloadingPdf = false;
super.onCancelled ();
//Loader.hideLoader ();
}
#Override
protected void onCancelled (String s) {
isDownloadingPdf = false;
super.onCancelled (s);
//Loader.hideLoader ();
}
private void showPdf () {
new Handler ().postDelayed (new Runnable () {
#Override
public void run () {
isDownloadingPdf = false;
openPDFFile (context, Uri.fromFile (file));
}
}, 1000);
}
}
PdfDownloader.java
package com.pdf;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class PdfDownloader {
private static final int MEGABYTE = 1024 * 1024;
public static String downloadFile (String fileUrl, File directory) {
String downloadStatus;
try {
URL url = new URL (fileUrl);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection ();
urlConnection.connect ();
InputStream inputStream = urlConnection.getInputStream ();
FileOutputStream fileOutputStream = new FileOutputStream (directory);
int totalSize = urlConnection.getContentLength ();
Log.d ("PDF", "Total size: " + totalSize);
byte[] buffer = new byte[MEGABYTE];
int bufferLength = 0;
while ((bufferLength = inputStream.read (buffer)) > 0) {
fileOutputStream.write (buffer, 0, bufferLength);
}
downloadStatus = "success";
fileOutputStream.close ();
}
catch (FileNotFoundException e) {
downloadStatus = "FileNotFoundException";
e.printStackTrace ();
}
catch (MalformedURLException e) {
downloadStatus = "MalformedURLException";
e.printStackTrace ();
}
catch (IOException e) {
downloadStatus = "IOException";
e.printStackTrace ();
}
Log.d ("PDF", "Download Status: " + downloadStatus);
return downloadStatus;
}
public static void openPDFFile (Context context, Uri path) {
Intent intent = new Intent (Intent.ACTION_VIEW);
intent.setDataAndType (path, "application/pdf");
intent.setFlags (Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
context.startActivity (intent);
}
catch (ActivityNotFoundException e) {
Toast.makeText (context, context.getString (R.string.txt_no_pdf_available), Toast.LENGTH_SHORT).show ();
}
Loader.hideLoader ();
}
public static File getAppDirectory (Context context) {
String extStorageDirectory = Environment.getExternalStorageDirectory ().toString ();
File folder = new File (extStorageDirectory, context.getString (R.string.app_folder_name).trim ());
if (!folder.exists ()) {
boolean success = folder.mkdirs();
Log.d ("Directory", "mkdirs():" + success);
}
return folder;
}
}

if you want to open the saved pdf file in your application rather than creating a intent to open in other application, you can use the following library to create the PdfView in Xml file. AndroidPdfViewer (this library also provides the zoom in-out facility)
After that as mentioned in the Firebase Document use the saved path reference of the file location in firebase Storage to fetch the file in Bytes and add it to your PdfView as
For example your file path will be like : "/folder1/yourfile.pdf"
pdfView = (PDFView) findViewById(R.id.pdfView);
mFirebaseStorage=FirebaseStorage.getInstance().getReference();
final long ONE_MEGABYTE = 1024 * 1024;
mFirebaseStorage.child("YourSavedFilePathRef").getBytes(ONE_MEGABYTE).addOnSuccessListener(new OnSuccessListener<byte[]>() {
#Override
public void onSuccess(byte[] bytes) {
pdfView.fromBytes(bytes).load();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(MainActivity.this,"download unsuccessful",Toast.LENGTH_LONG).show();
}
});

Simple code :)
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri fileuri = Uri.parse("URL of file on storage") ;
intent.setDataAndType(fileuri,"application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Intent in = Intent.createChooser(intent,"open file");
in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(in);
Hope this works :)

try to encode your firebase database file url. it work with me

Use Webview for view pdf file-
WebView webview = (WebView) findViewById(R.id.webview);
webview.getSettings().setJavaScriptEnabled(true);
String pdf = "https://firebasestorage.googleapis.com/v0/b/realtime-chat-46f4c.appspot.com/o/documents%2Fbf307aa5-79ae-4532-8128-ee394537b357.pdf?alt=media&token=2d0c5329-4717-4adc-9418-6614913e5bfa";
webview.loadUrl("http://drive.google.com/viewerng/viewer?embedded=true&url=" + pdf);

Related

How to upload file by content uri in WebView

Typical Scenario
In order to upload a file using WebView, it's typically needed to override WebChromeClient, and start a file chooser Activity for result:
...
webView.setWebChromeClient(new WebChromeClient() {
#Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,
FileChooserParams fileChooserParams) {
mFilePathCallback = filePathCallback;
Intent intent = new Intent(MainActivity.this, FilePickerActivity.class);
startActivityForResult(intent, 1);
return true;
}
});
...
Then, once file is selected (for simplicity, only a single file can be selected at a time), onActivityResult() is called with a file uri stored in a data object. So, the uri is retrieved and handed over to filePathCallback and the file gets uploaded:
...
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
if (requestCode == 1) {
mFilePathCallback.onReceiveValue(new Uri[] {data.getData()});
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
...
Basically, filePathCallback requires a uri to a file so that to upload it.
The problem
What if I have only an InputStream that contains the data I need to upload rather than a file with a URI? And I cannot save that data to a file so that to generate a URI (for security reasons). Is there a way to upload the data as a file in such case? In particular, can I convert an InputStream to a content URI and then upload it?
Approach 1
This approach works fine, if uri is generated using Uri.fromFile() as below:
...
Uri uri = Uri.fromFile(file);
...
Approach 2
If I implement my own ContentProvider and override openFile there in such a way, that it uses ParcelFileDescriptor.open() to create a ParcelFileDescriptor, then uploading a file based on a uri provided by getContentUri(...) is working without problems:
FileUploadProvider.java
public class FileUploadProvider extends ContentProvider {
public static Uri getContentUri(String name) {
return new Uri.Builder()
.scheme("content")
.authority(PROVIDER_AUTHORITY)
.appendEncodedPath(name)
.appendQueryParameter(OpenableColumns.DISPLAY_NAME, name)
.build();
}
#Nullable
#Override
public ParcelFileDescriptor openFile(#NonNull Uri uri, #NonNull String mode) throws FileNotFoundException {
List<String> segments = uri.getPathSegments();
File file = new File(getContext().getApplicationContext().getCacheDir(),
TextUtils.join(File.separator, segments));
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
}
...
}
Approach 3
However, if I create a ParcelFileDescriptor with help of ParcelFileDescriptor.createPipe(), then file upload never finishes, so it basically doesn't work:
...
public ParcelFileDescriptor openFile(#NonNull Uri uri, #NonNull String mode) throws FileNotFoundException {
List<String> segments = uri.getPathSegments();
File file = new File(getContext().getApplicationContext().getCacheDir(),
TextUtils.join(File.separator, segments));
InputStream inputStream = new FileInputStream(file);
ParcelFileDescriptor[] pipe;
try {
pipe = ParcelFileDescriptor.createPipe();
} catch (IOException e) {
throw new RuntimeException(e);
}
ParcelFileDescriptor readPart = pipe[0];
ParcelFileDescriptor writePart = pipe[1];
try {
IOUtils.copy(inputStream, new ParcelFileDescriptor.AutoCloseOutputStream(writePart));
} catch (IOException e) {
throw new RuntimeException(e);
}
return readPart;
}
...
Approach 4
To make matters worse, if I create a ParcelFileDescriptor with help of MemoryFile, then file upload never finishes as well:
...
public ParcelFileDescriptor openFile(#NonNull Uri uri, #NonNull String mode) throws FileNotFoundException {
List<String> segments = uri.getPathSegments();
File file = new File(getContext().getApplicationContext().getCacheDir(),
TextUtils.join(File.separator, segments));
try {
MemoryFile memoryFile = new MemoryFile(file.getName(), (int) file.length());
byte[] fileBytes = Files.readAllBytes(file.toPath());
memoryFile.writeBytes(fileBytes, 0, 0, (int) file.length());
Method method = memoryFile.getClass().getDeclaredMethod("getFileDescriptor");
FileDescriptor fileDescriptor = (FileDescriptor) method.invoke(memoryFile);
Constructor<ParcelFileDescriptor> constructor = ParcelFileDescriptor.class.getConstructor(FileDescriptor.class);
ParcelFileDescriptor parcelFileDescriptor = constructor.newInstance(fileDescriptor);
return parcelFileDescriptor;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
...
Why is file upload not working for Approach 3 and Approach 4?
Example
I created a sample app to showcase my issue here.
Below are steps to follow to reproduce it. First log in to your gmail account and click "create new message".
Solution
My colleagues have found a solution to this with help of StorageManager - please read more about the component here.
First, create a callback that handles file system requests from ProxyFileDescriptor in FileUploadProvider:
private static class CustomProxyFileDescriptorCallback extends ProxyFileDescriptorCallback {
private ByteArrayInputStream inputStream;
private long length;
public CustomProxyFileDescriptorCallback(File file) {
try {
byte[] fileBytes = Files.readAllBytes(file.toPath());
length = fileBytes.length;
inputStream = new ByteArrayInputStream(fileBytes);
} catch (IOException e) {
// do nothing here
}
}
#Override
public long onGetSize() {
return length;
}
#Override
public int onRead(long offset, int size, byte[] out) {
inputStream.skip(offset);
return inputStream.read(out,0, size);
}
#Override
public void onRelease() {
try {
inputStream.close();
} catch (IOException e) {
//ignore this for now
}
inputStream = null;
}
}
Then, create a file descriptor using StorageManager that will read the InputStream with help of the callback above.
...
StorageManager storageManager = (StorageManager) getContext().getSystemService(Context.STORAGE_SERVICE);
ParcelFileDescriptor descriptor;
try {
descriptor = storageManager.openProxyFileDescriptor(
ParcelFileDescriptor.MODE_READ_ONLY,
new CustomProxyFileDescriptorCallback(file),
new Handler(Looper.getMainLooper()));
} catch (IOException e) {
throw new RuntimeException(e);
}
return descriptor;
...
Please find the full code on github here.
Limitation
This approach is working only for Android API higher than 25.

PDF File showing empty using retrofit 2

I'm working on an app where I'm downloading a PDF file, saving it to internal storage and then opening that file in other app using FileProvider.
Note: It may be a duplicate question, I've gone through most of the questions on StackOverflow, but still didn't find the solution.
The file is getting downloaded fine but when I'm opening it, it is empty.
The downlaoded file is 30 kb and it has 5 pages but all are empty.
Initially, I thought it is empty because the other app doesn't have permission to open the file, but I did another thing to check whether it is a permission issue. I've saved the file to external storage, still, it was empty. So, it means it is not a permission issue.
Please Note:
Along with pdf file, there is some .xls file as well and when I'm opening those in excel android app, it says cannot open the file. This indicates, that there is some issue while writing the byte stream.
Retrofit Interface.java
#GET(ApiConstants.END_POINT_DOWNLOAD_DOCUMENT)
#Streaming
Call<ResponseBody> downloadDocument(#Query("bucket") String bucket, #Query("filename") String fileName);
Code to Download the file: Here I'm checking if a file is already there, then return the file, otherwise download the file.
public LiveData<Resource<File>> openOrDownloadFile(String bucket, String fileName) {
MutableLiveData<Resource<File>> documentLiveData = new MutableLiveData<>();
documentLiveData.postValue(Resource.loading(null));
Context context = MyApp.getInstance();
final File file = new File(context.getFilesDir(), fileName);
if (file.exists()) {
documentLiveData.postValue(Resource.success(file));
} else {
Call<ResponseBody> call = apiService.downloadDocument(bucket, fileName);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
appExecutors.diskIO().execute(new Runnable() {
#Override
public void run() {
try {
InputStream inputStream = null;
OutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
inputStream = response.body().byteStream();
outputStream = new FileOutputStream(file);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
}
documentLiveData.postValue(Resource.success(file));
outputStream.flush();
} catch (IOException e) {
documentLiveData.postValue(Resource.error("Error: Unable to save file/n"+e.getLocalizedMessage(), null));
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
} catch (IOException e) {
Log.e(AppConstants.TAG, e.getMessage(), e);
documentLiveData.postValue(Resource.error("Error: Unable to save file/n"+e.getLocalizedMessage(), null));
}
}
});
} else {
documentLiveData.postValue(Resource.error("Unable to download file", null));
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
documentLiveData.postValue(Resource.error(t.getLocalizedMessage(), null));
}
});
}
return documentLiveData;
}
Fragment Code
private void onItemClickListener(Document document) {
mDocumentsViewModel.openORDownloadFile(document.getType(), document.getName()).observe(this, new Observer<Resource<File>>() {
#Override
public void onChanged(#Nullable Resource<File> fileResource) {
binding.setResource(fileResource);
if (fileResource.status == Status.SUCCESS) {
openFile(fileResource.data);
}
}
});
}
void openFile(File file) {
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = FileProvider.getUriForFile(getContext(), BuildConfig.APPLICATION_ID, file);
intent.setDataAndType(uri, mDocumentsViewModel.getMimeType(file.getAbsolutePath()));
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
PackageManager pm = getActivity().getPackageManager();
if (intent.resolveActivity(pm) != null) {
startActivity(intent);
} else {
Toast.makeText(getActivity(), "This file cannot be opened on this device. Please download some compatible app from play store", Toast.LENGTH_SHORT).show();
}
}
Following are the versions :
ext.retrofit_version = "2.4.0"
ext.okhttp_version = "3.8.0"
I'm struggling with this issue, it'll be a great help if you can point out the issue. Thank you.
Update: The problem was with the backend APIs. My code was correct. Once they've fixed the problem at there side, it started working at my side without any changes.

Download image, save to store, but image gallery cant see that image

I am making gallery app which downloads images from server and puts in app folder. But when i open this app (https://play.google.com/store/apps/details?id=com.sonyericsson.album), i cant see my download images. This is my code
download image:
Glide.with(getActivity()).load(path)
.asBitmap()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(new SimpleTarget<Bitmap>() {
#Override
public void onResourceReady(final Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
Log.d(TAG, "pamti se");
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
saveToDirectory(resource, path);
}
}, 0);
}
});
save to directory:
private void saveToDirectory(Bitmap bitmap, String path) {
File pictureFile = getOutputMediaFile(path);
if (pictureFile == null) {
Toast.makeText(getActivity(), "Došlo je do greške!", Toast.LENGTH_LONG).show();
Log.d(TAG,
"Error creating media file, check storage permissions: ");// e.getMessage());
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.close();
Toast.makeText(getActivity(), "Slika je sačuvana!", Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
Toast.makeText(getActivity(), "Došlo je do greške!", Toast.LENGTH_LONG).show();
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Toast.makeText(getActivity(), "Došlo je do greške!", Toast.LENGTH_LONG).show();
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
#Nullable
private File getOutputMediaFile(String path) {
File mediaStorageDir = new File(Environment.getExternalStorageDirectory(), getActivity().getString(R.string.app_name));
Log.d(TAG, mediaStorageDir.getAbsolutePath());
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
return null;
}
}
String name = "";
for(int i = path.length() - 1; i >= 0; i--) {
if (path.charAt(i) == '/') {
break;
}
name = path.charAt(i) + name;
}
File mediaFile;
String mImageName = getActivity().getString(R.string.app_name) +"_"+ name;
//String mImageName = "IMG" +"-"+ name;
mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName);
return mediaFile;
}
You are saving your image to your internal app storage, you need to make it available to the gallery (external storage of your app) in order to be available outside your app.
Try this method:
private void galleryAddPic() {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
//change mCurrentPhotoPath for your imagepath
File f = new File(mCurrentPhotoPath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
Reference to the documentation:
https://developer.android.com/training/camera/photobasics.html#TaskGallery
https://developer.android.com/guide/topics/data/data-storage.html#filesExternal
Step 1.
Save your files to Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
Step 2.
Use MediaScanner to notify the system about the new file/image. I created a helper class for that. All you have to do is pass in the file path:
import android.content.Context;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.lang.ref.WeakReference;
public class MediaScannerUtils implements
MediaScannerConnection.MediaScannerConnectionClient {
private static final String LOG_TAG = "MediaScannerUtils";
private MediaScannerConnection mConnection;
private #Nullable WeakReference<MediaScannerListener> mListenerRef;
private String mPathToScan;
private String mMimeType;
/**
* Initialize the MediaScannerUtils class
* #param context Any context
* #param listener A listener that gets notified when the scan is completed
* #param pathToScan The path to scan. If null, the entire sdcard is scanned
* #param mimeType The mimeType of files to look for. If null, defaults to "audio/*"
*/
public MediaScannerUtils(#NonNull Context context, #Nullable MediaScannerListener listener,
#Nullable String pathToScan, #Nullable String mimeType) {
LogUtils.d(LOG_TAG, "Initializing MediaScannerUtils");
mPathToScan = pathToScan;
mMimeType = mimeType;
if(pathToScan == null) {
//If path to scan is null, set path to the entire SdCard
mPathToScan = FileUtils.getSDCardAbsolutePath();
}
if(mimeType == null) {
//If mime type is null, set mime type to audio wildcard
mMimeType = "image/*";
}
if(listener != null) {
mListenerRef = new WeakReference<>(listener);
}
mConnection = new MediaScannerConnection(context.getApplicationContext(), this);
mConnection.connect();
}
/**
* Called to notify the client when a connection to the
* MediaScanner service has been established.
*/
public void onMediaScannerConnected() {
mConnection.scanFile(mPathToScan, mMimeType);
}
/**
* Called to notify the client when the media scanner has finished
* scanning a file.
* #param path the path to the file that has been scanned.
* #param uri the Uri for the file if the scanning operation succeeded
* and the file was added to the media database, or null if scanning failed.
*/
public void onScanCompleted(String path, Uri uri) {
if(mConnection != null) {
mConnection.disconnect();
}
if(mListenerRef != null) {
MediaScannerListener listener = mListenerRef.get();
if (listener != null) {
listener.onScanCompleted();
}
}
}
/**
* Disconnects the MediaScannerConnection and releases any heavy object
*/
public void release() {
if (mConnection != null) {
mConnection.disconnect();
mConnection = null;
}
}
public interface MediaScannerListener {
void onScanCompleted();
}
}

ftp file download result in black screen

I am downloading a file from ftp server. downloading code worked fine, however after download code screen doesn't show anything ,it gets black. Also download function is not returning true value, even the file is being saved in the specified directory.
public class FTPClass{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_player);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Intent intent = getIntent();
dirname = intent.getStringExtra("currentDirName");
MyFTPClient mftp = new MyFTPClient();
createPath = mftp.getAppRootPath().concat("/"+ dirname);
mftp.setCurrentDir(createPath);
System.out.println(mftp.ftpChangeDirectory(createPath));
FTPFile[] farr = mftp.ftpListAllFiles();
System.out.println(farr.length);
for(int i = 0; i<farr.length;i++){
System.out.println("SRC: "+createPath+"/"+farr[i].getName());
String src = createPath+"/"+farr[i].getName();
System.out.println("DEST: "+"/data/data/com.example.ftpplayer" + "/app_"+dirname);
String dest ="/data/data/com.example.ftpplayer" + "/app_"+dirname+"/"+farr[i].getName();
System.out.println(mftp.downloadFile(src,dest));
}
}
}
public class CallingIntent extends Activity{
System.out.println("In item click ");
Intent intent = new Intent(getApplicationContext(), FTPClass.class);
String dir = ((TextView) view).getText().toString();
intent.putExtra("currentDirName", dir);
startActivity(intent);
}
public class MyFTPClient{
public boolean downloadFile(String srcPath , String destPath){
try {
FileOutputStream fos = new FileOutputStream(destPath);
System.out.println(mftp.retrieveFile(srcPath, fos)); // retrieve file doesn't return true
fos.flush();
fos.close();
return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
return false;
}
}
You need to run your code on the background thread, try using an asyncTask.

How create a folder on SdCard and how to copy files from one to another

In this Project i am trying to copy files from sdcard (for eg images in DICM) to Recycle Folder whenever user click delete button. But, i am facing problem. I am able to delete files but but unable to copy thing.
C.Java - Using for assigning directories.
package com.haha.recyclebin;
public class C
{
public static String SDCARD = "/mnt/sdcard";
public static String RECYCLE_BIN_ROOT = SDCARD+"/.Recycle";
}
U.Java - Using for copying file from one folder on Sdcard to Recycle Folder.
package com.haha.recyclebin;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class U
{
public static void copyFile(File sourceLocation, File targetLocation)
throws FileNotFoundException, IOException
{
U.debug("copying from "+sourceLocation.getAbsolutePath()+" to "+targetLocation.getAbsolutePath());
String destDirPath = targetLocation.getParent();
File destDir = new File(destDirPath);
if(!destDir.exists()){
destDir.mkdirs();
}
InputStream in = new FileInputStream(sourceLocation);
OutputStream out = new FileOutputStream(targetLocation);
// Copy the bits from instream to outstream
byte[] buf = new byte[1024*512];
int len;
while ((len = in.read(buf)) > 0) {
System.out.println("papa");
out.write(buf, 0, len);
System.out.println(">");
}
System.out.println(".");
in.close();
out.close();
}
public static void debug(Object msg){
System.out.println(msg);
}
}
RecycleActivity - using U.java and C.java in this code :-
package com.haha.recyclebin;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.Set;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.net.Uri;
import android.os.Bundle;
import android.widget.Toast;
public class RecycleActivity extends Activity {
private OnClickListener exitListener = new OnClickListener()
{
#Override
public void onClick(DialogInterface paramDialogInterface, int paramInt)
{
RecycleActivity.this.finish();
}
};
/**
* need a standalone class to hold data (file name)
*/
private final class DeleteFileListener implements OnClickListener
{
String file = null;
/**
* #param file the file to set
*/
public void setFile(String file)
{
this.file = file;
}
#Override
public void onClick(DialogInterface paramDialogInterface, int paramInt)
{
RecycleActivity.this.prepareRecyclebin();
File src = new File(file);
String destPath = C.RECYCLE_BIN_ROOT+file;
File dest = new File(destPath);
try
{
U.copyFile(src, dest); /* using U.java here */
src.delete();
String msg = RecycleActivity.this.getResources().getString(R.string.deleted) + destPath;
Toast.makeText(RecycleActivity.this, msg, Toast.LENGTH_SHORT).show();
} catch (Exception e)
{
e.printStackTrace();
Toast.makeText(RecycleActivity.this, R.string.delete_failed, Toast.LENGTH_SHORT).show();
}
RecycleActivity.this.finish();
}
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Intent intent = getIntent();
debugIntent(intent);
Bundle extras = intent.getExtras();
/* For File Explorer */
Object obj = extras.get(Intent.EXTRA_INTENT);
if(null!=obj){
Intent it2 = (Intent) obj;
Bundle ex2 = it2.getExtras();
Object obj2 = ex2.get(Intent.EXTRA_STREAM);
if(null!=obj2){
Uri uri = (Uri) obj2;
String file = uri.getPath();
System.out.println("file: "+file);
toRecyclebin(file);
}
}
}
/**
* #param file
*/
private void toRecyclebin(String file)
{
if(!file.startsWith(C.SDCARD))
{
promptLimit();
return;
}
String conf = this.getResources().getString(R.string.confirm_delete);
conf+="\n\n"+file;
DeleteFileListener listener = new DeleteFileListener();
listener.setFile(file);
new AlertDialog.Builder(this)
.setMessage(conf)
.setPositiveButton(R.string.yes, listener)
.setNegativeButton(R.string.no, exitListener)
.show();
}
/**
*
*/
private void promptLimit()
{
new AlertDialog.Builder(this)
.setMessage(R.string.limit)
.setPositiveButton(R.string.ok, exitListener)
.show();
}
/**
* #param intent
*/
private void debugIntent(Intent intent)
{
System.out.println("intent: "+intent);
Bundle extras = intent.getExtras();
Set<String> keys = extras.keySet();
for(String key:keys){
Object value = extras.get(key);
System.out.println("-["+key+"]:["+value+"]");
if(value instanceof Intent){
Intent intent2 = (Intent) value;
Bundle ext2 = intent2.getExtras();
Set<String> ks2 = ext2.keySet();
for(String k:ks2){
Object v2 = ext2.get(k);
System.out.println("--["+k+"]:["+v2+"]");
if(v2 instanceof Intent){
Intent i3 = (Intent) v2;
Bundle e3 = i3.getExtras();
Set<String> ks3 = e3.keySet();
for(String kk:ks3){
Object v3 = e3.get(kk);
System.out.println("---["+kk+"]:["+v3+"]");
}
}
}
}
}
Uri data = intent.getData();
System.out.println("data: "+data);
}
void prepareRecyclebin(){
File root = new File(C.RECYCLE_BIN_ROOT);
if(!root.exists()){
root.mkdirs();
}
}
}
I have file explorer which is working fine, I can see images and music on sdcard and i am able to delete then also. But after deletion they should go to Recycle folder (as stated in C.java ). I have created Recycle Folder (/mnt/sdcard/Recycle) manually using file explorer in eclipse.
But i don't see files in recycle folder.
Is there any problem with the Code ?
Any kind of Help will be appreciated.
Thanks !!
Have you Debug and make sure the copyfile has been executed?
And this is My CopyFile function, and they are quite the same:
public static boolean copyFile(String from, String to) {
try {
int bytesum = 0;
int byteread = 0;
File oldfile = new File(from);
if (oldfile.exists()) {
InputStream inStream = new FileInputStream(from);
FileOutputStream fs = new FileOutputStream(to);
byte[] buffer = new byte[1444];
while ((byteread = inStream.read(buffer)) != -1) {
bytesum += byteread;
fs.write(buffer, 0, byteread);
}
inStream.close();
fs.close();
}
return true;
} catch (Exception e) {
return false;
}
}
Try following Code, it will Work.
public void Save_To_Phone(Bitmap bitmap){
try {
FileOutputStream os = new FileOutputStream(YourSDCardPath);
bitmap.compress(CompressFormat.JPEG, 80, os);
os.close();
} catch (Exception e) {
Log.w("ExternalStorage", "Error writing file", e);
}
}

Categories

Resources