So, this program downloads a file from firebase storage,
my downloading code is:
private void downloadFiles(Context context, String fileName, String destinationDirectory, String url) {
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
Uri uri = Uri.parse(url);
DownloadManager.Request request = new DownloadManager.Request(uri);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalFilesDir(context, String.valueOf(destinationDirectory), fileName);
downloadManager.enqueue(request);
}
public void downloading(final String name) {
downloadRef = storage.getInstance().getReference().child(name);
downloadRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
String url = uri.toString();
downloadFiles(Main2Activity.this, name, getApplicationContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), url);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(Main2Activity.this, "Failed!!!", Toast.LENGTH_LONG).show();
}
});
}
and then I want to use this database so I tried to open it with:
database = SQLiteDatabase.openDatabase(myPath, null, 0);
How can I solve this one? It would be really helpful guys.
I thought your problem was accessibility.
That's why I brought a activity back to get permission from the user.
You test this code
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[] {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
} else {
Intent intent = new Intent(MainActivity.this, Main2Activity.class);
intent.putExtra("name", arrayList.get(position));
startActivity(intent);
}
}
});
You are using Environment.getExternalStorageState() which returns the current state of the primary shared/external storage media. It cannot be used to get the path as string of any file. Use context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) to get the string value of the path to the Download directory.
Related
Here i read some input which i want to use for creating "Produs" object which i upload it to the firebase storage, then i want to retrieve it to display a list of objects, i have a problem when i want to update the path to the image storage, to retrieve it later.
public class Add extends AppCompatActivity {
DatabaseReference mDatabase;
EditText etNume, etCantitate, etPret;
Button btnSubmit, btnImage;
Uri mImage;
ImageView ivTest;
public static String path="";
StorageReference mStorageRef;
final int GALLERY_INTENT = 2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add);
mDatabase = FirebaseDatabase.getInstance().getReference();
etNume = findViewById(R.id.etNume);
etCantitate = findViewById(R.id.etCantitate);
etPret = findViewById(R.id.etPret);
btnSubmit = findViewById(R.id.btnSubmit);
btnImage = findViewById(R.id.btnImage);
ivTest =findViewById(R.id.ivTest);
mStorageRef = FirebaseStorage.getInstance().getReference();
btnImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.setType("image/*");
startActivityForResult(i, GALLERY_INTENT);
}
});
btnSubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String nume, pret,cantitate;
nume = etNume.getText().toString().trim();
pret = etPret.getText().toString().trim();
cantitate = etCantitate.getText().toString().trim();
if(TextUtils.isEmpty(nume)){
etNume.setError("Email is required.");
return;
}
if(TextUtils.isEmpty(pret)){
etPret.setError("Email is required.");
return;
}
if(TextUtils.isEmpty(cantitate)){
etCantitate.setError("Email is required.");
return;
}
StorageReference file = mStorageRef.child("Produs").child(nume + ".jpg");
file.putFile(mImage).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
path += taskSnapshot.getMetadata().toString(); /// good path
Toast.makeText(Add.this, path, Toast.LENGTH_SHORT).show();
}
});
Toast.makeText(Add.this, path, Toast.LENGTH_SHORT).show();/// null path
Produs p=new Produs(nume,cantitate,pret,path);
Task task =mDatabase.child("Produs").child(nume).setValue(p);
task.addOnSuccessListener(new OnSuccessListener() {
#Override
public void onSuccess(Object o) {
Toast.makeText(Add.this, "Produsul a fost adaugat cu succes", Toast.LENGTH_SHORT).show();
startActivity(new Intent(getApplicationContext(),MainActivity.class));
}
});
task.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(Add.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == GALLERY_INTENT && resultCode == RESULT_OK && data != null && data.getData() != null){
mImage = data.getData();
ivTest.setImageURI(mImage);
}
}
}
How to have path changed from the onSuccess method?
Basically i want to change the path after i upload an image to build " Produs " object
Also, this is the good path to the image storage? As taskSnapshot.getdownloadURL() doesn't work for me.
The problem is not where you set and read the path variable, the problem is when you do this. Since the getDownloadURL() method makes a call to the server, its onSuccess may run much later than you think.
If you're seeing the wrong value for path, it's very likely that the onSuccess that sets it hasn't run yet. The easiest way to verify that is by either setting breakpoints on the read and write and running in a debugger, or by adding some logging and checking the order of that in your logcat.
The solution for this type of problem is always the same: any code that needs the download URL, needs to either be inside onSuccess, be called from there, or be synchronized in some other way.
So in your case, move the `` into the onSuccess:
StorageReference file = mStorageRef.child("Produs").child(nume + ".jpg");
file.putFile(mImage).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
path += taskSnapshot.getMetadata().toString(); /// good path
Toast.makeText(Add.this, path, Toast.LENGTH_SHORT).show();
Toast.makeText(Add.this, path, Toast.LENGTH_SHORT).show();
Produs p=new Produs(nume,cantitate,pret,path);
Task task =mDatabase.child("Produs").child(nume).setValue(p);
task.addOnSuccessListener(new OnSuccessListener() {
...
});
task.addOnFailureListener(new OnFailureListener() {
...
});
}
});
For more on this, see:
How to store download image url in realtime database firebase android
How to store Url into ArrayList from Firebase Storage?
Can someone help me with logic of the firebase on success listener
getContactsFromFirebase() method return an empty list
Setting Singleton property value in Firebase Listener
Not all of these are directly about Cloud Storage for Firebase, but the explanation applies here as well.
I am new to android development and I have an issue.
I have a fragment in which a user can post an announcement and should be able to upload a photo(optional).
When the form is full and the "Post announcement" button is pressed, I trigger the method to save the information to the database.
The only problem I am facing is retrieving the Uri of the newly uploaded photo.
This is the code which extracts the information.
public Map<String, Object> appendDataFromAnnouncementForm(){
String title = titleLineEdit.getText().toString();
String category = categoryLineEdit.getText().toString();
String description = descriptionLineEdit.getText().toString();
String date = dateLineEdit.getText().toString();
String time = timeLineEdit.getText().toString();
String location = locationLineEdit.getText().toString();
//Image upload to firebase + getting the Uri
if(localPhotoUri != null){
uploadImageToFirebase(generatePhotoName(localPhotoUri), localPhotoUri);
}
Map<String, Object> newAnnouncement = new HashMap<>();
//#####################################################
if(uploadedImageUri != null) // <- this is always null
{newAnnouncement.put("imageUri", uploadedImageUri.toString());}
//#############################################################
newAnnouncement.put("title", title);
newAnnouncement.put("category", category);
newAnnouncement.put("description", description);
newAnnouncement.put("date", date);
newAnnouncement.put("time", time);
newAnnouncement.put("location", location);
return newAnnouncement;
}
Below I am posting the code which uploads the photo to Firebase Storage. Since
private void uploadImageToFirebase(String photoName, Uri localContentUri) {
imagesStorageReferance = myStorageReference.child("images/" + photoName);
imagesStorageReferance.putFile(localContentUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
//getUploadedImageUri(referenceToImageFolder);
imagesStorageReferance.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
Log.d(TAG, "onSuccess: The download url of the photo is "
+ uri.toString());
uploadedImageUri = uri; /// <- I want to retrieve this
}
});
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d(TAG, "onFailure: Failed uploading the photo to the database " + e.getMessage());
}
});
}
From what I have read on the Internet, this is an synchronization problem(basically, the app registers the information to the database before my photo is uploaded). There are many solutions which I have tried, but I can't really figure it out one to work on my case...
I would be very grateful if you could provide me some explanation on what I should do in order to fix this. How can I wait the photo to be uploaded ?
I am sharing the code from my project:
Assign this globally:
StorageTask uploadTask;
String myUrl = "";
and this is code:
private void uploadImage()
{
if (imageUri != null)
{
final StorageReference reference = storageReference.child(System.currentTimeMillis()+"."+getExtension(imageUri));
uploadTask = reference.putFile(imageUri);
uploadTask.continueWithTask(new Continuation() {
#Override
public Object then(#NonNull Task task) throws Exception {
if (!task.isComplete())
{
throw task.getException();
}
return reference.getDownloadUrl();
}
}).addOnCompleteListener(new OnCompleteListener<Uri>() {
#Override
public void onComplete(#NonNull Task<Uri> task) {
if (task.isSuccessful())
{
Uri downloadUri = task.getResult();
myUrl = downloadUri.toString();
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Categories")
.child(randomKey);
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("categoryId", randomKey);
hashMap.put("categoryImage", myUrl);
hashMap.put("categoryName", editText.getText().toString());
databaseReference.setValue(hashMap);
save.setVisibility(View.VISIBLE);
startActivity(new Intent(AddCategoryActivity.this, CategoriesActivity.class));
}
else
{
save.setVisibility(View.VISIBLE);
Toast.makeText(AddCategoryActivity.this, "Failed!", Toast.LENGTH_SHORT).show();
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
save.setVisibility(View.VISIBLE);
Toast.makeText(AddCategoryActivity.this, ""+e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
else
{
save.setVisibility(View.VISIBLE);
Toast.makeText(this, "No Image Selected", Toast.LENGTH_SHORT).show();
}
}
Since firebase works asynchronously, the code continues to execute regardless of whether firebase has finished the upload process or not. In your case, the time to run the code following firebase is faster than the upload time to firebase to eventually assign uploadedImageUri = uri; which explains why you are getting a null value for uploadedImageUri present directly after the call for upload.
For this matter, I would suggest you to register to database inside uploadImageToFirebase function after uploadedImageUri = uri; to ensure that uploadedImageUri is never null and always fetched before database registration.
private void uploadImageToFirebase(String photoName, Uri localContentUri) {
imagesStorageReferance = myStorageReference.child("images/" + photoName);
imagesStorageReferance.putFile(localContentUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
//getUploadedImageUri(referenceToImageFolder);
imagesStorageReferance.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
Log.d(TAG, "onSuccess: The download url of the photo is "
+ uri.toString());
uploadedImageUri = uri;
String title = titleLineEdit.getText().toString();
String category = categoryLineEdit.getText().toString();
String description = descriptionLineEdit.getText().toString();
String date = dateLineEdit.getText().toString();
String time = timeLineEdit.getText().toString();
String location = locationLineEdit.getText().toString();
Map<String, Object> newAnnouncement = new HashMap<>();
newAnnouncement.put("imageUri", uploadedImageUri.toString());
newAnnouncement.put("title", title);
newAnnouncement.put("category", category);
newAnnouncement.put("description", description);
newAnnouncement.put("date", date);
newAnnouncement.put("time", time);
newAnnouncement.put("location", location);
//UPLOAD newAnouncement TO FIREBASE HERE...
}
});
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d(TAG, "onFailure: Failed uploading the photo to the database " + e.getMessage());
}
});
}
My requirement is the end-user must be able to upload files into the application from internal or external storage and finally display the name of the file in the page.
Actual result: Now I've fetched the file name from the storage and displayed the name in my page.
Expected Result: The end user must be able to load image or video files from external or internal storage to the application and finally display their name in the page.
But don't have any idea about how to load read the file from storage and store it in a arrayList.
Code for fetching the file name
public class ServiceDetails extends AppCompatActivity {
private Button next, attachment_one;
private ImageButton attach_file;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_enter_details);
next = findViewById(R.id.submit);
attachment_one = findViewById(R.id.attachmentOne);
attach_file = findViewById(R.id.attachFile);
next.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(ServiceDetails.this, ServiceAddress.class);
startActivity(intent);
}
});
attach_file.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.M &&
checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 10001);
}
new MaterialFilePicker()
.withActivity(ServiceDetails.this)
.withRequestCode(1)
.withFilter(Pattern.compile(".*\\.(mkv|wmv|avi|mpeg|swf|mov|mp4|jpg|jpeg)$"))
.withHiddenFiles(true) // Show hidden files and folders
.start();
}
});
attachment_one.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
attachment_one.setVisibility(View.INVISIBLE);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1 && resultCode == RESULT_OK) {
String file_path = data.getStringExtra(FilePickerActivity.RESULT_FILE_PATH);
String file_array[] = file_path.split("/");
String file_name = file_array[file_array.length - 1];
// Do anything with file
if(attachment_one.getText().toString().isEmpty()) {
attachment_one.setVisibility(View.VISIBLE);
attachment_one.setText(file_name);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case 10001: {
if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(ServiceDetails.this, "Permission granted", Toast.LENGTH_LONG).show();
}else {
Toast.makeText(ServiceDetails.this, "Permission not granted", Toast.LENGTH_LONG).show();
finish();
}
}
}
}
}
I'm new to android and kindly help me providing solution for this answer. Million thanks in advance!
Image showing file attachment option
As you are willing to load the title of video/images, and other file related information from the External Storage. You have to use this code and also make sure don't forget to create a Arraylist with model(required to extract information and find to the listview).
//ContentResolver and contentProvider as well as cursor
String[] projection = new String[]{
MediaStore.Video.Media._ID,
MediaStore.Video.Media.TITLE,
MediaStore.Video.Media.SIZE,
MediaStore.Video.Media.DATE_MODIFIED
};
String selection = null;
String[] selectionargs = null;
String orderBy = MediaStore.Video.Media.DISPLAY_NAME + " Desc";
Uri content_uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
Cursor cursor = getContentResolver().query(content_uri, projection, selection, selectionargs, orderBy);
if (cursor != null) {
cursor.moveToPosition(0);
}
while (true) {
long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID));
Uri VideoUri = ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id);
Log.d("uri", "onCreate: video path " + VideoUri);
String title = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.TITLE));
float size = cursor.getFloat(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE));
// loading a thumbnail from the content resolver
// Load thumbnail of a specific media item.
Bitmap thumbnail = null;
try {
thumbnail = getApplicationContext().getContentResolver().loadThumbnail(VideoUri, new Size(200, 200), null);
Log.d("thumbnail", "onCreate: Lodaing a thumbnail");
} catch (IOException e) {
Log.d("thumbnail", "onCreate: Showing Error on thumbnail");
e.printStackTrace();
}
videolist.add(new Video(thumbnail, VideoUri, title, size));
if (!cursor.isLast()) {
cursor.moveToNext();
} else {
Log.d("lastItem", "onCreate: last uri is encountered");
break;
}
}
cursor.close();
I've been looking for various tutorials but no one can solve my case. I hope here is something that can make me understand, about how to open PDF file automatically after finished download from database to android.
This is my download script.
#Override
public void onBindViewHolder(HolderData holder, int position) {
final ModelData md = mItems.get(position);
holder.txtname.setText(md.getName());
holder.txtwaktu.setText(md.getWaktu());
//Proses Downloading
holder.relativeLayoutMateri.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
uri = String.valueOf(Uri.parse("http://192.168.43.144/MLearning/crud/"+md.getPath()));
dm = (DownloadManager)context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(uri));
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
longid = dm.enqueue(request);
Toast.makeText(context, md.getName()+" Berhasil Di Download"+md.getPath(), Toast.LENGTH_SHORT).show();
}
});
}
Here is the solution please use ACTION_VIEW Intent to open all you need the path of downloaded pdf.
private static String filepath = Environment.getExternalStorageDirectory().getPath()+"/myfile.pdf";
File file = new File(filepath);
if (file.exists()) {
Uri path = Uri.fromFile(file);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(path, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
startActivity(intent);
}
catch (ActivityNotFoundException e) {
Log.d(TAG,e.getMessage());
}
}
I have a question about downloading a pdf file and opening it with an pdf reader application installed on the phone. I'm new to android and working my way up but got stuck on this part.
So what i have now:
I have an activity that for now starts downloading a pdf file and tries to open is with an intent. For now everything is static so thats why i have a set url.
private void DownloadFile(){
DownloadManager downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
Uri Download_Uri = Uri.parse("http://awebiste.adomain/afile.pdf");
DownloadManager.Request request = new DownloadManager.Request(Download_Uri);
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
request.setAllowedOverRoaming(false);
request.setTitle("My Data Download");
request.setDescription("Android Data download using DownloadManager.");
request.setDestinationInExternalFilesDir(this,Environment.DIRECTORY_DOWNLOADS,"test.pdf");
Long downloadReference = downloadManager.enqueue(request);
if (downloadReference != null){
Intent target = new Intent(Intent.ACTION_VIEW);
target.setDataAndType(Uri.parse(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) + "/test.pdf"), "application/pdf");
target.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Log.v("OPEN_FILE_PATH", getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) + "/test.pdf");
startActivity(target);
} else {
//TODO something went wrong error
}
}
Now the file is downloaded and saved in the application folder under /storage.sdcard0/Android/data/<application>/files/download and from the documents browser the file can be opent. But when i use the intent at the button of my code i get a toast that the file can not be opent. After some searching on google i think its a permission problem because these files are private to the application. So how do I make these files public?
Here's How I did it after a long day of search,Your code helped me a little to solve it:
String name;
DownloadManager mManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.show_interview);
Button down = (Button) findViewById(R.id.download);
down.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
down();
}
});
}
public void down() {
mManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
Uri downloadUri = Uri.parse(DOWNLOAD_FILE);
DownloadManager.Request request = new DownloadManager.Request(
downloadUri)
.setAllowedOverRoaming(false)
.setTitle("Downloading")
.setDestinationInExternalPublicDir(
Environment.DIRECTORY_DOWNLOADS, name + "CV.pdf")
.setDescription("Download in progress").setMimeType("pdf");
}
#Override
protected void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter(
DownloadManager.ACTION_DOWNLOAD_COMPLETE);
registerReceiver(broadcast, intentFilter);
}
public void showPdf() {
try {
File file = new File(Environment.getExternalStorageDirectory()
+ "/Download/" + name + "CV.pdf");//name here is the name of any string you want to pass to the method
if (!file.isDirectory())
file.mkdir();
Intent testIntent = new Intent("com.adobe.reader");
testIntent.setType("application/pdf");
testIntent.setAction(Intent.ACTION_VIEW);
Uri uri = Uri.fromFile(file);
testIntent.setDataAndType(uri, "application/pdf");
startActivity(testIntent);
} catch (Exception e) {
e.printStackTrace();
}
}
BroadcastReceiver broadcast = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
showPdf();
}
};