I'm working on an app that saves thermal images from a FLIR camera to the SD Card on the phone.
I'm using Android Marshmallow and I have to use the FLIR SDK.
In the FLIR SDK is a class "Frame". The class has a method "Frame.save", that needs a Java.io.File to save a thermal image: This is from the documentation:
public void save(java.io.File file,
RenderedImage.Palette previewPalette,
RenderedImage.ImageType previewImageType)
throws java.io.IOException,
java.lang.IllegalArgumentException
Saves a thermal JPEG file, which has a rendered visual preview and embedded thermal data
When I understand it right, on KitKat or higher I have to use the Storage Accsess Framework. So I used it. Send a Intent and get back a Uri to a picked folder on the SD Card. Now to the tricky part. This funktion should create a File and return a Java.io.File that ready for the "Frame.save" method.
public File getJavaFile (String Name, Uri myUri) {
DocumentFile pickedDir = DocumentFile.fromTreeUri(context, myUri); // Document file aus URI
DocumentFile DocumentFile = pickedDir.createFile("image/plain", Name + ".jpg" );
File file = new File(DocumentFile.getUri().getPath());
if(file.canWrite()){
Log.d(TAG + "/getJavaFile", "File can write");
}else {
Log.e(TAG + "/getJavaFile", "File cannot write");
}
Log.d(TAG + "/getJavaFile:", "File Created:" + file.getPath());
return file;
}
The file that the function return is not readable or writeable...
Otherwise, when I try to create a File directly, like so:
String root = Environment.getExternalStorageDirectory().toString();
File file = new File(root + "/saved_images");
Log.d(TAG, file.getPath());
Then the the system always gives me this emulated folder:
E/MainActivity: /storage/emulated/0/saved_images
So the question is: How to get a useable Java File, thats stored on the public storage space... Thank you for your time!
Related
I want to download file to public dir, it works well when sdcard is avaialble but gives me above error when sdcard is not avaiable. I do checking of sdcard.
I want to save files to DIRECTORY_MUSIC which is public by default. But the line request.setDestinationInExternalFilesDir() gives me above error.
Here is the code so far I have written
File dir = new File(Environment
.DIRECTORY_MUSIC + "/" + DIR_NAME + "/");
if (!dir.exists()) {
// create dir for first time
Log.d(LOG_TAG, "first time created dir");
dir.mkdir();
}
DownloadManager dm = (DownloadManager) v.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
Uri songLink = Uri.parse(streamUrl);
DownloadManager.Request request = new DownloadManager.Request(songLink);
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(false)
.setTitle(title)
.setMimeType("audio/mp3")
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
.setDestinationInExternalFilesDir(v.getContext(), dir.getAbsolutePath(),
File.separator + DIR_NAME + File.separator + title);
dm.enqueue(request);
What changes should I do to save file in that dir
I want to save music file which I am downloading from an url and saving to public music directory so that music player will find that file
My question is how Whatsapp make WhatsApp audio folder and download the whatsapp audios to that dir. For phones with SD card I can do this but I fail when there's no SD card in phone. How it is done ?
To save download file in public directory:
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_MUSIC, filename);
This method throws:
Throws
IllegalStateException
If the external storage directory cannot be found or create
So you must check if external storage is writable before use.
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
Also requires permission:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
More info
I'm learning from treehouse and building a self destructing messaging app tutotrial link now the instructer is saying save files in external storage but since i don't have a device with external storage i want to save file in internal storage and i wrote this code but it seems not working
private Uri getOutputMediaFileUri(int mediaType) {
String appName = null;
File mediaStorage = null;
if(isExternameStorageAvailable()){
// 1. get the external storage directory
appName = MainActivity.this.getString(R.string.app_name);
mediaStorage = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), appName);
// 2. create our subdir
if(!mediaStorage.exists()){
if(!mediaStorage.mkdirs()){
Log.e(TAG, "Failed to create directory");
return null;
}
}
// 3. create a file name
// TODO: 05 05
// 4. create the file
}else{
appName = MainActivity.this.getString(R.string.app_name);
ContextWrapper contextWrapper = new ContextWrapper(getApplicationContext());
mediaStorage = contextWrapper.getDir(appName, Context.MODE_PRIVATE);
if(!mediaStorage.exists()){
if(!mediaStorage.mkdirs()){
Log.e(TAG, "Failed to create directory");
return null;
}
}
}
File mediaFile = null;
Date now = new Date();
String timeStampe = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(now);
String path = mediaStorage.getPath() + File.separator;
if(mediaType == MEDIA_TYPE_IMAGE){
mediaFile = new File(path + "IMG_" + timeStampe + ".jpg");
}else if(mediaType == MEDIA_TYPE_VIDOE){
mediaFile = new File(path + "VID_" + timeStampe + ".mp4");
}
Log.d(TAG, "FILE:" + Uri.fromFile(mediaFile));
return Uri.fromFile(mediaFile);
}
all the Uri object is returning null
Maybe you can try this, I used this to access and make directory in internal storage:
String internalPath = Environment.getRootDirectory().getAbsolutePath();
Don't think of external storage as a sd/memory stick. It will exist on your device as a virtual folder on your device.
All Android devices have two file storage areas: "internal" and "external" storage. These names come from the early days of Android, when most devices offered built-in non-volatile memory (internal storage), plus a removable storage medium such as a micro SD card (external storage). Some devices divide the permanent storage space into "internal" and "external" partitions, so even without a removable storage medium, there are always two storage spaces and the API behavior is the same whether the external storage is removable or not. The following lists summarize the facts about each storage space.
More at...
http://developer.android.com/training/basics/data-storage/files.html#InternalVsExternalStorage
I am downloading a pdf file from server and saving it on sd card without extension (for security purpose so that normal user can't open that file from file manager).For e.g.- I am downloading abc.pdf and saving it on sd card with abc on below path
String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
File folder = new File(extStorageDirectory, "files");
And later I want to view that file by adding extension.
So when I am accessing that file from code by using below code then its gives error file does't exist..
String s=Environment.getExternalStorageDirectory() + "/files/" + "abc";
File pdfFile = new File(s+".pdf");
So how can I save file in sd card without extension and later open that file with extension.
Workaround for your problem is to rename your saved pdf file without extension to filename with .pdf extension & after completing/accessing view or read operation on your new pdf extension file again you can rename it to file without extension
Example Usage:
String currentFileName = Environment.getExternalStorageDirectory() + File.separator
+ "files" + File.separator + "abc";
String renamedFilename = currentFileName + ".pdf";
boolean isRenamed = renameFile(currentFileName, renamedFilename);
Log.d("isRenamed: ", "" + isRenamed);
if(isRenamed {
//perform your operation
}
Again rename the file if not in use (here exchange renameFile() parameters):
boolean renameAfterOperation = renameFile(renamedFilename, currentFileName);
Log.d("renameAfterOperation : ", "" + renameAfterOperation );
And here is renameFile(currentFilePath, renamedFilePath):
public boolean renameFile(String currentFilePath, String renamedFilePath){
File currentFile = new File(currentFilePath);
File newFile = new File(renamedFilePath);
boolean isrenamed = currentFile.renameTo(newFile);
return isrenamed;
}
In this way whenever you want to perform operation on saved file first rename it to .pdf & whenever it's not in use, again rename it without extension. Let me know if this works for you..
I have got a problem with backup database in my app. I am working on Android 2.2.3 and this has sd card installed. Making copy of the database works fine. The problem occures when I'am testing my app on the phone with internal memory enought big like sd cards (Nexus 32gb). In this scenario my method doesn't work extracting file to sd card because it doesn't (sd card) exist. How to make copy of database to internal independed location? I've tried:
File outPut = new File(Environment.getRootDirectory().toString() + "/myfolder/");
but got permission denied and can not create folder with data. Can anyone show correct way?
EDITED:
I don't get it. I'd like to make new folder with dataBackup. I've defined correct location for that but it says that can not find file. SDCard is present. Why it can not create that folder - "/storeUGif/databaseName.db".?
Here is absolute path for destination folder:
public static final String OUTPUT_BACKUP_DATABASE = Environment.getExternalStorageDirectory().getAbsolutePath() + "/storeUGif/" + SqliteHelper.DATABASE_NAME;
if(isSdPresent())
{
//File outPut = new File(Environment.getExternalStorageDirectory().getAbsolutePath().toString()+"/StoreUGif/"+SqliteHelper.DATABASE_NAME);
File outPut = new File(Tools.OUTPUT_BACKUP_DATABASE);
File storeUGif = new File(Environment.getExternalStorageDirectory().getAbsolutePath().toString());
storeUGif.mkdir();
File currentDB = getApplicationContext().getDatabasePath(SqliteHelper.DATABASE_NAME);
FileInputStream is = new FileInputStream(currentDB);
OutputStream os = new FileOutputStream(outPut);
byte[] buffer = new byte[1024];
while (is.read(buffer) > 0) {
os.write(buffer);
}
os.flush();
os.close();
is.close();
}
else
{
Toast.makeText(this, "SDCard is unvailable", Toast.LENGTH_SHORT).show();
}
Use Environment.getExternalStorageDirectory() to get a valid path.
Despite its name, it will return the default storage, either the external or (if missiing) the internal one.
For reference: http://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory()
It looks like I can not play videos stored in my internal application directory.
I have videos stored in /data/data/my.package.org/files/
And I'm trying to play a file from there using
String fpath = "/data/data/my.package.org/files/video.mpg"
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(fpath), "video/*");
But both Android default video player and some external videoplayer (MX player) say 'this video can not be played".
Whereas when I'm saving videos to SD card they are played fine.
Why is that?
Put your video in assets folder and use this code to play video with MediaPlayer
InputStream is = getResources().getAssets().open("video.mpg");
OR
Put your video in assets folder and...
String fpath = "/data/data/my.package.org/assets/video.mpg"
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(fpath), "video/*");
put your video in the res\raw folder. Then copy it out to the external directories where apps like video player can read them. Only your app can read /data/data/blah....
if its in res\raw, then
typeName = sourceSink.Types.video.toString();
for (sourceSink.VideoFiles video: sourceSink.VideoFiles.values() ){
resourceName = video.toString();
fileName = resourceName + ".mp4";
resource = getResources().getIdentifier(resourceName, "raw", "com.invodo.allshareplay");
createExternalStoragePublicFile(typeName,fileName,resource);
}
and then you can use this to copy it:
void createExternalStoragePublicFile(String fType, String fname, int res ) {
// Create a path where we will place our picture in the user's
// public pictures directory. Note that you should be careful about
// what you place here, since the user often manages these files. For
// pictures and other media owned by the application, consider
// Context.getExternalMediaDir().
File path = null;
if (((fType.equals(sourceSink.Types.photo.toString())) || (fType.equals(sourceSink.Types.file.toString())) ) ){
path = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
}
if (fType.equals(sourceSink.Types.music.toString())) {
path = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_MUSIC);
}
if (fType.equals(sourceSink.Types.video.toString())) {
path = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_MOVIES);
}
File file = new File(path, "/" + fname);
try {
// Make sure the Pictures directory exists.
path.mkdirs();
// Very simple code to copy a picture from the application's
// resource into the external file. Note that this code does
// no error checking, and assumes the picture is small (does not
// try to copy it in chunks). Note that if external storage is
// not currently mounted this will silently fail.
InputStream is = getResources().openRawResource(res);
OutputStream os = new FileOutputStream(file);
byte[] data = new byte[is.available()];
is.read(data);
os.write(data);
is.close();
os.close();
scanMedia(file);
} catch (IOException e) {
// Unable to create file, likely because external storage is
// not currently mounted.
Log.w("ExternalStorage", "Error writing " + file, e);
}
}
then it's easy - just do the second half of the answer I provided and write them out. /data/data/ folder is never going to be viewed by anything other than your app.