Get current Wallpaper android 13, more detailed problem - wallpaper

The exception happens at:
final Drawable wallpaperDrawable = wallpaperManager.getDrawable();
"Permission android.permission.READ_EXTERNAL_STORAGE denied" which means probably that wallpaperManager use READ_EXTERNAL_STORAGE permission to work, and need to find other way to get it using READ_MEDIA_IMAGES permission
Added the question (even though it is the second) because it includes more code and specifications that might help solve it.
Manifest:
<uses-permission android:name="android.permission.READ_STORAGE_PERMISSION" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Attached Main code, tried to change my method to include android 13, currently I see the permission window, and got stuck after that:
public void save_current_wallpaper_to_internal_storage() {
//get-current-wallpaper
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
//READ_MEDIA_IMAGES for android 13
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_MEDIA_IMAGES}, READ_REQUEST_CONST);
} else {
final WallpaperManager wallpaperManager = WallpaperManager.getInstance(this);
final Drawable wallpaperDrawable = wallpaperManager.getDrawable();
Bitmap bitmap = drawableToBitmap(wallpaperDrawable);
saveToInternalStorage(bitmap);
}
} else {
//READ_EXTERNAL_STORAGE android < 13
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, READ_REQUEST_CONST);
} else {
final WallpaperManager wallpaperManager = WallpaperManager.getInstance(this);
final Drawable wallpaperDrawable = wallpaperManager.getDrawable();
Bitmap bitmap = drawableToBitmap(wallpaperDrawable);
saveToInternalStorage(bitmap);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == READ_REQUEST_CONST) {// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
WallpaperManager wm = WallpaperManager.getInstance(getApplicationContext());
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
final Drawable wallpaperDrawable = wm.getDrawable();
Bitmap bitmap = drawableToBitmap(wallpaperDrawable);
saveToInternalStorage(bitmap);
}
}
else{
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED) {
final Drawable wallpaperDrawable = wm.getDrawable();
Bitmap bitmap = drawableToBitmap(wallpaperDrawable);
saveToInternalStorage(bitmap);
}
}
final Drawable wallpaperDrawable = wm.getDrawable();
Bitmap bitmap = drawableToBitmap(wallpaperDrawable);
saveToInternalStorage(bitmap);
} else {
Log.v("TAG", "denied");
}
}
}
Error:
FATAL EXCEPTION: Thread-5
Process: com.DailyWallpaper, PID: 9186
java.lang.SecurityException: Permission android.permission.READ_EXTERNAL_STORAGE denied
for package com.DailyWallpaper
at android.os.Parcel.createExceptionOrNull(Parcel.java:3011)
at android.os.Parcel.createException(Parcel.java:2995)
at android.os.Parcel.readException(Parcel.java:2978)
at android.os.Parcel.readException(Parcel.java:2920)
at
android.app.IWallpaperManager$Stub$Proxy.getWallpaperWithFeature(IWallpaperManager.java:895)
at android.app.WallpaperManager$Globals.getCurrentWallpaperLocked(WallpaperManager.java:667)
at android.app.WallpaperManager$Globals.peekWallpaperBitmap(WallpaperManager.java:563)
at android.app.WallpaperManager$Globals.peekWallpaperBitmap(WallpaperManager.java:538)
at android.app.WallpaperManager.getDrawable(WallpaperManager.java:791)
at com.Daily_Wallpaper.MainActivity.save_current_wallpaper_to_internal_storage(MainActivity.java:127)
at com.Daily_Wallpaper.MainActivity$$ExternalSyntheticLambda12.run(Unknown Source:2)
at java.lang.Thread.run(Thread.java:1012)
Caused by: android.os.RemoteException: Remote stack trace:
at android.os.storage.StorageManager.checkPermissionAndAppOp(StorageManager.java:1805)
at android.os.storage.StorageManager.checkPermissionAndAppOp(StorageManager.java:1782)
at android.os.storage.StorageManager.checkPermissionAndAppOp(StorageManager.java:1849)
at android.os.storage.StorageManager.checkExternalStoragePermissionAndAppOp(StorageManager.java:1965)
at android.os.storage.StorageManager.checkPermissionReadImages(StorageManager.java:1931)

It's a known issue.
See https://issuetracker.google.com/issues/237124750 and https://issuetracker.google.com/issues/236690156
No acceptabe solution by far.

Related

Saving a file in shared storage Xamarin forms

I need to save a file in the shared storage of android. I came across this link => https://developer.android.com/training/data-storage/shared/documents-files
I am using the dependency service and I am able to successfully save a file to desired location. But I am able to create only a blank file. I need to write some content into that file. Actually I created a thread few hours ago with android tag and got the solution where I had to override the OnActivityResult method and get the intent data. Now I have done it and I am able to get the intent data. But Now I dont know which path should i choose from the intent and how to open the file using the chosen path and how to write content into that chosen file. Any android + xamarin expert should be able to help me..
The android platform code to implement the write service:
Activity _activity;
private static int CREATE_FILE = 6835;
public WriteFileService()
{
_activity = CrossCurrentActivity.Current.Activity;
}
void IWriteService.WriteFile(string Content)
{
Intent intent = new Intent(Intent.ActionCreateDocument);
intent.AddCategory(Intent.CategoryOpenable);
intent.SetType("application/txt");
intent.PutExtra(Intent.ExtraTitle, "Invoice.txt");
_activity.StartActivityForResult(intent, CREATE_FILE);
}
The overriden OnActivityResultMethod:
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
Toast.MakeText(Application.Context, "requestCode is " + requestCode, ToastLength.Short).Show();
if (requestCode == 6835)
{
if (data != null)
{
Toast.MakeText(Application.Context,
data.GetType().ToString(),
ToastLength.Short).Show();
}
}
base.OnActivityResult(requestCode, resultCode, data);
}
This is the screen of the Intent Data from OnActivityResult
Use this in your Android project to save a stream to file:
public async Task SaveAndView(string fileName, String contentType, MemoryStream stream)
{
try
{
string root = null;
//Get the root path in android device.
if (Android.OS.Environment.IsExternalStorageEmulated)
{
root = Android.OS.Environment.ExternalStorageDirectory.ToString();
}
else
root = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
//Create directory and file
Java.IO.File myDir = new Java.IO.File(root + "/meusarquivos");
myDir.Mkdir();
Java.IO.File file = new Java.IO.File(myDir, fileName);
//Remove if the file exists
if (file.Exists()) file.Delete();
//Write the stream into the file
FileOutputStream outs = new FileOutputStream(file);
outs.Write(stream.ToArray());
outs.Flush();
outs.Close();
}
catch (Exception ex)
{
PostLog.AppCenterLogExcecao(ex, new Dictionary<string, string> { { "origem", "OrderViewModel - 159" } });
}
}
And in your shared code:
await DependencyService.Get<ISave>().SaveAndView(OrderId.ToString() + ".pdf", "application/pdf", stream);
Be sure to ask for the permissions before using the code.
To save the file. ive used this code
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
if (requestCode == 6835)
{
if (data != null)
{
Android.Net.Uri uri = Android.Net.Uri.Parse(data.DataString);
var stream = ContentResolver.OpenOutputStream(uri, "w");
byte[] byteArray = Encoding.UTF8.GetBytes("Hi Thameem. I am your file.");
MemoryStream stream1 = new MemoryStream(byteArray);
stream1.CopyTo(stream);
stream.Flush();
stream.Close();
Toast.MakeText(Application.Context,
"The file has been exported successfully",
ToastLength.Short).Show();
}
}
base.OnActivityResult(requestCode, resultCode, data);
}

How to Solve Environment.getExternalStorageDirectory() in android Q(10) [duplicate]

Working on android Java, recently updated SDK to API level 29 now there is a warning shown which states that
Environment.getExternalStorageDirectory() is deprecated in API level 29
My code is
private void saveImage() {
if (requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
final String folderPath = Environment.getExternalStorageDirectory() + "/PhotoEditors";
File folder = new File(folderPath);
if (!folder.exists()) {
File wallpaperDirectory = new File(folderPath);
wallpaperDirectory.mkdirs();
}
showLoading("Saving...");
final String filepath=folderPath
+ File.separator + ""
+ System.currentTimeMillis() + ".png";
File file = new File(filepath);
try {
file.createNewFile();
SaveSettings saveSettings = new SaveSettings.Builder()
.setClearViewsEnabled(true)
.setTransparencyEnabled(true)
.build();
if(isStoragePermissionGranted() ) {
mPhotoEditor.saveAsFile(file.getAbsolutePath(), saveSettings, new PhotoEditor.OnSaveListener() {
#Override
public void onSuccess(#NonNull String imagePath) {
hideLoading();
showSnackbar("Image Saved Successfully");
mPhotoEditorView.getSource().setImageURI(Uri.fromFile(new File(imagePath)));
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,Uri.fromFile(new File(filepath))));
Intent intent = new Intent(EditImageActivity.this, StartActivity.class);
startActivity(intent);
finish();
}
#Override
public void onFailure(#NonNull Exception exception) {
hideLoading();
showSnackbar("Failed to save Image");
}
});
}
What will be the alternative for this?
Use getExternalFilesDir(), getExternalCacheDir(), or getExternalMediaDirs() (methods on Context) instead of Environment.getExternalStorageDirectory().
Or, modify mPhotoEditor to be able to work with a Uri, then:
Use ACTION_CREATE_DOCUMENT to get a Uri to a location of the user's choosing, or
Use MediaStore, ContentResolver, and insert() to get a Uri for a particular type of media (e.g., an image) — see this sample app that demonstrates doing this for downloading MP4 videos from a Web site
Also, note that your Uri.fromFile with ACTION_MEDIA_SCANNER_SCAN_FILE should be crashing on Android 7.0+ with a FileUriExposedException. On Android Q, only the MediaStore/insert() option will get your content indexed by the MediaStore quickly.
Note that you can opt out of these "scoped storage" changes on Android 10 and 11, if your targetSdkVersion is below 30, using android:requestLegacyExternalStorage="true" in the <application> element of the manifest. This is not a long-term solution, as your targetSdkVersion will need to be 30 or higher sometime in 2021 if you are distributing your app through the Play Store (and perhaps elsewhere).
Get the destPath with the new API call:
String destPath = mContext.getExternalFilesDir(null).getAbsolutePath();
For Android Q, you can add android:requestLegacyExternalStorage="true" to your element in the manifest. This opts you into the legacy storage model, and your existing external storage code will work.
<manifest ... >
<!-- This attribute is "false" by default on apps targeting
Android 10 or higher. -->
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
Technically, you only need this once you update your targetSdkVersion to 29. Apps with lower targetSdkVersion values default to opting into legacy storage and would need android:requestLegacyExternalStorage="false" to opt out.
Please use getExternalFilesDir(), getExternalCacheDir() instead of Environment.getExternalStorageDirectory() when you creating file in Android 10.
See below line:
val file = File(this.externalCacheDir!!.absolutePath, "/your_file_name")
This is a small example how to get URI for a file if you want to take photo using default camera and store it in a DCIM folder (DCIM/app_name/filename.jpg):
Open camera (remember about CAMERA permission):
private var photoURI: Uri? = null
private fun openCamera() {
Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
photoURI = getPhotoFileUri()
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
takePictureIntent.resolveActivity(requireActivity().packageManager)?.also {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
}
}
}
And get URI:
private fun getPhotoFileUri(): Uri {
val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
val fileName = "IMG_${timeStamp}.jpg"
var uri: Uri? = null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val resolver = requireContext().contentResolver
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/app_name/")
}
uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
}
return uri ?: getUriForPreQ(fileName)
}
private fun getUriForPreQ(fileName: String): Uri {
val dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
val photoFile = File(dir, "/app_name/$fileName")
if (photoFile.parentFile?.exists() == false) photoFile.parentFile?.mkdir()
return FileProvider.getUriForFile(
requireContext(),
"ru.app_name.fileprovider",
photoFile
)
}
Don't forget about WRITE_EXTERNAL_STORAGE permission for pre Q and add a FileProvider to AndroidManifest.xml.
And get a result:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
REQUEST_IMAGE_CAPTURE -> {
photoURI?.let {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val thumbnail: Bitmap =
requireContext().contentResolver.loadThumbnail(
it, Size(640, 480), null
)
} else {
// pre Q actions
}
}
}
}
}
This worked for me
Add this line in application tag of manifest file
android:requestLegacyExternalStorage="true"
Example
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:networkSecurityConfig="#xml/network_security_config"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
android:theme="#style/AppTheme">
</application>
Target SDK is 29
defaultConfig {
minSdkVersion 16
targetSdkVersion 29
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
To get internal storage directory without hard coding,
Permissions (For all Android versions). Don't forget to get permissions from the user.
Request all files access
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />
Legacy permission for Android 10 (add this to AndroidManifest.xml > application tag).
android:requestLegacyExternalStorage="true"
Get internal storage directory path:
public static String getInternalStorageDirectoryPath(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
return storageManager.getPrimaryStorageVolume().getDirectory().getAbsolutePath();
} else {
return Environment.getExternalStorageDirectory().getAbsolutePath();
}
}
This worked
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
contentResolver?.also { resolver ->
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, "Image_"+".jpg")
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg")
put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + File.separator+ "TestFolder")
}
val imageUri: Uri? = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
fos = imageUri?.let { resolver.openOutputStream(it) }
bitmap.compress(Bitmap.CompressFormat.JPEG,100,fos)
Objects.requireNonNull(fos)
}
}
You could make use of StorageManager & StorageVolume classes
StorageVolume.getPrimaryStorageVolume(): This volume is the same storage device returned by Environment#getExternalStorageDirectory() and Context#getExternalFilesDir(String).
public String myGetExternalStorageDir() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
return getPrimaryStorageVolumeForAndroid11AndAbove();
else
return getPrimaryStorageVolumeBeforeAndroid11();
}
#TargetApi(Build.VERSION_CODES.R)
private String getPrimaryStorageVolumeForAndroid11AndAbove() {
StorageManager myStorageManager = (StorageManager) ctx.getSystemService(Context.STORAGE_SERVICE);
StorageVolume mySV = myStorageManager.getPrimaryStorageVolume();
return mySV.getDirectory().getPath();
}
private String getPrimaryStorageVolumeBeforeAndroid11() {
String volumeRootPath = "";
StorageManager myStorageManager = (StorageManager) ctx.getSystemService(Context.STORAGE_SERVICE);
StorageVolume mySV = myStorageManager.getPrimaryStorageVolume();
Class<?> storageVolumeClazz = null;
try {
storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");
Method getPath = storageVolumeClazz.getMethod("getPath");
volumeRootPath = (String) getPath.invoke(mySV);
} catch (Exception e) {
e.printStackTrace();
}
return volumeRootPath;
}
private fun saveImage(bitmap: Bitmap, name: String) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val resolver = contentResolver
val contentValues = ContentValues()
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, name)
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/png")
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/" + "YOUR_FOLDER")
val imageUri =
resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
val fos = resolver.openOutputStream(imageUri!!)
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos)
fos!!.flush()
fos.close()
toast("Saved to gallery")
} else {
if (isPermissionGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
val imagesDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM
).toString() + File.separator + "YOUR_FOLDER"
if (!file.exists()) {
file.mkdir()
}
val image = File(imagesDir, "$name.png")
val fos = FileOutputStream(image)
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos)
fos.flush()
fos.close()
} else {
// ask for permission
}
}
}
Recently I also face similar kind of issues, Due to my code was large and i don't want to add new functionality in existing code so i just simply change path..
Environment.getExternalStorageDirectory() Replace with
context.getExternalFilesDir(null).getAbsolutePath()
Code
private void saveImage() {
if (requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
final String folderPath = this.getExternalFilesDir(null).getAbsolutePath() + "/PhotoEditors";
File folder = new File(folderPath);
if (!folder.exists()) {
File wallpaperDirectory = new File(folderPath);
wallpaperDirectory.mkdirs();
}
showLoading("Saving...");
final String filepath=folderPath
+ File.separator + ""
+ System.currentTimeMillis() + ".png";
File file = new File(filepath);
try {
file.createNewFile();
SaveSettings saveSettings = new SaveSettings.Builder()
.setClearViewsEnabled(true)
.setTransparencyEnabled(true)
.build();
if(isStoragePermissionGranted() ) {
mPhotoEditor.saveAsFile(file.getAbsolutePath(), saveSettings, new PhotoEditor.OnSaveListener() {
#Override
public void onSuccess(#NonNull String imagePath) {
hideLoading();
showSnackbar("Image Saved Successfully");
mPhotoEditorView.getSource().setImageURI(Uri.fromFile(new File(imagePath)));
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,Uri.fromFile(new File(filepath))));
Intent intent = new Intent(EditImageActivity.this, StartActivity.class);
startActivity(intent);
finish();
}
#Override
public void onFailure(#NonNull Exception exception) {
hideLoading();
showSnackbar("Failed to save Image");
}
});
}
var tempDir: File = inContext.getExternalFilesDir("/")!!
tempDir = File(tempDir.getAbsolutePath().toString() + "/.IncidentImages/")
tempDir.mkdir()
If you work with XAMARIN and are confused by all this different answers (like me) just follow this example:
var picture = new Java.IO.File(Environment.DirectoryPictures, "fileName");
Took me some time to figure this out.

Unable to save files in API 23 anymore

We have an application which saves images in a directory in an SD card. The directory is created if it does not already exist.
Here is the code that has done the job before the arrival of API 23:
OutputStream output;
File filepath = Environment.getExternalStorageDirectory();
File dir = new File(filepath.getAbsolutePath()
+ "/fingerprint/");
dir.mkdirs();
Bitmap bitmap = m_bitmap;
File file = new File(dir, userId.getText().toString() + ".jpg");
try {
output = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, output);
output.flush();
output.close();
} catch (Exception e) {
e.printStackTrace();
}
For some reasons, the directory is no longer created and files are no longer saved in Android 6.0. We introduced these methods to update our code with API changes in Marshmallow.
private void requestPermission(final Context context){
if(ActivityCompat.shouldShowRequestPermissionRationale((Activity)context, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
new AlertDialog.Builder(context)
.setMessage(context.getResources().getString(R.string.permission_storage))
.setPositiveButton(R.string.allow, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions((Activity) context,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_WRITE_EXTERNAL_STORAGE);
}
}).show();
} else {
ActivityCompat.requestPermissions((Activity)context,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_WRITE_EXTERNAL_STORAGE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode,String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_WRITE_EXTERNAL_STORAGE: {
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(CaptureFingerprintActivity.this,
getResources().getString(R.string.permission_storage_success),
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(CaptureFingerprintActivity.this,
getResources().getString(R.string.permission_storage_failure),
Toast.LENGTH_SHORT).show();
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
return;
}
}
}
And the code that creates the directory and saves files is also updated.
OutputStream output;
File storageDir = null;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
if (PackageManager.PERMISSION_GRANTED == ActivityCompat.checkSelfPermission(CaptureFingerprintActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
storageDir = new File(Environment.Environment.getExternalStorageDirectory()
, "fingerprint");
if (!storageDir.exists()) {
storageDir.mkdir();
} else {
requestPermission(CaptureFingerprintActivity.this);
}
}
Bitmap bitmap = m_bitmap;
File file = new File(storageDir, userId.getText().toString() + ".jpg");
try {
output = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, output);
output.flush();
output.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
This still doesn't seem to be creating directories.

No 'output' extra specified Exception

I use the Google Photo app to pick gallery photo and then when I crop the picture and save, it catches an exception, Here is my code :
goto_picture.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
intent = new Intent(Intent.ACTION_PICK, null);
intent.setDataAndType(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
IMAGE_UNSPECIFIED);
startActivityForResult(intent, PHOTO_ZOOM);
dialog.cancel();
}
});
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (requestCode == PHOTO_GRAPH) {
startPhotoZoom(Uri.fromFile(file));
String imagePath = SystemUtils.getSDPath() + "/temp.jpg";
File picture = new File(imagePath);
if (picture.exists()) {
pictureBitmap = BitmapFactory.decodeFile(imagePath);
ImageUtils.SaveCacheBitmap(pictureBitmap);
rvEditAvatar.setImageBitmap(pictureBitmap);
}
}
if (requestCode == PHOTO_ZOOM) {
startPhotoZoom(data.getData());
}
if (requestCode == PHOTO_RESULT) {
Bundle extras = data.getExtras();
if (extras != null) {
pictureBitmap = extras.getParcelable("data");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
pictureBitmap.compress(Bitmap.CompressFormat.JPEG, 100,
stream);
ImageUtils.SaveCacheBitmap(pictureBitmap);
rvEditAvatar.setImageBitmap(pictureBitmap);
}
}
}
}
public void startPhotoZoom(Uri uri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 180);
intent.putExtra("outputY", 180);
intent.putExtra("return-data", true);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
startActivityForResult(intent, PHOTO_RESULT);
}
Logcat:
Process: com.google.android.apps.photos, PID: 7031
java.lang.RuntimeException: Unable to resume activity
{com.google.android.apps.photos/com.google.android.apps.photos.photoeditor.intents.EditActivity}:
java.lang.UnsupportedOperationException: No 'output' extra specified
and can not save to specified inputUri:
content://com.google.android.apps.photos.contentprovider/0/1/content%3A%2F%2Fmedia%2Fexternal%2Fimages%2Fmedia%2F72072/ACTUAL
As the exception said, you have to specify output extra like the following code.
intent.putExtra(MediaStore.EXTRA_OUTPUT, someOutPutPath);
And return data is not secure in case of big image cropped which may cause crash. I think that's why it forces you to use an output extra but not the data directly. So you may set the return-data to false as well:
intent.putExtra("return-data", false);
I meet this problem today, and solved by double check the data pass-back.I test following code on both Android L and Android 4. On Android L the fileUri is not empty while pre Android L we got fileUri null(in this case, I got the bitmap by simply getData).
private Bitmap decodeBitmapFromCrop(Intent data) {
Bundle extras = data.getExtras();
Bitmap photo = null;
if (extras != null) {
photo = extras.getParcelable("data");
} else {
Uri fileUri = data.getData();
if (fileUri != null) {
try {
photo = MediaStore.Images.Media.getBitmap(getContentResolver(), fileUri);
} catch (IOException e) {
XXLog.d(TAG, "Media.getBitmap", e);
}
}
}
return photo;
}

android - How to set MP3 as Ringtone

File newSoundFile = new File("pathFile");
if (DebugUtil.DEBUG) {
DebugUtil.logError(new Exception(), newSoundFile.getAbsolutePath());
}
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, newSoundFile.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, "Title");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/*");
values.put(MediaStore.MediaColumns.SIZE, newSoundFile.length());
values.put(MediaStore.Audio.Media.ARTIST, R.string.app_name);
values.put(MediaStore.Audio.Media.DURATION, 230);
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, false);
values.put(MediaStore.Audio.Media.IS_ALARM, false);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
Uri uri = MediaStore.Audio.Media.getContentUriForPath(newSoundFile.getAbsolutePath());
context.getContentResolver().delete(uri, MediaStore.MediaColumns.DATA + "=\"" + newSoundFile.getAbsolutePath() + "\"", null);
Uri newUri = context.getContentResolver().insert(uri, values);
try {
RingtoneManager.setActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE, newUri);
KitKatToast.makeText(context, R.string.msg_setAsRingTuneSuccess, KitKatToast.LENGTH_LONG).show();
}
catch (Exception e) {
if (DebugUtil.DEBUG) {
DebugUtil.logError(new Exception(), e.toString());
}
}
I saw many posts but anyone showed what i should actually have to do. So i decided to create this complete answer. The only think you actually need is a button.
Lets start.
Here is my MainActivity.java which i used
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
b2 = (Button) findViewById(R.id.button2);
b2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent1 = new Intent();
intent1.setAction(Intent.ACTION_GET_CONTENT);
intent1.setType("audio/*");
startActivityForResult(Intent.createChooser(intent1, "Choose Sound File"), 6);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && requestCode == 6) {
Uri i = data.getData(); //getDATA
String s = = i.getPath(); //getPath
File k = new File(s); //set File from path
if (s != null) { //(file.exists
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, k.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, "ring");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.MediaColumns.SIZE, k.length());
values.put(MediaStore.Audio.Media.ARTIST, R.string.app_name);
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, true);
values.put(MediaStore.Audio.Media.IS_ALARM, true);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
Uri uri = MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath());
getContentResolver().delete(uri, MediaStore.MediaColumns.DATA + "=\"" + k.getAbsolutePath() + "\"", null);
Uri newUri = getContentResolver().insert(uri, values);
try {
RingtoneManager.setActualDefaultRingtoneUri(MainActivity.this, RingtoneManager.TYPE_RINGTONE, newUri);
} catch (Throwable t) {
}
}
}
}
}
Lastly its really important to add those permisions in your AndroidManifest.xml for example if you dont add the permision to write external storage your app will crash like mine.. xD
What you need:
<uses-permission android:name="android.permission.WRITE_SETTINGS" ></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" ></uses-permission>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" ></uses-permission>
You can try my app on Google Play : BackAtel Audio Manager
Hope that helps.... my problem is now solved!! i hope that i solved your problem too :))

Resources