Making Android filepaths uniform - android

I have three segments of code: one that sets the original filepath of the file, one that is used in renaming the file, and one that is used to match the file so that the file (audio recording) can be played.
My problem is that, to the best of my knowledge & what I have been able to find out online, I need "file://" before the rest of the filepath when I am renaming it...otherwise the MediaPlayer throws up exceptions when I try to do the playback. After much searching, I have not come up with a good way to make them uniform so that the "matcher" code can work on all the files. My best guess is that it would be ideal if I could find a way to not have to use "file://" before the rest of the filepath.
1) Code that sets original filepath:
public void setFileNameAndPath(){
int count = 0;
File f;
do{
count++;
mFileName = getString(R.string.default_file_name)
+ " #" + (mDatabase.getCount() + count) + ".mp4";
mFilePath = Environment.getExternalStorageDirectory().getAbsolutePath();
mFilePath += "/SoundRecorder/" + mFileName;
f = new File(mFilePath);
}while (f.exists() && !f.isDirectory());
}
2) Renaming the filepath:
public void rename(int position, String name) {
//rename a file
String mFilePath = "file://" + Environment.getExternalStorageDirectory().getAbsolutePath();
mFilePath += "/SoundRecorder/" + name;
File f = new File(mFilePath);
if (f.exists() && !f.isDirectory()) {
//file name is not unique, cannot rename file.
Toast.makeText(mContext,
String.format(mContext.getString(R.string.toast_file_exists), name),
Toast.LENGTH_SHORT).show();
} else {
//file name is unique, rename file
File oldFilePath = new File(getItem(position).getFilePath());
oldFilePath.renameTo(f);
mDatabase.renameItem(getItem(position), name);
notifyItemChanged(position);
}
}
3) Matching the file:
Intent iin = getIntent();
Bundle b = iin.getExtras();
newString = (String) b.get("filename");
mFilePath = Environment.getExternalStorageDirectory().getAbsolutePath();
mFilePath += "/SoundRecorder/" + newString;

I think file:// is the URI of the file and it's useful for example in a mediaplayer where the resource can exists on local storage (file://) or over internet (http://)
To "convert" string to URI use
Uri uri = Uri.parse("http://www.google.com");
And to "convert" URI to file use
File file = new File(uri.getPath());

Related

checking a file if it exist or not exist (not working)

I am trying to check the mp3 file located to my raw folder under my res. my mp3 file is exist but my code gives me a false return.
String filename = "android.resource://" + this.getPackageName() + "/raw/w";
Toast.makeText(ViewPager.this, mp3check(filename)+"",Toast.LENGTH_LONG).show();
checking the mp3 file
public boolean mp3check(String _filename) {
return new File(_filename).exists();
}
I don't think you can treat a raw resource as a regular file.
Since it is a resource, there is no need to check if it exists.
You can open it using the resource ID.
For example, if your file is named, mysong.mp3, you can open it like this:
InputStream is = getResources().openRawResource(R.raw.mysong);
or
AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.mysong);
You can use the AssetFileDescriptor to play it with a MediaPlayer.
try this
String filename = "android.resource://" + this.getPackageName() + "/raw/w";
String newFilePath = "new file path"; // ExternalStorageDirectory path
final Path destination = Paths.get(newFilePath );
try (
final InputStream in = getResources().openRawResource(R.raw.w);
) {
Files.copy(in, destination);
}
Toast.makeText(ViewPager.this, mp3check(filename)+"",Toast.LENGTH_LONG).show();
public boolean mp3check(String _newFilePath) {
return new File(_newFilePath).exists();
}

Android New Image has strange numbers on the end of the file name

I'm writing a camera2 app in android and when I try to save the image, something adds extra numbers on the end of the filename before the '.jpg'
I have a feeling it's because of the createTempFile() method, but here's my code:
File createImageFile() throws IOException {
++image_id;
String timestamp = new SimpleDateFormat("yyyyMMdd").format(new Date());
String subFolder = "";
if(pref_session_unique_gallery.equals("yes")){
if(event_name != null){
subFolder = event_name;
} else {
subFolder = timestamp;
}
} else {
subFolder = "_GEN";
}
if(event_name == null){
imageFileName = "CPB_"+timestamp+"-"+image_id;
} else {
imageFileName = "CPB_"+event_name+"_"+timestamp+"-"+image_id;
}
imageStorageDirectory = Environment.getExternalStorageDirectory() + File.separator + "CPB" + File.separator + subFolder;
imageFinalFileName = imageFileName;
Toast.makeText(getApplicationContext(), imageStorageDirectory + "/" + imageFileName, Toast.LENGTH_LONG).show();
File storageDirectory = new File(imageStorageDirectory);
storageDirectory.mkdir();
File image = File.createTempFile(imageFileName, ".jpg", storageDirectory);
return image;
}
When I read the toast it gives me the correct path and filename that I am expecting, but when I look in my folder view, the picture has a lot of extra numbers on it.
For example, the picture name should be CPB_20160120-1.jpg but it currently reads CPB_20160120-1484291604.jpg If it makes a difference, the file was saved at 6:37 PM
two more examples:
should be: CPB_20160120-2.jpg
is: CPB_20160120-22140921986.jpg
should be: CPB_20160120-3.jpg
is: CPB_20160120-3-965716644.jpg
Not sure where those extra numbers are coming from when the file saves...
Those random numbers are explicitly generated by createTempFile(), as seen in the source code.
You probably don't want to use temporary files anyway, thus I'd recommend to create normal files:
File image = new File(storageDirectory, imageFileName + ".jpg");
According implementation of used method new file is created with extra random integer new File(tmpDirFile, prefix + Math.randomIntInternal() + suffix)
public static File createTempFile(String prefix, String suffix, File directory)
throws IOException {
// Force a prefix null check first
if (prefix.length() < 3) {
throw new IllegalArgumentException("prefix must be at least 3 characters");
}
if (suffix == null) {
suffix = ".tmp";
}
File tmpDirFile = directory;
if (tmpDirFile == null) {
String tmpDir = System.getProperty("java.io.tmpdir", ".");
tmpDirFile = new File(tmpDir);
}
File result;
do {
result = new File(tmpDirFile, prefix + Math.randomIntInternal() + suffix);
} while (!result.createNewFile());
return result;
}

How to open a file without knowing its extension but knowing full name?

Intent tostart = new Intent(Intent.ACTION_VIEW);
tostart.setDataAndType(Uri.parse(video_path+".***"), "video/*");
startActivity(tostart);
Let's say I have a file path
/mnt/sdcard/video/my_birthday_moovie001
'my_birthday_moovie001' can be either .mkv, .mpg or .mkv. I've tried to add ".***" to the file path but I still can't open the file.
Well i read the comments you have stored your path in db without extensions there are many extensions that exists so android cant automatically pick the extension you have to create some way to detect extension.
following is a robust way that is best match in your case but not recommended in proper cases where extensions are known
public String chk_path(String filePath)
{
//create array of extensions
String[] ext=new String[]{".mkv",".mpg"}; //You can add more as you require
//Iterate through array and check your path which extension with your path exists
String path=null;
for(int i=0;i<ext.Length;i++)
{
File file = new File(filePath+ext[i]);
if(file.exists())
{
//if it exists then combine the extension
path=filePath+ext[i];
break;
}
}
return path;
}
now to play a song in your code
if(chk_path(video_path)!=null)
{
Intent tostart = new Intent(Intent.ACTION_VIEW);
tostart.setDataAndType(Uri.parse(video_path), "video/*");
startActivity(tostart);
}
else
//tell user that although the path in database but file on this path do not exists
Well as I put on comments
You could compare if the path matches with any filename(it doesn't contains the extension) and then if it does you got it.
You can simply do this :
Get the directory path
File extStore = Environment.getExternalStorageDirectory();
Set the file name my_birthday_moovie001 on my example I put unnamed but change it as your like
String NameOfFile = "unnamed";
Add the videos, I put it Downloads but you can change it
String PathWithFolder = extStore + "/Download/";
Create a method that lists all the files from your path
private List<String> getListFiles(File parentDir) {
ArrayList<String> inFiles = new ArrayList<String>();
File[] files = parentDir.listFiles();
for (File file : files) {
if (file.isDirectory()) {
inFiles.addAll(getListFiles(file));
} else {
String AbsolutePath = file.getAbsolutePath();
//Get the file name ex : unnamed.jpg
String nameofFile = AbsolutePath.substring(AbsolutePath.lastIndexOf("/") + 1, AbsolutePath.length());
//Remove the .jpg --> Output unnamed
String fileNameWithoutExtension = nameofFile.substring(0, nameofFile.lastIndexOf('.'));
//Add each file
inFiles.add(fileNameWithoutExtension);
}
}
return inFiles;
}
You got the names of the files doing this
List<String> files = getListFiles(new File(PathWithFolder));
Simply add a for that looks for a match of your file
for (int i = 0; i<=files.size()-1; i++){
if(PathWithFolder.equals(files.get(i))) {
Toast.makeText(MainActivity.this, "You got it!", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(MainActivity.this, "You don't.", Toast.LENGTH_SHORT).show();
}
}
If you want to get the path as well and do what #Zain Ul Abidin proposed and compare it on getListFiles() method add this :
String fileExtension = nameofFile.substring(nameofFile.lastIndexOf("."));
Hope it helps.
From the other question :
Consider DirectoryScanner from Apache Ant:
DirectoryScanner scanner = new DirectoryScanner();
scanner.setIncludes(new String[]{"**/*.java"});
scanner.setBasedir("C:/Temp");
scanner.setCaseSensitive(false);
scanner.scan();
String[] files = scanner.getIncludedFiles();
You'll need to reference ant.jar (~ 1.3 MB for ant 1.7.1).
And then, run on files array and check
if files[i].include(yourfile)
yourfile= files[i]
You may try in this way , first getting the name of file and extension then finally compare and implement. like this :
Example file name is 04chamelon and extension is .png:
File f = new File("/mnt/storage/sdcard/Pictures/04chameleon");
File yourDir = new File("/mnt/storage/sdcard/Pictures");
nametwo = f.getName();
for (File fa : yourDir.listFiles()) {
if (fa.isFile())
fa.getName();
String path = fa.getName(); // getting name and extension
filextension = path.substring(path.lastIndexOf(".") + 1); // seperating extension
name1 = fa.getName();
int pos = name1.lastIndexOf(".");
if (pos > 0) {
name1 = name1.substring(0, pos);
}
}
if (name1.equals(nametwo)) {
Intent tostart = new Intent(Intent.ACTION_VIEW);
tostart.setDataAndType(Uri.parse(f + "." + filextension), "image/*");
//tostart.setDataAndType(Uri.parse(f + "." + filextension), "video/*");
startActivity(tostart);
}
With the latest ContentResolver, you can easily make this work using the contentResolver.getType(uri) function which detects the filetype.
private fun getIntentForFile(intent: Intent, filePath: String, context: Context): Intent {
val uri = FileProvider.getUriForFile(
context,
context.applicationContext.packageName + ".fileprovider",
File(filePath)
)
intent.putExtra(Intent.EXTRA_STREAM, uri)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.setDataAndType(uri, context.contentResolver.getType(uri))
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return intent
}

How to extract files from .obb file?

in my application I downloaded the expansion file at Android->obb->packagename->main.1.packagename.obb .
Can someone explain to me, even with the sample code how to extract my files from it ?
I tried to use the APK Expansion Zip Library as :
ZipResourceFile expansionFile = APKExpansionSupport.getAPKExpansionZipFile(MainActivity.this, 3, 0);
for (ZipResourceFile.ZipEntryRO entry : expansionFile.getAllEntries())
Log.d("",entry.mFileName);
InputStream input = expansionFile.getInputStream(Environment.getExternalStorageDirectory().toString()
+ "/sdcard/Android/obb/com.example.project/main.3.com.example.project.obb/obb/file.zip/file.apk");
But expansionFile is always null.
The .obb file was created with Jobb, used on the folder obb/file.zip .
Solved with the following code:
final StorageManager storageManager = (StorageManager) getSystemService(STORAGE_SERVICE);
String obbPath = Environment.getExternalStorageDirectory() + "/Android/obb";
final String obbFilePath = obbPath + "/com.example.project/main.3.com.example.project.obb";
OnObbStateChangeListener mount_listener = new OnObbStateChangeListener() {
public void onObbStateChange(String path, int state) {
if (state == OnObbStateChangeListener.MOUNTED) {
if (storageManager.isObbMounted(obbFilePath)) {
Log.d("Main","Mounted successful");
String newPath = storageManager.getMountedObbPath(obbFilePath);
File expPath = new File(newPath+"/file.zip/file.apk");
Log.d("Main","File exist: " + expPath.exists());
}
}
}
};
storageManager.mountObb(obbFilePath, "key", mount_listener);
After mounting the .obb file , I can access my data in the path mnt/obb/myfolder .
I used this for reading a specific file from the obb:
In your AndroidManifest.xml:
<!-- Needed for reading the obb file -->
<provider
android:name=".extension.ZipFileContentProvider"
android:authorities="com.example.extension.ZipFileContentProvider"/>
ZipFileContentProvider:
public class ZipFileContentProvider extends APEZProvider {
#Override
public String getAuthority() {
return "com.example.extension.ZipFileContentProvider";
}
}
Get file URI:
final Uri CONTENT_URI = Uri.parse("content://" + "com.example.extension.ZipFileContentProvider");
Uri uri = Uri.parse(CONTENT_URI + "/drawable/" + name)
To create the obb file i used a gradle script (the res folder is in the same directory):
task createExpansionFile(type: Zip) {
from 'res'
entryCompression = ZipEntryCompression.STORED
archiveName = 'main' + '.' + '1' + '.' + 'com.example' + '.obb'
println archiveName
println relativePath(destinationDir)
println relativePath(archivePath)
}

How to get the real path with ACTION_OPEN_DOCUMENT_TREE Intent?

My app downloads and unzips a file in a specific folder:
output = new FileOutputStream(realpath, true);
output.write(buffer, 0, bytesRead);
ZipFile zipFile = new ZipFile(realpath);
With the new introduced ACTION_OPEN_DOCUMENT_TREE Intent, I would like to offer the user to choose that folder.
When testing the values received in my onActivityResult, I get a Path like /tree/primary:mynewfolder, which is not the physical real path like /sdcard/mynewfolder.
Uri treeUri = data.getData();
String sPath = treeUri.getPath();
Log.v("Path from Tree ", sPath);
My unzip method need the real path:
ZipFile zipFile = new ZipFile(realpath);
How do I get the real path like /sdcard/mynewfolder from the provided URI in Lollipop (API 21 & 22)?
Process of getting real Path from URI is same as before, but with a little addition:
Uri uri = data.getData();
Uri docUri = DocumentsContract.buildDocumentUriUsingTree(uri,
DocumentsContract.getTreeDocumentId(uri));
String path = getPath(this, docUri);
The gist of getPath() method with intermediate methods can be found here: getPath()
Apparently I need reputation to Comment or edit improves Minute V answer. since I guess it's still relevant for people who don't want external libraries or have retrocompatability.
The path you get from just the Uri should be relative to the Environment.getExternalStorageDirectory().getPath(). from what I gather it will have some ":" to split the info on the link.
You just have to split the link and take the last value in the array to get the relative path. Then you just use Environment.getExternalStorageDirectory().getPath()and add a "/" and then add your path.
Here is the code I used:
Uri uri = resultData.getData();
String [] pathsections = resultData.getData().getPath().split(":");
path = Environment.getExternalStorageDirectory().getPath() + "/" + pathsections[pathsections.length-1];
As you can see, there should be no need to do all does if's and Environment.getExternalStorageDirectory().getPath() should get you the path on a physical device too so you won't have to break your head around hard coding the path.
No need checking android version..
public static string GetRealPath(DocumentFile treeUri)
{
if (treeUri == null)
return "";
var path1 = treeUri.Uri.Path;
if (path1.StartsWith("/tree/"))
{
var path2 = path1.Remove(0, "/tree/".Length);
if (path2.StartsWith("primary:"))
{
var primary = path2.Remove(0, "primary:".Length);
if (primary.Contains(':'))
{
var storeName = "/storage/emulated/0/";
var last = path2.Split(':').LastOrDefault();
var realPath = storeName + last;
return realPath;
}
}
else
{
if (path2.Contains(':'))
{
var path3 = path2.Split(':').FirstOrDefault();
var storeName = path3;
var last = path2.Split(':').LastOrDefault();
var realPath = "/" + storeName + "/" + last;
return realPath;
}
}
}
return path1;
}

Categories

Resources