I am trying to use this code to send my application apk file to another device:
public static void sendAppItself(Activity paramActivity) throws IOException {
PackageManager pm = paramActivity.getPackageManager();
ApplicationInfo appInfo;
try {
appInfo = pm.getApplicationInfo(paramActivity.getPackageName(),
PackageManager.GET_META_DATA);
Intent sendBt = new Intent(Intent.ACTION_SEND);
sendBt.setType("*/*");
sendBt.putExtra(Intent.EXTRA_STREAM,
Uri.parse("file://" + appInfo.publicSourceDir));
paramActivity.startActivity(Intent.createChooser(sendBt,
"Share it using"));
} catch (PackageManager.NameNotFoundException e1) {
e1.printStackTrace();
}
}
This code works very well.
But the name of the apk file shared with this code is base.apk
How can I change it?
Copy the file from the source directory to a new directory.
Rename the file while copying and share the copied file.
Delete the temp file after share is complete.
private void shareApplication() {
ApplicationInfo app = getApplicationContext().getApplicationInfo();
String filePath = app.sourceDir;
Intent intent = new Intent(Intent.ACTION_SEND);
// MIME of .apk is "application/vnd.android.package-archive".
// but Bluetooth does not accept this. Let's use "*/*" instead.
intent.setType("*/*");
// Append file and send Intent
File originalApk = new File(filePath);
try {
//Make new directory in new location
File tempFile = new File(getExternalCacheDir() + "/ExtractedApk");
//If directory doesn't exists create new
if (!tempFile.isDirectory())
if (!tempFile.mkdirs())
return;
//Get application's name and convert to lowercase
tempFile = new File(tempFile.getPath() + "/" + getString(app.labelRes).replace(" ","").toLowerCase() + ".apk");
//If file doesn't exists create new
if (!tempFile.exists()) {
if (!tempFile.createNewFile()) {
return;
}
}
//Copy file to new location
InputStream in = new FileInputStream(originalApk);
OutputStream out = new FileOutputStream(tempFile);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
System.out.println("File copied.");
//Open share dialog
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(tempFile));
startActivity(Intent.createChooser(intent, "Share app via"));
} catch (IOException e) {
e.printStackTrace();
}
}
Update: this method does not work anymore and throws exception if you implement it. Since android N, we should use content providers if we want to have access to files in memory(like the apk file). For more information please visit this Guide. Although the whole idea of copying and renaming and sharing the copied version is still valid.
You can use this function, test on api 22 and 27
private void shareApplication() {
ApplicationInfo app = getApplicationContext().getApplicationInfo();
String filePath = app.sourceDir;
Intent intent = new Intent(Intent.ACTION_SEND);
// MIME of .apk is "application/vnd.android.package-archive".
// but Bluetooth does not accept this. Let's use "*/*" instead.
intent.setType("*/*");
// Append file and send Intent
File originalApk = new File(filePath);
try {
//Make new directory in new location=
File tempFile = new File(getExternalCacheDir() + "/ExtractedApk");
//If directory doesn't exists create new
if (!tempFile.isDirectory())
if (!tempFile.mkdirs())
return;
//Get application's name and convert to lowercase
tempFile = new File(tempFile.getPath() + "/" + getString(app.labelRes).replace(" ","").toLowerCase() + ".apk");
//If file doesn't exists create new
if (!tempFile.exists()) {
if (!tempFile.createNewFile()) {
return;
}
}
//Copy file to new location
InputStream in = new FileInputStream(originalApk);
OutputStream out = new FileOutputStream(tempFile);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
System.out.println("File copied.");
//Open share dialog
// intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(tempFile));
Uri photoURI = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider", tempFile);
// intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(tempFile));
intent.putExtra(Intent.EXTRA_STREAM, photoURI);
startActivity(Intent.createChooser(intent, "Share app via"));
} catch (IOException e) {
e.printStackTrace();
}
}
This only happens because it is saved by base.apk name.
To share it as per your need you have to just copy this file into another directory path and rename it over there. Then use new file to share.
This file path[file:///data/app/com.yourapppackagename/base.apk] in data folder is having only read permissions so you can't rename .apk file over there.
2021 Kotlin way
First we need to set a file provider
In AndroidManifest.xml create a File provider
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true"
>
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"
/>
</provider>
If you don't have file_path.xml the create one in res/xml (create xml folder if it doesn't exist)
and in file_path.xml add
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path
name="apk"
path="cache/ExtractedApk/" />
</paths>
Now add the code to share the apk
private fun shareAppAsAPK(context: Context) {
val app: ApplicationInfo = context.applicationInfo
val originalApk = app.publicSourceDir
try {
//Make new directory in new location
var tempFile: File = File(App.instance.getExternalCacheDir().toString() + "/ExtractedApk")
//If directory doesn't exists create new
if (!tempFile.isDirectory) if (!tempFile.mkdirs()) return
//rename apk file to app name
tempFile = File(tempFile.path + "/" + getString(app.labelRes).replace(" ", "") + ".apk")
//If file doesn't exists create new
if (!tempFile.exists()) {
if (!tempFile.createNewFile()) {
return
}
}
//Copy file to new location
val inp: InputStream = FileInputStream(originalApk)
val out: OutputStream = FileOutputStream(tempFile)
val buf = ByteArray(1024)
var len: Int
while (inp.read(buf).also { len = it } > 0) {
out.write(buf, 0, len)
}
inp.close()
out.close()
//Open share dialog
val intent = Intent(Intent.ACTION_SEND)
//MIME type for apk, might not work in bluetooth sahre as it doesn't support apk MIME type
intent.type = "application/vnd.android.package-archive"
intent.putExtra(
Intent.EXTRA_STREAM, FileProvider.getUriForFile(
context, BuildConfig.APPLICATION_ID + ".fileprovider", File(tempFile.path)
)
)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
startActivity(intent)
} catch (e: IOException) {
e.printStackTrace()
}
}
If someone trying to generate apk from fragment they may need to change few lines from #sajad's answer as below
Replace
File tempFile = new File(getExternalCacheDir() + "/ExtractedApk");
with
File tempFile = new File(getActivity().getExternalCacheDir() + "/ExtractedApk");
2.while importing BuildConfig for below line
import androidx.multidex.BuildConfig // DO NOT DO THIS!!! , use your app BuildConfig.
and if you're getting below EXCEPTION
Couldn't find meta-data for provider with authority
Look for provider info in manifest file
then look for "provider"s name and authority in your manifest file and if it's androidx.core.content.FileProvider then
Replace
Uri photoURI = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider", tempFile);
With
Uri photoURI = FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID + ".fileprovider", tempFile);
Related
I am trying to create PDF file from base64 string. Because of Storage Update in Android 11, I have to change my code but I'm getting following error in Android 11 devices:
java.lang.IllegalArgumentException: Primary directory (invalid) not allowed for content://media/external/file; allowed directories are [Download, Documents]
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:172)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:142)
at android.content.ContentProviderProxy.insert(ContentProviderNative.java:549)
at android.content.ContentResolver.insert(ContentResolver.java:2149)
at android.content.ContentResolver.insert(ContentResolver.java:2111)
This code create a PDF file and save it into folder.
public static void createPDF(Context mContext, String fileName, String base64) {
try {
String folderPath;
File dwldsPath;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
folderPath = mContext.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS) + File.separator + "appFolderName";
dwldsPath = new File(folderPath + "/" + fileName);
File folder = new File(folderPath);
folder.mkdirs();
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName); // file name
values.put(MediaStore.MediaColumns.MIME_TYPE, "application/pdf"); // file extension, will automatically add to file
values.put(MediaStore.DownloadColumns.RELATIVE_PATH, folderPath); // end "/" is not mandatory
Uri uriFile = mContext.getContentResolver().insert(MediaStore.Files.getContentUri("external"), values); // important!
OutputStream outputStream = mContext.getContentResolver().openOutputStream(uriFile);
outputStream.write(Base64.decode(base64, 0));
outputStream.close();
} else {
folderPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) + File.separator + "appFolderName";
dwldsPath = new File(folderPath + "/" + fileName);
File folder = new File(folderPath);
folder.mkdirs();
FileOutputStream os = new FileOutputStream(dwldsPath, false);
os.write(Base64.decode(base64, 0));
os.flush();
os.close();
}
openPDF(mContext, dwldsPath);
} catch (IOException e) {
e.printStackTrace();
} catch (ActivityNotFoundException e) {
Toast.makeText(mContext, "No PDF Viewer Installed", Toast.LENGTH_LONG).show();
}
}
This code is working for opening file
public static void openPDF(Context mContext, File dwldsPath) {
Intent intentUrl = new Intent(Intent.ACTION_VIEW);
Uri uri = FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID + ".provider", dwldsPath);
intentUrl.setDataAndType(uri, "application/pdf");
intentUrl.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentUrl.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
mContext.startActivity(intentUrl);
}
In addition to this error, folder.mkdirs() returns false in Android 11. Here is provider_paths.xml and defined in AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external"
path="." />
<external-files-path
name="external_files"
path="." />
<files-path
name="files"
path="." />
</paths>
I google it but I couldn't find any working solution to fix problem. Thanks in advance.
I finally found a solution. I can't say it's a best solution but it works perfectly.
folderPath = mContext.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS) + File.separator + "appFolderName";
to
folderPath = mContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) + File.separator + "appFolderName";
I suppose in Android 11, they allowed to create folder/file in DOWNLOADS folder but not DOCUMENTS. Best regards.
Note for Huawei Developers: You just keep the current file writing strategy. No need to Android 11 special code for now. I tried the new file writing method and it crashed. Apperantly, they didn't fully implemented Android 11.
Since Android 10 (API 29) I need to use the Storage Access Framework's File Picker to select GPX (GPS) files to copy from the Downloads folder to my local app folder. I have implemented the file picker and am able to select the GPX file, however the result data URI appears different to the filename (but unique) and I cannot seem to use it to copy the files. The rest of the code is the same "copy" code I used in previous versions of Android. What am I doing wrong and how should I best use the SAF File Picker to copy files? I haven't been able to find a recent (API 29) "file copy" example on the net...
private static final int READ_REQUEST_CODE = 42;
...
public void performFileSearch() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
// intent.setType("application/gpx"); // Filters GPX file but wont let me select them.
intent.setType("*/*");
startActivityForResult(intent, READ_REQUEST_CODE);
}
...
if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
Uri uri = null;
if (data != null) {
uri = data.getData();
handleDownloadedGPXFiles2(uri);
}
}
...
private void handleDownloadedGPXFiles2(Uri selectedFileUri) {
File sourceFile = new File(selectedFileUri.getPath()); // Returns a unique number or string but NOT filename string???
File destDirectory = new File(this.getExternalFilesDir(null), "Imported");
File destFile = new File(destDirectory, "test.gpx"); // Needs to be same name as original filename.
try {
if (!destFile.exists()) {
destFile.createNewFile();
}
FileInputStream inStream = new FileInputStream(sourceFile);
FileOutputStream outStream = new FileOutputStream(destFile);
FileChannel inChannel = inStream.getChannel();
FileChannel outChannel = outStream.getChannel();
inChannel.transferTo(0, inChannel.size(), outChannel);
inStream.close();
outStream.close();
} catch (IOException e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(), "File Import Complete", Toast.LENGTH_LONG).show();
}
File sourceFile = new File(selectedFileUri.getPath());
Remove above line.
FileInputStream inStream = new FileInputStream(sourceFile);
Replace that line by:
InputStream inStream = getContentResolver().openInputStream(selectedFileUri);
Further you can remove
if (!destFile.exists()) {
destFile.createNewFile();
}
as the file will be created by the new FileOutputStream();
Finally: Your last Toast() is on the wrong place. It should be in the try block.
Place a different Toast() in the catch block to inform yourself or the user.
Thanks blackapps. Final code works well...
private void handleDownloadedGPXFiles2(Uri selectedFileUri) {
String displayName = "imported.gpx";
String fileExtension;
ContentResolver contentResolver = getContentResolver();
Cursor cursor = contentResolver.query(selectedFileUri, null, null, null, null);
try {
if (cursor != null && cursor.moveToFirst()) {
displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
if (displayName != null && displayName.length() >=4) {
fileExtension = displayName.substring(displayName.length() - 4);
if (!fileExtension.equals(".gpx")){
myCustomToast("Must be a .GPX file!");
return;
}
} else {
myCustomToast("Must be a .GPX file!");
return;
}
}
File destDirectory = new File(this.getExternalFilesDir(null), "Imported");
File destFile = new File(destDirectory, displayName);
FileOutputStream outStream = new FileOutputStream(destFile);
InputStream in = getContentResolver().openInputStream(selectedFileUri);
OutputStream out = outStream;
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
out.flush();
out.close();
Toast.makeText(getApplicationContext(), "File Import Complete", Toast.LENGTH_LONG).show();
} catch (IOException e) {
Toast.makeText(getApplicationContext(), "File Import FAILED", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
finally
{
if (cursor != null)
cursor.close();
}
}
public void share(String song){
Uri uri = Uri.parse("android.resource://com.dsbsoft.myApp/raw/"+song+".mp3");
Intent share = new Intent(Intent.ACTION_SEND);
share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
share.setType("audio/mp3");
share.putExtra(Intent.EXTRA_STREAM, uri);
this.startActivity(Intent.createChooser(share, "Send song"));
}
all works perfectly but at the time to send the file, i think, it's not exists...
In the void comes String variable song, that contains the name of file.
For example:
the call was: share("abc"); i want to send the mp3 file(it is in raw folder) abc.mp3
Apparently we can't send directly resourse files.
Thats why i do the following.
To send mp3 file, i burn it on a folder in the storage and share this new file.
the code:
public void makeOutSide(String song, InputStream ins){
// Create the directory
File dir = new File(Environment
.getExternalStorageDirectory() + "/.CSOUNDS/");
// If it does not exists, make it.
if (!dir.exists()) {
dir.mkdir(); // Generating the directory
}
try {
// Open the resource
byte[] buffer = new byte[ins.available()];
ins.read(buffer);
ins.close();
// Burn
String filename = Environment
.getExternalStorageDirectory().toString()
+ "/.CSOUNDS/"+song+".mp3";
FileOutputStream fos = new FileOutputStream(filename);
fos.write(buffer);
fos.close();
} catch (Exception e) { }
}
public void share(String song, InputStream ins){
makeOutSide(song,ins);
String rout = Environment.getExternalStorageDirectory().toString()+"/.CSOUNDS/"+song+".mp3";
Uri uri = Uri.parse(rout);
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("audio/*");
share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
share.putExtra(Intent.EXTRA_STREAM,uri);
startActivity(Intent.createChooser(share, "Share song"));
}
in the call of the share method comes an InputStream ins at this way:
InputStream ins = getResources().openRawResource(R.raw.abc);
share("abc",ins);
Try this:
public void share(String song){
File audio = new File("android.resource://com.dsbsoft.myApp/raw/+song+ ".mp3");
Intent share = new Intent(Intent.ACTION_SEND).setType("audio/*");
share.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(audio));
startActivity(Intent.createChooser(share, "Share song"));
}
I'm following the Google Camera Tutorial for an Android application. At this moment, I'm able to take a picture, save it, show the path and show the bitmap into an ImageView.
Here is an exemple of the logcat when I ask for the absolute path of a picture I just took :
D/PATH:: /storage/emulated/0/Pictures/JPEG_20160210_140144_217642556.jpg
Now, I would like to transfer it on a PC via USB. When I broswe into the device storage, I can see the public folder Picturethat I called earlier in my code with the variable Environment.DIRECTORY_PICTURES. However, there is nothing in this folder.
Screenshot of my device's folders
I can't insert a SD Card in my device to test. Also, I don't want to put the pictures into cache directory for preventing to be deleted.
Here is my permissions in Manifest :
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
When the user click on the camera buttons :
dispatchTakePictureIntent();
[...]
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
This is method creating the file
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = "file:" + image.getAbsolutePath();
Log.d("PATH:", image.getAbsolutePath());
return image;
}
I guess I misunderstood something about the External Storage. Can someone explain me why I can't save a picture and access it on a PC ? Thank you !
-- EDIT --
After reading an answer below, I tried to get the file in OnActivityResult and to save it with Java IO. Unfortunately, there is no file in Pictures folder when I look with Explorer.
if (requestCode == REQUEST_TAKE_PHOTO) {
Log.d("AFTER", absolutePath);
// Bitmap bitmap = BitmapFactory.decodeFile(absolutePath);
// imageTest.setImageBitmap(Bitmap.createScaledBitmap(bitmap, 2100, 3100, false));
moveFile(absolutePath, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString());
}
private void moveFile(String inputFile, String outputPath) {
InputStream in = null;
OutputStream out = null;
try {
//create output directory if it doesn't exist
File dir = new File (outputPath);
if (!dir.exists())
{
dir.mkdirs();
}
in = new FileInputStream(inputFile);
out = new FileOutputStream(outputPath + imageFileName + ".jpg");
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
in = null;
// write the output file
out.flush();
out.close();
out = null;
// delete the original file
new File(inputFile).delete();
}
You're currently saving the file as a temporary file, so it won't persist on disk after the application lifecycle. Use something like:
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
File f = new File(Environment.getExternalStorageDirectory() + [filename])
And then create a FileOutputStream to write to it.
FileOutStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
To solve my problem, I had to write the file into the application's data folder and to user the MediaScannerConnection. I've put a .txt file for testing, but after it works you can put any other file.
I'll share the solution for those who have a similar problem :
try
{
// Creates a trace file in the primary external storage space of the
// current application.
// If the file does not exists, it is created.
File traceFile = new File(((Context)this).getExternalFilesDir(null), "TraceFile.txt");
if (!traceFile.exists())
traceFile.createNewFile();
// Adds a line to the trace file
BufferedWriter writer = new BufferedWriter(new FileWriter(traceFile, true /*append*/));
writer.write("This is a test trace file.");
writer.close();
// Refresh the data so it can seen when the device is plugged in a
// computer. You may have to unplug and replug the device to see the
// latest changes. This is not necessary if the user should not modify
// the files.
MediaScannerConnection.scanFile((Context)(this),
new String[] { traceFile.toString() },
null,
null);
}
catch (IOException e)
{
Log.d("FileTest", "Unable to write to the TraceFile.txt file.");
}
I'm trying to get a image from android Photos app using the share option that point to my PhotoGetFromGallery activity. Here is the code:
public void copy(File src, File dst) throws IOException {
FileInputStream inStream = new FileInputStream(src);
FileOutputStream outStream = new FileOutputStream(dst);
FileChannel inChannel = inStream.getChannel();
FileChannel outChannel = outStream.getChannel();
inChannel.transferTo(0, inChannel.size(), outChannel);
inStream.close();
outStream.close();
}
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
void handleSendImage(Intent intent) {
Uri imageUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
String sourcePath = getRealPathFromURI(imageUri);
if(isExternalStorageWritable()) {
if (imageUri != null) {
File sd = Environment.getExternalStorageDirectory();
File data = Environment.getDataDirectory();
String destinationImagePath = sd + "/Pictures/MyAppImgFolder/";
File source = new File(data, sourcePath);
String fileName = source.getName();
File destination = new File(sd, destinationImagePath + fileName);
try {
copy(source, destination);
} catch (Exception e) {
Log.e("COPY IMAGE ERROR", e.toString() + ". Destination Path is " + destinationImagePath.toString() + " and Source path is "+ sourcePath);
}
}
}
}
sourcePath string returns the correct image path (ex. /storage/emulated/0/Pictures/Instagram/IMG_20150413_114608.jpg). However, I'm getting the FileNotFoundException because Environment.getDataDirectory() returns /data/storage/emulated/0/Pictures/Instagram/IMG_20150413_114608.jpg.
Here is my log:
E/COPY IMAGE ERRORīš java.io.FileNotFoundException: /data/storage/emulated/0/Pictures/Instagram/IMG_20150413_114608.jpg: open failed: ENOENT (No such file or directory). Destination Path is /storage/emulated/0/Pictures/MyAppImgFolder/ and Source path is /storage/emulated/0/Pictures/Instagram/IMG_20150413_114608.jpg
Here is my AndroidManifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
My question is how can I get, if possible, any path of images stored at Photos app or Android Gallery?
You should not be using getDataDirectory - you are already being handed a complete path, starting with "/storage" Use the single argument File() constructor passing only the sourcePath, like this:
File sd = Environment.getExternalStorageDirectory();
String destinationImagePath = sd + "/Pictures/MyAppImgFolder/";
//sourcePath is already a full path name
File source = new File(sourcePath);
//redundant String fileName = source.getName();
File destination = new File(destinationImagePath + sourcePath);
//You are proposing many new subdirectories, so you must create them
destination.getParentFile()makeDirs();
//now you can continue with your copy attempt
I managed to solve the problem. Follows the code that works . Thanks to Chris Stratton for guiding me in this matter.
File sd = Environment.getExternalStorageDirectory();
String destinationImagePath = sd + AppConstant.PHOTO_ALBUM;
File imagePath = new File(destinationImagePath);
File source = new File(sourcePath);
String fileName = source.getName();
File destination = new File(destinationImagePath + fileName);
if (!imagePath.exists()) {
imagePath.mkdirs();
try {
copy(source, destination);
Toast.makeText(getApplicationContext(), "Success! File was copy from " + sourcePath + " to " + destinationImagePath, Toast.LENGTH_LONG).show();
} catch (Exception e) {
Log.e("COPY IMAGE ERROR", e.toString());
}
} else if(destination.exists() && !destination.isDirectory()){
Toast.makeText(getApplicationContext(), "Image is already on your image folder", Toast.LENGTH_LONG).show();
}