How to clear Mediastore before setting ringtone - java

When I set a ringtone from my app works once, but when running the code again, it tries to create a duplicate entry in the media store, which creates problems. Without creating seperate unique file names for every sound file, I want to fix this problem.
I found this solution posted in an answer here: setting audio file as Ringtone
and am trying to use that to fix mine.
When I try it in my code below, I get two errors. One is an SQLiteException and the other is a RuntimeException which is caused by the squlite error, which is after the Java code.
String TAG = "CFFS";
File dir = new File(Environment.getExternalStorageDirectory()+ "/ringtones"); // Set base DIR where new ringtone will live
dir.mkdirs(); // create if directors don't exist
File outputFile = new File(dir, "College Fight Song.mp3"); // Define out new output file
Uri inURI = null;
try {
inURI = Uri.parse(getIntent().getStringExtra("com.carboni.fightsongs.FILE_RES_ID"));
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Could not get URI " + e);
}
// If we didn't parse a good URI then don't execute the code below
if (inURI != null) {
InputStream in = null;
// Get the input stream
try { in = new BufferedInputStream(this.getContentResolver().openInputStream(inURI)); }
catch (Exception e) { Log.e(TAG, "Exception getting input stream " + e); }
// Get the output stream
OutputStream out = null;
try { out = new FileOutputStream(outputFile); }
catch (Exception e) { Log.e(TAG, "Exception getting output stream " + e); }
// Again, if we don't have 2 good handles then don't try to read/write them
if ((in != null) && (out != null)) {
byte[] buf = new byte[1024]; // Define our buffer size
int bytesRead = 0;
while (bytesRead >= 0) {
try {
bytesRead = in.read(buf, 0, buf.length); // Read max of 1024 bytes
if (bytesRead > 0)
out.write(buf); // Write buffer to new file if we got a good read
} catch (Exception e) {
Log.e(TAG,"Exception reading " + e);
e.printStackTrace();
}
}
}
// Close out handles and proceed
try {
in.close();
out.close();
}
catch (Exception e) { Log.e(TAG, "Exception closing streams " + e); }
ContentValues v = new ContentValues();
v.put(MediaStore.MediaColumns.DATA, outputFile.getAbsolutePath());
v.put(MediaStore.MediaColumns.TITLE, "College Football Fight Song");
v.put(MediaStore.MediaColumns.SIZE, outputFile.length());
v.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
v.put(MediaStore.Audio.Media.IS_RINGTONE, true);
Uri pURI = MediaStore.Audio.Media.getContentUriForPath(outputFile.getAbsolutePath());
// remove entry every time so we don't get duplicate entries and have a problem setting a 2nd time
getContentResolver().delete(pURI, MediaStore.MediaColumns.DATA + "\"" + outputFile.getAbsolutePath() + "\"", null);
Uri nURI = this.getContentResolver().insert(pURI, v);
Log.i(TAG, "Setting ringtone URI to " + nURI);
// Set ringtone
RingtoneManager.setActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE, nURI);
Toast.makeText(this, "Ringtone set", Toast.LENGTH_LONG).show();
ERROR:
09-03 14:16:08.343: ERROR/DatabaseUtils(11968): android.database.sqlite.SQLiteException: near ""/mnt/sdcard/ringtones/College Fight Song.mp3"": syntax error: , while compiling: DELETE FROM audio_meta WHERE _data"/mnt/sdcard/ringtones/College Fight Song.mp3"

It looks like the error is this line:
getContentResolver().delete(pURI, MediaStore.MediaColumns.DATA + "\"" + outputFile.getAbsolutePath() + "=\"", null);

Related

App Intent Problem | Your app contains an Intent Redirection vulnerability

I got this message after updating app in play console. I am sharing code of a method where the error is, as suggested by Google. I never updated this part of the code and it never showed any problem before. I am not sure why it is showing me an error. Do I need to update the way of saving a file? I hope to find a solution here.
public void saveDocument(ScannedDocument scannedDocument) {
Mat doc = (scannedDocument.processed != null) ? scannedDocument.processed : scannedDocument.original;
Intent intent = getIntent();
String fileName;
boolean isIntent = false;
Uri fileUri = null;
if (intent.getAction().equals("android.media.action.IMAGE_CAPTURE")) {
fileUri = ((Uri) intent.getParcelableExtra(MediaStore.EXTRA_OUTPUT));
Log.d(TAG, "intent uri: " + fileUri.toString());
try {
fileName = File.createTempFile("onsFile", ".jpg", this.getCacheDir()).getPath();
} catch (IOException e) {
e.printStackTrace();
return;
}
isIntent = true;
} else {
String folderName = mSharedPref.getString("storage_folder", FOLDER_NAME);
File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString()
+ "/" + folderName);
if (!folder.exists()) {
folder.mkdirs();
Log.d(TAG, "wrote: created folder " + folder.getPath());
}
fileName = folder.getAbsolutePath()
+ "/DOC-"
+ new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date())
+ ".jpg";
}
Mat endDoc = new Mat(Double.valueOf(doc.size().width).intValue(),
Double.valueOf(doc.size().height).intValue(), CvType.CV_8UC4);
Core.flip(doc.t(), endDoc, 1);
Imgcodecs.imwrite(fileName, endDoc);
endDoc.release();
try {
ExifInterface exif = new ExifInterface(fileName);
exif.setAttribute("UserComment", "Generated");
String nowFormatted = mDateFormat.format(new Date().getTime());
exif.setAttribute(ExifInterface.TAG_DATETIME, nowFormatted);
exif.setAttribute(ExifInterface.TAG_DATETIME_DIGITIZED, nowFormatted);
// exif.setAttribute("Software", "OpenNoteScanner " + BuildConfig.VERSION_NAME + "");
exif.saveAttributes();
} catch (IOException e) {
e.printStackTrace();
}
if (isIntent) {
InputStream inputStream = null;
OutputStream realOutputStream = null;
try {
inputStream = new FileInputStream(fileName);
realOutputStream = this.getContentResolver().openOutputStream(fileUri);
// Transfer bytes from in to out
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer)) > 0) {
realOutputStream.write(buffer, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
return;
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
try {
inputStream.close();
realOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
animateDocument(fileName, scannedDocument);
Log.d(TAG, "wrote: " + fileName);
if (isIntent) {
new File(fileName).delete();
setResult(RESULT_OK, intent);
finish();
} else {
addImageToGallery(fileName, this);
}
refreshCamera();
}
Google has a page on Mitigating Intent Redirection vulnerabilities that you should read carefully.
The short version is that the vulnerability could potentially1 be exploited by a malicious app to allow it to access private app components or files.
The document explains three possible ways to mitigate this vulnerability. Unfortunately, there is not enough context to be sure which of the three is most appropriate for your app. However, the first one is straightforward:
"If the affected app component does not need to receive Intents from other apps then you can make that app component private by setting `android:exported="false" in your Manifest."
I never updated this part of the code and it never showed any problem before.
That could mean that this is a relatively new kind of Android vulnerability, or that Google's methodology for detecting it has become more rigorous since last time you published your app.
Do I need to update the way of saving a file?
Possibly yes. Or possibly one of the mitigations will be sufficient.
I hope to find a solution here.
There are some possible solutions in the Google document I linked to.
1 - It is moot if it is actually possible to exploit the vulnerability in your app. The point is that Google Play Store's scanning / analysis / testing methodology has found what they believe to be a problem. Their goal is to protect Play Store users.

Get percentage of extraction with XZ Java for android

I am using the XZ Java library to extract a .xz file on Android of size around 16MB. I am running the extraction/decompression code as an AsyncTask and so, I would like to see the percentage of extraction via the onProgressUpdate(Integer ... values) method.
My decompression code looks something like this.
byte[] buf = new byte[8192];
String name = null;
try {
name = "my_archive.xz";
InputStream in = getResources().openRawResource(R.raw.my_archive);//new FileInputStream(name); //
FileOutputStream out = openFileOutput("my_archive.sqlite", Context.MODE_PRIVATE);
label = (TextView)findViewById(R.id.textLabel);
try {
in = new XZInputStream(in);
label.setText("Writing db file.");
int size;
while ((size = in.read(buf)) != -1) {
out.write(buf,0,size);
progress++;
publishProgress(progress);
}
}
catch (Exception e)
{
System.err.println("Input Stream error: "+e.getMessage());
}
finally {
// Close FileInputStream (directly or indirectly
// via LZMAInputStream, it doesn't matter).
in.close();
}
} catch (FileNotFoundException e) {
System.err.println("LZMADecDemo: Cannot open " + name + ": "
+ e.getMessage());
System.exit(1);
} catch (EOFException e) {
System.err.println("LZMADecDemo: Unexpected end of input on "
+ name);
System.exit(1);
} catch (IOException e) {
System.err.println("LZMADecDemo: Error decompressing from "
+ name + ": " + e.getMessage());
System.exit(1);
}
The progress variable should actually hold the percentage value. If anyone has worked with this library, and if you figured out an easy way to calculate the percentage of progress please help me out here.
Thanks in advance for the help.
I tried to get the size of the archive file using the available() method on the inputstream like below.
InputStream in = getResources().openRawResource(R.raw.my_archive);
int fileSize = in.available();
And during extraction process, I calculated progress like below:
int size;
int counter=0;
while ((size = in.read(buf)) != -1) {
out.write(buf,0,size);
counter++;
progress = (int) (counter*100*1024/(double)fileSize);
publishProgress(progress);
}
However, this doesn't result in the right progress for some reason. The progress goes upto 108% before its finished. I know I'm doing something wrong here, so please improve this answer with the right calculation.
Thanks

Internal storage

I'm currently trying to store json data I get on the Internet in the internal storage of the phone. In order to do so, I have get the data from an API as a string (no issue in this part, nor during the parsing afterwards). Then comes the part where I try to store it in a file... And the problems that come along!
The ultimate goal is to update data when an Internet connection is available, and use the data previously stored when no connection can be found.
Here is my code (data is in the String jsonString):
// IN CASE OF INTERNET CONNECTION (ie "jsonString != null")
if (jsonString != null) {
try {
FileOutputStream fos = new FileOutputStream(json_InternalFile);
fos.write(jsonString.getBytes());
fos.close();
} catch (FileNotFoundException e) {
Log.e("Response: ", "> " + "File not found");
e.printStackTrace();
} catch (IOException e) {
Log.e("Response: ", "> " + "IO Exception");
e.printStackTrace();
}
}
// IF NO CONNECTION AVAILABLE (ie "jsonString == null)
if (jsonString == null) {
try {
FileInputStream fis = new FileInputStream(json_InternalFile);
DataInputStream dis = new DataInputStream(fis);
BufferedReader br = new BufferedReader(new InputStreamReader(dis));
String strLine;
while ((strLine = br.readLine()) != null) {
jsonString = jsonString + strLine;
}
dis.close();
} catch (FileNotFoundException e) {
Log.e("Response: ", "> " + "File not found");
e.printStackTrace();
} catch (IOException e) {
Log.e("Response: ", "> " + "File not found");
e.printStackTrace();
}
}
None of the parts works individually. When I run the app, I got this message: "Unfortunately, the app "APP_NAME" stopped running" (whichever part I comment)
I also tried to replace the line:
FileOutputStream fos = new FileOutputStream(json_InternalFile);
with:
FileOutputStream fos = openFileOutput(jsonStorage_FileName, 0);
... Without success ^^'
I used - and abused ;) - the following code I found:
http://www.mysamplecode.com/2012/06/android-internal-external-storage.html
Thank you in advance, I really can't see the problem here (and it's turning me slightly mad ><)

How to get file.length of file on Internal storage? .length() doesn`t seem to work

trying to get length of file which from local storage. File exists 100% (because I even tried to create it straight before getting the length (and checked it exists). Code is as simple as:
try {
InputStream is = new FileInputStream("errorlog2.txt");
// Get the size of the file
long length = file.length();
// Close the input stream and return length
is.close();
return length;
}
catch (IOException e) {
Log.w(BaseHelper.TAG_MAIN_ACTIVITY, "bad stuff: ", e);
return 0;
in 100% cases it throws an exception. What might be the problem? What`s correct way to get length of local storage files?
thanks a lot!
UPDATE (full code) - file exists and readable, but no length :(
//creating file
String someFileName = "errlogtest.log";
try {
FileOutputStream fOut = openFileOutput(someFileName, Context.MODE_APPEND);
OutputStreamWriter osw = new OutputStreamWriter(fOut);
osw.write("dsgaadfg0df9g0sdf90sg9058349 sdf");
osw.flush();
osw.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
//reading file
try {
FileInputStream fileToOpen = openFileInput(someFileName);
byte[] readerByte = new byte[fileToOpen.available()];
while (fileToOpen.read(readerByte) != -1) {
}
String fileContents = new String(readerByte);
fileContents.toString();
// next line works fine
Toast.makeText(getApplicationContext(), "FILE CONTENTS: " + fileContents, Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
Log.w("Reading file", "Unable to open file");
} catch (IOException e) {
Log.w("Reading file", "Error reading file");
}
// trying to get length
// simply not working:
File file = new File(someFileName);
long length2 = file.length();
Toast.makeText(getApplicationContext(), "FILE LENGTH:" + length2, Toast.LENGTH_LONG).show();
// shows zero and filenotfoundexception: /errlogtest.log
try {
RandomAccessFile raffile = new RandomAccessFile(new File(someFileName), "r");
long length = raffile.length();
Toast.makeText(getApplicationContext(), "FILE LENGTH:" + length, Toast.LENGTH_LONG).show();
catch (IOException e) {
Log.w("Reading file", "Error reading file", e);
}
help please
Depending on where you are creating the file then you'll need to provide a full path and not just a file name.
For example, if the file is being created using Context.openFileOutput(...) then you would use something like...
long length = new File(getFilesDir().getAbsolutePath() + "/errorlog2.txt").length();
Without opening the file you can get its length:
Method 1:
File file = new File("someFile.txt");
long length = file.length();
Method 2:
RandomAccessFile raf = new RandomeAccessFile(new File("someFile.txt"), "r");
long length = raf.length();

How to deal with corrupted files that were created but IOException occured?

Could you please suggest how to deal with these situations ? I understand that in the second example, it is very rare that it would happen on unix, is it ? If access rights are alright. Also the file wouldn't be even created. I don't understand why the IOException is there, either it is created or not, why do we have to bother with IOException ?
But in the first example, there will be a corrupted zombie file. Now if you tell the user to upload it again, the same thing may happen. If you can't do that, and the inputstream has no marker. You loose your data ? I really don't like how this is done in Java, I hope the new IO in Java 7 is better
Is it usual to delete it
public void inputStreamToFile(InputStream in, File file) throws SystemException {
OutputStream out;
try {
out = new FileOutputStream(file);
} catch (FileNotFoundException e) {
throw new SystemException("Temporary file created : " + file.getAbsolutePath() + " but not found to be populated", e);
}
boolean fileCorrupted = false;
int read = 0;
byte[] bytes = new byte[1024];
try {
while ((read = in.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
} catch (IOException e) {
fileCorrupted = true;
logger.fatal("IO went wrong for file : " + file.getAbsolutePath(), e);
} finally {
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
if(fileCorrupted) {
???
}
}
}
public File createTempFile(String fileId, String ext, String root) throws SystemException {
String fileName = fileId + "." + ext;
File dir = new File(root);
if (!dir.exists()) {
if (!dir.mkdirs())
throw new SystemException("Directory " + dir.getAbsolutePath() + " already exists most probably");
}
File file = new File(dir, fileName);
boolean fileCreated = false;
boolean fileCorrupted = false;
try {
fileCreated = file.createNewFile();
} catch (IOException e) {
fileCorrupted = true;
logger.error("Temp file " + file.getAbsolutePath() + " creation fail", e);
} finally {
if (fileCreated)
return file;
else if (!fileCreated && !fileCorrupted)
throw new SystemException("File " + file.getAbsolutePath() + " already exists most probably");
else if (!fileCreated && fileCorrupted) {
}
}
}
I really don't like how this is done in Java, I hope the new IO in Java 7 is better
I'm not sure how Java is different than any other programming language/environment in the way you are using it:
a client sends some data to your over the wire
as you read it, you write it to a local file
Regardless of the language/tools/environment, it's possible for the connection to be interrupted or lost, for the client to go away, for the disk to die, or for any other error to occur. I/O errors can occur in any and all environments.
What you can do in this situation is highly dependent on the situation and the error that occured. For example, is the data structured in some way where you could ask the user to resume uploading from record 1000, for example? However, there is no single solution that fits all here.

Categories

Resources