FileNotFoundException open failed: EACCES (Permission denied) on Android Emulator - android

Following is the code where activity is erroring out :
the error happens at line outputStream = new FileOutputStream(file);
public class MainActivity extends AppCompatActivity {
public void layoutToJPG(View v) {
View screen = v.getRootView();
// or I've also tried: View screen = new View(this);
screen.setDrawingCacheEnabled(true);
Bitmap b = screen.getDrawingCache();
Log.d("bitmap", b.toString());
File path = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_MOVIES);
File file = new File(path, "/sample.jpg");
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
b.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
Toast.makeText(getApplicationContext(), "Saved to Gallery.", Toast.LENGTH_SHORT).show();
try {
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Error :
W/libc: Unable to set property "qemu.gles" to "1": connection failed; errno=13 (Permission denied)
W/System.err: java.io.FileNotFoundException: /storage/emulated/0/Movies/sample.jpg: open failed: EACCES (Permission denied)
at libcore.io.IoBridge.open(IoBridge.java:496)
at java.io.FileOutputStream.<init>(FileOutputStream.java:235)
The above is the error I am getting. I am running it on android emulator Pixel XL API 29
Does it require some special permissions to save file on the emulator.

As.
Android's permission system is one of the biggest security concern all
along since those permissions are asked for at install time. Once
installed, the application will be able to access all of things
granted without any user's acknowledgement what exactly application
does with the permission.
Android 6.0 Marshmallow introduces one of the largest changes to the
permissions model with the addition of runtime permissions, a new
permission model that replaces the existing install time permissions
model when you target API 23 and the app is running on an Android 6.0+
device
Try this code.
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
if (!ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
1);
}
}
Add this in Menifest:
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />

You have to add permission. And, ask user to accept permission.
Manifest :
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Request permission :
There's a library which you can use to ask for permission
Dexter.withContext(this)
.withPermission(Manifest.permission.CAMERA)
.withListener(new PermissionListener() {
#Override public void onPermissionGranted(PermissionGrantedResponse response) {/* ... */}
#Override public void onPermissionDenied(PermissionDeniedResponse response) {/* ... */}
#Override public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {/* ... */}
}).check();
Over than API level 23(maybe, I actually forgot) you have to request user to grant permission. That's why you have to add above source code.

Related

Does storage access framework work on Xiaomi devices?

I have an app that lets users open files via the storage access framework, edit them, and then overwrite the previously open file. In short this is the essential code:
private ActivityResultLauncher<String[]> mGetContent;
private Uri OpenFileUri;
public void onViewCreated(#NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mGetContent = registerForActivityResult(new ActivityResultContracts.OpenDocument(),
new ActivityResultCallback<Uri>() {
#Override
public void onActivityResult(Uri uri) {
try (InputStream in = getActivity().getContentResolver().openInputStream(uri))
{
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String text = reader.lines().collect(Collectors.joining("\n"));
binding.editBox.setText(text);
OpenFileUri = uri;
} catch (IOException e) {
e.printStackTrace();
}
}
});
binding.buttonOpen.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mGetContent.launch(new String[] {"text/*"});
}
});
binding.buttonSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (OpenFileUri == null)
return;
try (OutputStream mOutputStream = getActivity().getContentResolver().openOutputStream(OpenFileUri, "wt")) {
try (PrintWriter p = new PrintWriter(mOutputStream)) {
String t = binding.editBox.getText().toString();
p.println(t);
} catch (Exception e1) {
e1.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
Full code is available here: https://github.com/pekspro/CorruptFileDemo (created for a different purpose)
The app does work fine for most of my users, but one is using Xiaomi 11T Pro with Android 11. A device I do not have access to :-(. Other devices with Anroid 11 works fine. This user could open a file, but an exception is thrown when the file is saved (not sure what, do not have any logs). My real app also trying to call takePersistableUriPermission, but this also throws an java.lang.SecurityException on this device.
When I run the app and open a file, the URI is:
content://com.android.externalstorage.documents/document/…
But for this user, it instead begins with:
content://com.mi.android.globalFileexplorer.myprovider/external_files/Documents/…
This makes me suspect that Mi File Manager is used as a document selector on Xaomi devices.
If I open a file directly in Mi File Manager I see that is only has read only permissions.
Is this behavior expected for (some) Xiaomi devices? For testing purposes, can some force my app to use Mi File Manager as document selector?
Does storage access framework work on Xaomi devices?
Yes all you posted works.
Only a provider gives no write access to a file choosen by user.
(But maybe there is a setting that would give it ?? ...)

Permission denied (missing INTERNET permission?) Not Appearing in logcat

Does anyone know how the missing permissions behave and when is it shown in logcat?
I tried removing the INTERNET permission intentionally to trigger this exception, but it's not being triggered at all during httpsURLConnection.connect() below -- what happens is that it goes straight to the finally block.
Initially I thought it's because the permission was granted before and the app/test device remembers it, so I uninstalled the app then reinstalled it but the same thing happens.
Does anyone know what triggered this behavior? Thanks!
Edit: I have another app (Sunshine app from the Udacity course) where I copied this code from, and that one shows the permission error.
Excerpt from my class -- expecting a Permission denied (missing INTERNET permission?) in the httpsURLConnection.connect() line
public class MovieDBAPI extends AsyncTask<String, Object, List<Movie>> {
final String TAG = getClass().getSimpleName();
protected List<Movie> doInBackground(String... params) {
BufferedReader bufferedReader = null;
HttpsURLConnection httpsURLConnection = null;
StringBuffer stringBuffer = null;
try {
//create a URL
URL url = new URL(buildURL(params[0]));
Log.v(TAG, url.toString());
httpsURLConnection = (HttpsURLConnection) url.openConnection();
httpsURLConnection.setRequestMethod("GET");
httpsURLConnection.connect();
//get string input
InputStream inputStream = httpsURLConnection.getInputStream();
if (inputStream == null) {
//no input stream, nothing to do
return null;
}
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
stringBuffer = new StringBuffer();
while((line = bufferedReader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
stringBuffer.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//if stringBuffer is not null, then prepare the result
if (stringBuffer != null) {
return getMovieDataFromJSON(stringBuffer.toString());
}
if (httpsURLConnection != null) {
httpsURLConnection.disconnect();
}
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
}
For Android M and above, check Android docs..
You don't need to permission access for normal permissions
https://developer.android.com/guide/topics/security/permissions.html#normal-dangerous
https://developer.android.com/guide/topics/security/normal-permissions.html
For Marshmallow and above, you would need to request permissions at runtime. Mentioning them in AndroidManifest.xml isn't necessary,
Please refer to the following link,
https://developer.android.com/training/permissions/requesting.html
As for marshmallow and above android has a new run time permission system. You have ask for at run time . Add the following snippet into your class which will help you to ask for run time permission .
private int INTERNET_PERMISSION_CODE = 23;
//We are calling this method to check the permission status
private boolean isInternetnAllowed() {
//Getting the permission status
int result = ContextCompat.checkSelfPermission(this, Manifest.permission.INTERNET);
//If permission is granted returning true
if (result == PackageManager.PERMISSION_GRANTED)
return true;
//If permission is not granted returning false
return false;
}
//Requesting permission
private void requestInternetPermission(){
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.INTERNET)){
//If the user has denied the permission previously your code will come to this block
//Here you can explain why you need this permission
//Explain here why you need this permission
}
//And finally ask for the permission
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.INTERNET}, INTERNET_PERMISSION_CODE);
}
//This method will be called when the user will tap on allow or deny
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
//Checking the request code of our request
if(requestCode == INTERNET_PERMISSION_CODE){
//If permission is granted
if(grantResults.length >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
//Displaying a toast
Toast.makeText(this,"Permission granted for internet",Toast.LENGTH_LONG).show();
}else{
//Displaying another toast if permission is not granted
Toast.makeText(this,"Oops you just denied the permission",Toast.LENGTH_LONG).show();
}
}
}
Then what ever you are doing in doInBackground method
do it like this way
if(isInternetnAllowed()){
//do your doInbackground stuff
}else {
requestInternetPermission();
}
Hope it helps

How to take CLEAR_APP_CACHE permission in Android Marshmallow at runtime?

Code:
void clearCache() {
if (mClearCacheObserver == null) {
mClearCacheObserver = new CachePackageDataObserver();
}
PackageManager mPM = getPackageManager();
#SuppressWarnings("rawtypes")
final Class[] classes = {Long.TYPE, IPackageDataObserver.class};
Long localLong = Long.valueOf(CACHE_APP);
try {
Method localMethod =
mPM.getClass().getMethod("freeStorageAndNotify", classes);
localMethod.setAccessible(true);
// Start of inner try-catch block
try {
localMethod.invoke(mPM, localLong, mClearCacheObserver);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.getCause().printStackTrace();
}
// End of inner try-catch block
} catch (NoSuchMethodException e1) {
e1.printStackTrace();
}
}
Logcat:
java.lang.SecurityException: Neither user 10206 nor current process has android.permission.CLEAR_APP_CACHE.
at android.os.Parcel.readException(Parcel.java:1620)
at android.os.Parcel.readException(Parcel.java:1573)
at android.content.pm.IPackageManager$Stub$Proxy.freeStorageAndNotify(IPackageManager.java:5081)
at android.app.ApplicationPackageManager.freeStorageAndNotify(ApplicationPackageManager.java:2500)
at android.content.pm.PackageManager.freeStorageAndNotify(PackageManager.java:4710)
at java.lang.reflect.Method.invoke(Native Method)
at com.onexsoftech.clearcacheapp.MainActivity.clearCache(MainActivity.java:278)
at com.onexsoftech.clearcacheapp.MainActivity.insertDummyContactWrapper1(MainActivity.java:495)
at com.onexsoftech.clearcacheapp.MainActivity.insertDummyContact(MainActivity.java:472)
Prior to Android 6.0, CLEAR_APP_CACHE had a protectionLevel of dangerous, so ordinary SDK apps could request it in the manifest.
As of Android 6.0, CLEAR_APP_CACHE has a protectionLevel of signature|privileged. Ordinary Android apps cannot hold this permission. You can only hold this permission if your app is signed with the firmware's signing key or you are installed on the privileged system partition.
From Android M -> CLEAR_APP_CACHE, Protection level: system|signature
Android 6.0 does not change the behavior of normal permissions (all
non-dangerous permissions including normal, system, and signature
permissions).
So it is not possible to ask for that permission in runtime. To be more precise
A signature|system permission, meaning that it can only be held by
apps that are signed with the firmware's signing key or are installed
on the system partition (e.g., by a rooted device user). From this stackoverflow Q/A.
Docs:
https://source.android.com/devices/tech/config/runtime_perms.html#affected-permissions
Add Permission in AndroidManifest.xml
<permission android:name="android.permission.CLEAR_APP_CACHE"/>
<uses-permission android:name="android.permission.CLEAR_APP_CACHE"/>
Make a Constant for Request Code.
Constants.java
public static final int REQUEST_CODE_FOR_PERMISSION = 501;
Request Permission :-
public static void requestPermissionForClearCache(Activity activity) {
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.CLEAR_APP_CACHE) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CLEAR_APP_CACHE)) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.CLEAR_APP_CACHE}, Constatnts.REQUEST_CODE_FOR_PERMISSION);
} else {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.CLEAR_APP_CACHE}, Constatnts.REQUEST_CODE_FOR_PERMISSION);
}
}
}
Override Below method in Fragment.
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
if (requestCode == Constatnts.REQUEST_CODE_FOR_PERMISSION && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted successfully
} else {
// permission was NOT granted successfully
}
}

Read file in android - file permission denied

I want to read file from external storage. I uploaded the file in Eclipse DDMS to storage/sdcard (image below). But whenever I tried to read, I got an error of permission denied. Is there any problem in my file permission? Or I need to add anything in manifest file (I am not writing anything at the moment)?
Any help will be appreciated.
Code:
public void extimport(View v){
EditText xedittxt = (EditText) findViewById(R.id.frmexttxt);
String xedit = xedittxt.getText().toString();
xedit = xedit.trim();
File file;
file = new File(xedit);
StringBuilder text = new StringBuilder();
Log.d("fcheck",""+xedit);
try {
BufferedReader br = new BufferedReader(new FileReader(file)); //THIS LINE THROWS ERROR
Log.d("fcheck","f3"); //This line never got printed
String line;
while ((line = br.readLine()) != null) {
text.append(line);
text.append('\n');
}
br.close();
resultView = (TextView) findViewById(R.id.header);
resultView.setText(text);
}
catch (IOException e) {
Log.d("File open error",""+e);
Toast.makeText(getApplicationContext(), "Error opening the file.", Toast.LENGTH_SHORT).show();
}
}
LogCat:
11-19 00:21:54.252: D/fcheck(5885): /storage/sdcard/mylibman.csv
11-19 00:21:54.272: D/File open error(5885): java.io.FileNotFoundException: /storage/sdcard/mylibman.csv: open failed: EACCES (Permission denied)
Make sure you have added the permission to read external storage in your manifest file.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
I was experiencing the same problem and it can be easily removed by following either of these steps:
1. Install your app by using -g if installing on Android N and O versions.
2. Grant permission manually
Settings->apps->"app_name"->Permissions->Enable Switch
For Both steps 1 and 2, define uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE" and uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE" in AndroidManifest.xml
Like this :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="...">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- all permissions here -->
<application
...
Storage permission needs to be given by the user before accessing the functionality
Add Dependency:
dependencies:
permission_handler: ^5.0.1
Code Snippet:
var status = await Permission.storage.status;
if (status.isUndetermined) {
// You can request multiple permissions at once.
Map<Permission, PermissionStatus> statuses = await [
Permission.storage,
].request();
print(statuses[Permission.storage]); // it should print PermissionStatus.granted
}

Nexus 7 Android File Transfer (Socket Programming in Android)

public class WiFiLibrary {
public Socket client = null;
public FileInputStream fileInputStream = null;
public BufferedInputStream bufferedInputStream = null;
public OutputStream outputStream = null;
public void Connect()
{
try
{
client = new Socket("169.254.84.140",9999);
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void SendFile()
{
try
{
File file = new File("/sdcard/TEST/TEST.xml");
byte[] mybytearray = new byte[(int) file.length()];
fileInputStream = new FileInputStream(file);
bufferedInputStream = new BufferedInputStream(fileInputStream);
/**reads the file */
bufferedInputStream.read(mybytearray, 0, mybytearray.length);
outputStream = client.getOutputStream();
/** writes file to the output stream byte by byte */
outputStream.write(mybytearray, 0, mybytearray.length);
outputStream.flush();
bufferedInputStream.close();
outputStream.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
public void Disconnect()
{
try
{
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Here is my client class code for android. But when i said connect it crashes and closes. I add permissions my Manifest (There is no problem on the manifest). I used some part of code s in the past with a different tablet. But I try it Nexus 7 and it just crashed.
Here is my manifest permissions also:
android:minSdkVersion="16"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
Could anyone an idea what is the problem about my nexus 7 ?? I opened nexus 7 as developer also but nothing was changed. Samely it crashed.
I got this
http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html
The exception that is thrown when an application attempts to perform a networking operation on its main thread.
This is only thrown for applications targeting the Honeycomb SDK or higher. Applications targeting earlier SDK versions are allowed to do networking on their main event loop threads, but it's heavily discouraged. See the document Designing for Responsiveness.

Categories

Resources