2

I receive this error:

remove failed: ENOENT (No such file or directory) : /storage/emulated/0/screenShot.jpg
FileNotFoundException: /storage/emulated/0/screenShot.jpg: open failed: EACCES (Permission denied)

while running this screenshot method (the error points at the FileOutputStream creation from the imageFile, after "else"):

public void shareScreenshot(View v){
    Date now = new Date();
    android.text.format.DateFormat.format("yyyy-MM-dd_hh-mm-ss", now);

    CharSequence nowStr = DateFormat.format("yyyy-MM-dd_hh-mm-ss", now);

    try {
        // image naming and path  to include sd card  appending name you choose for file
        String mPath = Environment.getExternalStorageDirectory().toString() + "/" + "screenShot" + ".jpg";

        // create bitmap screen capture
        View v1 = getWindow().getDecorView().getRootView();
        v1.setDrawingCacheEnabled(true);
        Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
        v1.setDrawingCacheEnabled(false);

        File imageFile = new File(mPath);
        if(imageFile.delete()){

            FileOutputStream outputStream = new FileOutputStream(imageFile);
            int quality = 100;
            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
            outputStream.flush();
            outputStream.close();

            startShareIntent(imageFile);

        }else{

            FileOutputStream outputStream = new FileOutputStream(imageFile);
            int quality = 100;
            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
            outputStream.flush();
            outputStream.close();

            startShareIntent(imageFile);
        }


    } catch (Throwable e) {
        // Several error may come out with file handling or OOM
        e.printStackTrace();
        Toast.makeText(this,"Something went wrong, try again.", Toast.LENGTH_SHORT).show();

    }
}

And here's my manifest:

<?xml version="1.0" encoding="utf-8"?>

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="com.android.vending.BILLING" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/Theme.AppCompat.Light.NoActionBar" >
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Benni
  • 969
  • 1
  • 19
  • 29

3 Answers3

2

To request permission at runtime use this function which checks for version's 23 above as well as below

public  boolean isPermissionGrantedForStorage() {
    if (Build.VERSION.SDK_INT >= 23) {
        if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                == PackageManager.PERMISSION_GRANTED) {
            Log.v(TAG,"Permission is granted");
            return true;
        } else {

            Log.v(TAG,"Permission is revoked");
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
            return false;
        }
    }
    else { 
         //permission is automatically granted on sdk<23 upon installation
        Log.v(TAG,"Permission is granted");
        return true;
    }
}

Make sure your Activity implements OnRequestPermissionResult

Now callback for this will be

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if(grantResults[0]== PackageManager.PERMISSION_GRANTED){
        Log.v(TAG,"Permission: "+permissions[0]+ "was "+grantResults[0]);
        //resume tasks needing this permission
    }
}

More over you are not writing anything to FileOutputStream. Without writing how can you expect to get the image stored !

Ideally it should be this way

ByteArrayOutputStream bytearrayoutputstream;
File file;
FileOutputStream fileoutputstream;

@Override
 protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      bytearrayoutputstream = new ByteArrayOutputStream();
      // you code to access image and other logic ...
      Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
      bitmap.compress(Bitmap.CompressFormat.PNG, 60, bytearrayoutputstream);
      file = new File( Environment.getExternalStorageDirectory() + "/SampleImage.png");
     try 
      {
      file.createNewFile();
      fileoutputstream = new FileOutputStream(file);
      fileoutputstream.write(bytearrayoutputstream.toByteArray()); 
      fileoutputstream.close();
      } 
      catch (Exception e) 
      {
           e.printStackTrace();
      } 
}

Along with <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Sreehari
  • 5,621
  • 2
  • 25
  • 59
  • The problem is that the `FileOutputStream` constructor itself is failing to create the file, so the code does not have a chance to write any bytes to it. – Remy Lebeau Aug 18 '16 at 07:20
  • @RemyLebeau Did you tried my code ? What exception are you getting. If you are trying in a device , does it have an External SD card? And would appreciate if you could tell why this is DOWNVOTED – Sreehari Aug 18 '16 at 07:24
  • The question being asked is how to create a new file without a permission denied error, not with how to write to the file. Your answer does nothing at all to address the question that was actually asked. That is why it is downvoted. – Remy Lebeau Aug 18 '16 at 07:32
  • @RemyLebeau Added both the concerns in answer – Sreehari Aug 18 '16 at 08:06
  • the file is being written to by pasing the `FileOutputStream` directly to `bitmap.compress()`, the `ByteArrayOutputStream` is redundant. That whole portion of your answer is not necessary. – Remy Lebeau Aug 18 '16 at 15:37
1

As of API level 23 and higher camera permission needs to be requested at runtime

Change your onCreate code to:

if (PackageManager.PERMISSION_GRANTED == ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA)) { // asks primission to use the devices camera

 //what ever you want to do ..

} else {
    requestWritePermission(MainActivity.this);
}

and add the function

private static void requestWritePermission(final Context context) {
    if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, Manifest.permission.CAMERA)) {
        new AlertDialog.Builder(context)
                .setMessage("This app needs permission to use The phone Camera in order to activate the Scanner")
                .setPositiveButton("Allow", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.CAMERA}, 1);
                    }
                }).show();

    } else {
        ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.CAMERA}, 1);
    }
}

add these lines and try again. Also for more input read the flowing articale:

https://developer.android.com/training/permissions/requesting.html

Chief Madog
  • 1,738
  • 4
  • 28
  • 55
  • Oh I see, I'll try it out. But I suppose you used onCreate as an example only? I would check for the permission on my method of taking the screenshot instead? – Benni Aug 18 '16 at 07:17
  • The problem being asked about is with creating a new file, not with accessing the camera. Your answer may be technically correct, but it does nothing to address the question that was actually asked. That being said, `WRITE_EXTERNAL_STORAGE` is considered a "dangerous" permission, so runtime permission is required. If you edit your code example to handle that, I will retract my downvote. – Remy Lebeau Aug 18 '16 at 07:24
  • @Benni the user could revoke permission while your app is still running. So you should check permission every time you need it. – Remy Lebeau Aug 18 '16 at 07:29
  • @RemyLebeau It did solve my error and gave me a screenshot, but what do you mean about it being dangerous? – Benni Aug 18 '16 at 07:40
  • @Benni `WRITE_EXTERNAL_STORAGE` has nothing to do with taking screenshots. If you read the documentation that Chief's answer links to, `WRITE_EXTERNAL_STORAGE` is listed in the "dangerous permissions" group. It is not enough to simply declare that your app uses that permission, the user has to actually grant permission. On Android 6 and above, you need to ask for that permission in code at runtime. Chief's code shows you how to do that for camera access (another "dangerous" permission), now you need to adapt the code to ask for SD card access as well. – Remy Lebeau Aug 18 '16 at 08:00
-1

it showing this error because there is no such file in that folder as you specified in this code. may be something wrong with your filename specified by you. while taking screenshot it save with its app name.

Abhinav
  • 388
  • 4
  • 12
  • The "no such file" error is from the `File.delete()` call. That is OK. The problem being asked about is the "permission denied" error from the `FileOutputStream` constructor. Your answer is not addressing that issue. – Remy Lebeau Aug 18 '16 at 07:36