I try to read and change an textfile on the external storage SD card. To make the example more easy I already inserted the content URI I get from the File Chooser.
I run the app on an Nexus 5X with Android 7 (SDK 24). The minSdkVersion is set to 19 and the targetSdkVersion is 23.
package de.cowabuja.androiduriaccess;
import android.content.Intent;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String uriString = "content://com.android.externalstorage.documents/document/primary%3ADCIM%2FAny%2Dir%2FtheFile.txt";
Uri uri = Uri.parse(uriString);
getApplicationContext().grantUriPermission(getPackageName(), uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
Here the Log:
...
E/AndroidRuntime: FATAL EXCEPTION: main
Process: de.cowabuja.androiduriaccess, PID: 2972
java.lang.RuntimeException: Unable to start activity ComponentInfo{de.cowabuja.androiduriaccess/de.cowabuja.androiduriaccess.MainActivity}: java.lang.SecurityException: Uid 10132 does not have permission to uri 0 # content://com.android.externalstorage.documents/document/primary%3ADCIM%2FAny%2FDir%2FtheFile.txt
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Caused by: java.lang.SecurityException: Uid 10132 does not have permission to uri 0 # content://com.android.externalstorage.documents/document/primary%3ADCIM%2FAny%2FDir%2theFile.txt
at android.os.Parcel.readException(Parcel.java:1683)
at android.os.Parcel.readException(Parcel.java:1636)
at android.app.ActivityManagerProxy.grantUriPermission(ActivityManagerNative.java:4808)
at android.app.ContextImpl.grantUriPermission(ContextImpl.java:1655)
at android.content.ContextWrapper.grantUriPermission(ContextWrapper.java:712)
at de.cowabuja.androiduriaccess.MainActivity.onCreate(MainActivity.java:19)
at android.app.Activity.performCreate(Activity.java:6664)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
...
I try to call grantUriPermission because I try to solve the exception I did get before:
java.lang.SecurityException: Permission Denial: reading de.cowabuja.androidaccess uri content://com.android.externalstorage.documents/document/primary%3ADCIM%2FAny%2Dir%2FtheFile.txt from pid=1399, uid=10350 requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission()
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.cowabuja.androiduriaccess">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
</application>
</manifest>
You cannot assemble a Uri to a third-party provider like that and expect it to work. That provider has not granted you permission to work with that content. At most, it previously gave you temporary access to the content, but those rights died when your process died.
Either:
Move the file to one of the locations where you have filesystem access on removable storage: getExternalFilesDirs(), getExternalCacheDirs(), and getExternalMediaDirs(). If those methods (on Context) return 2+ entries, the second and subsequent ones are directories on removable storage that you can use. You can then use normal Java file I/O (e.g., File, FileInputStream).
Use the Storage Access Framework to ask the user to choose a file to work with. The user may elect to choose one on removable storage, or not, as it is the user's device and the user's files. You would then use the Uri with ContentResolver, via methods like openInputStream().
Related
I have a weird crash in Lollipopand below. I get a security Exception when trying to download a file from the server, but in devices running Marshmallow and above the app does not crash. Logcat:
Caused by: java.lang.SecurityException: need WRITE_EXTERNAL_STORAGE permission to use DESTINATION_FILE_URI: uid 10229 does not have android.permission.WRITE_EXTERNAL_STORAGE.
In App's grandle I use
targetSdkVersion 22
Will change after our first push on Google Console to target the latest sdk version, but for now this will remain to 22, so no need for run time permissions.
Furthermore, in App's Manifest we declare app's permission.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Also, the code that uses the DownloadManagerinside an AsynckTask :
try {
String dirPath = String.format("%5$s/%1$s/Resources/%2$s/%3$s/%4$s/", userID, resource.getiD(), filePackage.getiD(), language, dir.getCanonicalPath());
File makeDirs = new File(dirPath);
makeDirs.mkdirs();
} catch (Exception ex) {
ex.printStackTrace();
}
this.downloadManager = (DownloadManager) getApplicationContext().getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(url);
request.setDestinationInExternalFilesDir(getApplicationContext(), null, filePath);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
request.setVisibleInDownloadsUi(false);
downloadID = downloadManager.enqueue(request);
Again, this crash is observed only in Galaxy A5 with OS version 5.0.2, in an emulator running Samsung Galaxy S6 with Lollipop and in emulator running Kitkat 4.4.4 HTC One.
The full stack trace :
java.lang.RuntimeException: Unable to start activity ComponentInfo{...players.PDFViewer}: java.lang.SecurityException: need WRITE_EXTERNAL_STORAGE permission to use DESTINATION_FILE_URI: uid 10229 does not have android.permission.WRITE_EXTERNAL_STORAGE.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2808)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2873)
at android.app.ActivityThread.access$900(ActivityThread.java:181)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1482)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6145)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
Caused by: java.lang.SecurityException: need WRITE_EXTERNAL_STORAGE permission to use DESTINATION_FILE_URI: uid 10229 does not have android.permission.WRITE_EXTERNAL_STORAGE.
at android.os.Parcel.readException(Parcel.java:1540)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:185)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:137)
at android.content.ContentProviderProxy.insert(ContentProviderNative.java:475)
at android.content.ContentResolver.insert(ContentResolver.java:1260)
at android.app.DownloadManager.enqueue(DownloadManager.java:1336)
at de.imsystems.crmmobile.players.PDFViewer.onCreate(PDFViewer.java:104)
at android.app.Activity.performCreate(Activity.java:6374)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2752)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2873)
at android.app.ActivityThread.access$900(ActivityThread.java:181)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1482)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6145)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
If you have any thoughts, please share them, thanks in advance.
Eventually this post WRITE_EXTERNAL_STORAGE not working on lollipop even though it's set in the manifest helped me. What I did was to alter permissions in AndroidManifest.xml file like this:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="26" tools:replace="android:maxSdkVersion"/>
This way the app doesn't crashes!
I have an app that lets you make a list, and for each item you can put in a name, price, description, image, etc.
I started writing the app with the minimum API level 21. I'm currently trying to bring it down to API 19 so that I can get some of the KitKat users.
The problem happens when a user on API 19 tries to take a picture using the app. When they push the "take picture" button the camera pulls up just fine, but when they take a picture and hit the checkmark to save the image the camera app crashes.
Here is the error code in the logs for the camera app. The main line I'm seeing is this:
Caused by: java.lang.SecurityException: Permission Denial: opening provider android.support.v4.content.FileProvider from ProcessRecord{a517eda0 12685:com.android.camera/u0a32} (pid=12685, uid=10032) that is not exported from uid 10057
Process: com.android.camera, PID: 12685
java.lang.IllegalStateException: Could not execute method of the activity at android.view.View$1.onClick(View.java:3823)
at android.view.View.performClick(View.java:4438)
at android.view.View$PerformClick.run(View.java:18422)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at android.view.View$1.onClick(View.java:3818)
at android.view.View.performClick(View.java:4438)
at android.view.View$PerformClick.run(View.java:18422)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.SecurityException: Permission Denial: opening provider android.support.v4.content.FileProvider from ProcessRecord{a517eda0 12685:com.android.camera/u0a32} (pid=12685, uid=10032) that is not exported from uid 10057
at android.os.Parcel.readException(Parcel.java:1465)
at android.os.Parcel.readException(Parcel.java:1419)
at android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:2848)
at android.app.ActivityThread.acquireProvider(ActivityThread.java:4415)
at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2207)
at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1425)
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:906)
at android.content.ContentResolver.openOutputStream(ContentResolver.java:669)
at android.content.ContentResolver.openOutputStream(ContentResolver.java:645)
at com.android.camera.Camera.doAttach(Camera.java:1385)
at com.android.camera.Camera.onReviewDoneClicked(Camera.java:1362)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at android.view.View$1.onClick(View.java:3818)
at android.view.View.performClick(View.java:4438)
at android.view.View$PerformClick.run(View.java:18422)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
And also, since I believe it is a permissions kind of thing, here is my AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="jeremy.com.wineofmine">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name="jeremy.com.wineofmine.MainActivity"
android:screenOrientation="portrait"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="jeremy.com.wineofmine.AddActivity"
android:label=""
android:parentActivityName="jeremy.com.wineofmine.MainActivity"
android:screenOrientation="portrait" />
<activity
android:name="jeremy.com.wineofmine.DetailsActivity"
android:label=""
android:parentActivityName="jeremy.com.wineofmine.MainActivity"
android:screenOrientation="portrait" />
<activity
android:name="jeremy.com.wineofmine.EditActivity"
android:label=""
android:parentActivityName="jeremy.com.wineofmine.MainActivity"
android:windowSoftInputMode="stateHidden" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="jeremy.com.wineofmine.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
<activity android:name="jeremy.com.wineofmine.ImageActivity"
android:parentActivityName="jeremy.com.wineofmine.DetailsActivity"></activity>
</application>
Does anyone know whats going on here? I'm at a loss. I believe I gave the app permission to access the files using those two permission lines in the manifest.
If any additional code would be helpful just let me know.
UPDATE 1:
Adding the camera intent code (before I did not have the FLAG_GRANT_WRITE_URI_PERMISSION line, but I added it due to CommonsWare's post. It did not fix the issue):
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePictureIntent.addFlags(FLAG_GRANT_WRITE_URI_PERMISSION);
// 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) {
}
// Continue only if the File was successfully created
if (photoFile != null) {
photoURI = FileProvider.getUriForFile(this,
"jeremy.com.wineofmine.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
Sorry, I had it backwards in the comment. The camera app is writing, and so you need to add FLAG_GRANT_WRITE_URI_PERMISSION to the Intent.
UPDATE ...and, since you're trying to support Android 4.4, you need to also do this crap:
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP) {
i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
else {
ClipData clip=
ClipData.newUri(getContentResolver(), "whatevs", outputUri);
i.setClipData(clip);
i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
where:
i is the Intent
outputUri is the value you are using for EXTRA_OUTPUT
I am using a MediaStore class in my application and facing the below error(logcat),
E/DatabaseUtils: Writing exception to parcel
java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/audio/media from pid=5769, uid=10059 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()
at android.content.ContentProvider.enforceReadPermissionInner(ContentProvider.java:539)
at android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:452)
at android.content.ContentProvider$Transport.query(ContentProvider.java:205)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:112)
at android.os.Binder.execTransact(Binder.java:446)
05-11 17:27:35.982 5769-5769/com.media.wanware.fragmentdemo D/AndroidRuntime: Shutting down VM
05-11 17:27:35.984 5769-5769/com.media.wanware.fragmentdemo E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.media.wanware.fragmentdemo, PID: 5769
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.media.wanware.fragmentdemo/com.media.wanware.fragmentdemo.MainActivity}: java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/audio/media from pid=5769, uid=10059 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/audio/media from pid=5769, uid=10059 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()
at android.os.Parcel.readException(Parcel.java:1546)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:185)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:137)
at android.content.ContentProviderProxy.query(ContentProviderNative.java:421)
at android.content.ContentResolver.query(ContentResolver.java:478)
at android.content.ContentResolver.query(ContentResolver.java:422)
at com.media.wanware.fragmentdemo.MainActivity.getAllSongsFromDevice(MainActivity.java:45)
at com.media.wanware.fragmentdemo.MainActivity.onCreate(MainActivity.java:29)
at android.app.Activity.performCreate(Activity.java:5990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
I read this question,
Android reading external storage gives securityException
But I have placed the permissions correctly in my manifest below,
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.media.wanware.fragmentdemo">
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="19" />
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="19" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Also upon reading further I also went through this below question,
Android permission doesn't work even if I have declared it
The big reason for not getting your permission nowadays is because
your project has a targetSdkVersion of 23 or higher
For these permissions, not only does your targetSdkVersion 23+ app
need to have the element(s), but you also have to
ask for those permissions at runtime from the user on Android 6.0+
devices, using methods like checkSelfPermission() and
requestPermissions().
As a temporary workaround, drop your targetSdkVersion below 23.
But my target SDK is below 23 only. Why I am getting the same error ?
SDK 23 has all new method and functionalities to deal with the Android Permissions to try to compile your code with lower SDK verions. This may solve your problem.
And also remove maxSdkVersion from your permissions.
Happy Coding :)
Better than compiling with lower version, you have to make an appropriate code for all versions or eventually you will be left behind in the current ways of programming, especially in android.
Check this article of how to request permissions at run time here.
Here's and example of how I properly request these permission:
if (ActivityCompat.checkSelfPermission(context, android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context,
android.Manifest.permission.READ_EXTERNAL_STORAGE)) {
Snackbar.make(getWindow().getDecorView().getRootView(), "We need permissions to do stuff.\n Please allow.", Snackbar.LENGTH_LONG)
.setAction("Settings", new View.OnClickListener() {
#Override
public void onClick(View view) {
final Intent i = new Intent();
i.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
i.addCategory(Intent.CATEGORY_DEFAULT);
i.setData(Uri.parse("package:" + context.getPackageName()));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
context.startActivity(i);
}
}).show();
ActivityCompat.requestPermissions((Activity) context,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION},
MY_PERMISSIONS_REQUEST_READ);
} else {
ActivityCompat.requestPermissions((Activity) context,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION},
MY_PERMISSIONS_REQUEST_READ);
}
}else {
//Do your stuff here
}
I have a published app that gets reports about a ClassNotFoundExceptionfrom users that I went beyond my wits end trying to fix. I have not been able to reproduce this crash and similar instances of this error here on SO have either been cases of incorrect path to a dependency or a different package in the MainActivity than the manifest.
The issues with the wrong path to the dependencies are an Eclipse thing, while all the other errors could be easily fixed with Android Studio's "sync" and "clean project" (which I did to no avail).
I've triple checked all the package names and did not find any discrepancies.
Here is my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.johan.fsc">
<uses-permission android:name = "android.permission.VIBRATE"/>
<uses-permission android:name="com.android.vending.BILLING" />
<application
android:allowBackup="true"
android:icon="#drawable/logo"
android:label="#string/app_name"
android:fullBackupContent="true">
<activity
android:name="com.johan.fsc.MainActivity"
android:screenOrientation="portrait"
android:label="#string/app_name"
android:theme="#style/splashscreenTheme"
android:hardwareAccelerated="false"
android:largeHeap="true">>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name = "com.johan.fsc.SettingsActivity"
android:theme="#style/PreferencesTheme"/>
</application>
Here is the error report I always get from users:
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.johan.fsc/com.johan.fsc.MainActivity}: java.lang.ClassNotFoundException: Didn't find class "com.johan.fsc.MainActivity" on path: DexPathList[[zip file "/data/app/com.johan.fsc-1/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2426)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2595)
at android.app.ActivityThread.access$800(ActivityThread.java:178)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1470)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5624)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.johan.fsc.MainActivity" on path: DexPathList[[zip file "/data/app/com.johan.fsc-1/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
at android.app.Instrumentation.newActivity(Instrumentation.java:1071)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
... 10 more
Suppressed: java.io.IOException: Failed to open oat file from dex location '/data/app/com.johan.fsc-1/base.apk'
at dalvik.system.DexFile.openDexFileNative(Native Method)
at dalvik.system.DexFile.openDexFile(DexFile.java:295)
at dalvik.system.DexFile.<init>(DexFile.java:80)
at dalvik.system.DexFile.<init>(DexFile.java:59)
at dalvik.system.DexPathList.loadDexFile(DexPathList.java:262)
at dalvik.system.DexPathList.makeDexElements(DexPathList.java:231)
at dalvik.system.DexPathList.<init>(DexPathList.java:109)
at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:48)
at dalvik.system.PathClassLoader.<init>(PathClassLoader.java:65)
at android.app.ApplicationLoaders.getClassLoader(ApplicationLoaders.java:57)
at android.app.LoadedApk.getClassLoader(LoadedApk.java:370)
at android.app.LoadedApk.makeApplication(LoadedApk.java:562)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4818)
at android.app.ActivityThread.access$1500(ActivityThread.java:178)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1531)
... 7 more
Caused by: java.io.IOException: Failed to open oat file from /data/app/com.johan.fsc-1/arm/base.odex (error Failed to open oat filename for reading: No such file or directory) (no dalvik_cache availible) and relocation failed.
... 22 more
Caused by: java.io.IOException:
... 22 more
Caused by: java.io.IOException: Failed to remove obsolete file from /data/dalvik-cache/arm/data#app#com.johan.fsc-1#base.apk#classes.dex when searching for dex file /data/app/com.johan.fsc-1/base.apk: Permission denied
... 22 more
Suppressed: java.lang.ClassNotFoundException: com.johan.fsc.MainActivity
at java.lang.Class.classForName(Native Method)
at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
... 13 more
Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available/output.
It would seem that the culprit is java.io.IOException: Failed to remove obsolete file from /data/dalvik-cache/arm/data#app#com.johan.fsc-1#base.apk#classes.dex when searching for dex file /data/app/com.johan.fsc-1/base.apk: Permission denied, but I have not found why it's being invoked for some users and not the majority, and more importantly--how to fix it.
Possible Cause 1: There is a typo in the manifest in the line android:largeHeap="true">>. xml line ends with >>. This may be preventing the Intent-Filter from executing.
Possible Cause 2: My guess is that the phone is searching for a class <PackageName>.<PackageName>.<ClassName> instead of <PackageName>.<ClassName> . So definitely <PackageName>.<PackageName>.<ClassName> is not found and ClassNotFoundException would be the result. In android studio, in the manifest, by default activity name is written like this: android:name=".<ClassName>" instead of android:name="<PackageName>.<ClassName>" . You can give this a try.
Most phones may be checking whether packagename is added before the class name in the manifest. If it is added then they don't add it while searching of the class. While few phones must be adding the package name by default while searching for the class. Hence, they cannot find your class.
Certainly, you're naming your activity wrong. An activity CAN NOT consist the package's name in its name attribute.
Since you're already defining the package name here
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.johan.fsc">
You shouldn't mention that name here
<activity android:name="com.johan.fsc.MainActivity"
The only situation you should use package name along with a class's name is when the java class resides in a different package, as done in import statements.
Even if your activity is not present in the src folder and is instead present in a nested folder, android studio should handle the linking of manifest and the activity itself. Yet again, package name shouldn't be used there.
I am trying to develop a Google Map application.
The demo application works fine on a real device but fails on the emulator.
the logcat output is as follows:
java.lang.RuntimeException: Unable to start activity ComponentInfo{il.co.talkie.mapdemo/il.co.talkie.mapdemo.MapDemoActivity}: java.lang.SecurityException: "passive" location provider requires ACCESS_FINE_LOCATION permission.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.SecurityException: "passive" location provider requires ACCESS_FINE_LOCATION permission.
at android.os.Parcel.readException(Parcel.java:1599)
at android.os.Parcel.readException(Parcel.java:1552)
at android.location.ILocationManager$Stub$Proxy.requestLocationUpdates(ILocationManager.java:606)
at android.location.LocationManager.requestLocationUpdates(LocationManager.java:880)
at android.location.LocationManager.requestLocationUpdates(LocationManager.java:464)
at il.co.talkie.mapdemo.MapDemoActivity.getMyLocation(MapDemoActivity.java:170)
at il.co.talkie.mapdemo.MapDemoActivity.onCreate(MapDemoActivity.java:106)
at android.app.Activity.performCreate(Activity.java:6237)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Line 170 of MapDemoActivity is
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0,0, this);
The manifest file has these permissions (otherwise it will not work on a real device) as can be seen here:
Manifest.XML
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="il.co.talkie.mapdemo" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<permission
android:name="com.javapapers.currentlocationinmap.permission.MAPS_RECEIVE"
android:protectionLevel="signature" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="#string/google_maps_key" />
<activity
android:name=".MapDemoActivity"
android:label="#string/title_activity_map_demo" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
I would like to use the emulator to get my location - it displays the google map and it finds locations of addresses I provide, but it refuses to get my location - so I can not calculate distances properly.
What is wrong?
The emulator I use was created for API 23 and target Google API.
Any help will be welcomed.
If you are using emulator on Android M , you will need to request permission from user despite your manifest. See
ACCESS_FINE_LOCATION permission error emulator only
Android M Google API's to use Google Maps and other permissions
You may check out articles / tutorials e.g. this to work with the new system or just target a lower API <= 22
Error is occuring because of this problem:
Caused by: java.lang.SecurityException: "passive" location provider requires ACCESS_FINE_LOCATION permission.
Just add a new permission to your app manifest:
uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>