App crashes while reading files from Storage path in noughat - android

Issue:
The code is for choosing a file from external storage for doing OTA
update from Android App.This works well in Kitkat but when it comes to
Nougat phones(Moto G4) while choosing the Path App is crashing.
I tried debugging, the issue is with this line file = new File(item.getFilePath()); this creates NullPointerException in Nougat version,I also tried giving permission in Manifest for Reading External Storage,but still issue persists.what could be the issue? I have posted the code below.Please help
public class ChooseImageFileDialog extends Activity {
private FileListAdapter mAdaptor;
private ArrayList<FileFolderItem> mFileFolderList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mChooseButton = (Button) findViewById(R.id.select_button);
mChooseButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (mSelectedFile != null) {
getIntent().putExtra(RETURN_PATH_RESULT,
mSelectedFile.getPath());
setResult(RESULT_OK, getIntent());
finish();
}
}
});
mFileFolderList = new ArrayList<FileFolderItem>();
mAdaptor = new FileListAdapter(this, mFileFolderList);
mListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listview, View view, int
position, long id) {
FileFolderItem item = mFileFolderList.get(position);
if (item == null)
return;
File file = new File(item.getFilePath());
highlightSelectedItem(listview, view);
}
});
Modification :27/11/2017
mChooseButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (mSelectedFile != null) {
if (Build.VERSION.SDK_INT >= 23) {
if (checkPermission()) {
Log.e("value", "Permission already Granted, Now you
can save image.");
}
else {
requestPermission();
}
}else {
Log.e("value", "Not required for requesting runtime
permission");
getIntent().putExtra(RETURN_PATH_RESULT,
mSelectedFile.getPath());
setResult(RESULT_OK, getIntent());
finish();
}
}
}
});
private boolean checkPermission() {
int result =
ActivityCompat.checkSelfPermission(ChooseImageFileDialog.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (result == PackageManager.PERMISSION_GRANTED) {
return true;
}else{
return false;
}
}
private void requestPermission()
{
if(ActivityCompat.
shouldShowRequestPermissionRationale(ChooseImageFileDialog.th
is,Manifest.permission.WRITE_EXTERNAL_STORAGE))
{
Toast.makeText(ChooseImageFileDialog.this, "Write External Storage
permission allows us to do store images. Please allow this
permission in App Setting", Toast.LENGTH_LONG).show();
}
else
{
ActivityCompat.requestPermissions(ChooseImageFileDialog.this, new
String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
PERMISSION_REQUEST_CODE);
}
}
I have modified the code to get runtime permissions also but still
Application is crashing.Still having the same problem

You must request permission in Runtime for devices above Android 5.1.
So you need to ask for WRITE_EXTERNAL_STORAGE permission :)
Read the following documentation:
https://developer.android.com/training/permissions/requesting.html

Related

Trying to write to External/SD storage in Android

I'm trying to write a file to the SD card on android but i cannot get it to work properly. I'm using an Emulator with Android 6.0, where the app manifest has
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
And as far as i understand it, for this to work the user must grant the permission at run time too. I have this code with some explanation inline as comments:
public class AboutPref extends PreferenceFragmentCompat {
private static final int WRITE_REQUEST_CODE = 2;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.about_preferences);
Preference export_settings = findPreference("export_settings");
export_settings.setOnPreferenceClickListener(exportSettings());
}
// The export_settings Preference acts like a button, where this is called when it is clicked/tapped
// it basically checks if the permission is already granted, and if so, doesn't bother asking the user for it again
private Preference.OnPreferenceClickListener exportSettings()
{
return new Preference.OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
//SettingsHelper.ExportSettings(getContext(), getActivity());
int checkVal = getContext().checkCallingOrSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
if(checkVal != PackageManager.PERMISSION_GRANTED) {
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which){
case DialogInterface.BUTTON_POSITIVE:
askForStoragePermission();
break;
}
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setMessage(R.string.permission_explained)
.setPositiveButton(R.string.OK, dialogClickListener)
.show();
} else {
doExportSettings();
}
return false;
}
};
}
// This is called if the user had not given permission earlier as shown above
public void askForStoragePermission()
{
List<String> permissionsList = new ArrayList<>();
permissionsList.add(Manifest.permission.READ_EXTERNAL_STORAGE);
String[] permissions = permissionsList.toArray(new String[permissionsList.size()]);
requestPermissions(permissions, WRITE_REQUEST_CODE);
}
// When the user had not given permission earlier this is called after the permission request alert is closed
// which once again checks if permission is granted or not
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case WRITE_REQUEST_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
doExportSettings();
} else {
Toast.makeText(getContext(), "Failed! Need permission", Toast.LENGTH_LONG).show();
}
}
}
// and this is the actualy method that is run when permission is/was granted
private void doExportSettings()
{
// This one is simple for now, but will be used to write application settings to a file
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
File sdcard = Environment.getExternalStorageDirectory();
String exportFileName = "ApplicaitonName/app_settings.pwt";
File file = new File(sdcard, exportFileName);
try {
BufferedWriter out = new BufferedWriter(new FileWriter(file));
out.write(prefs.toString());
} catch (Exception e) {
System.out.println("export error => " + e.getMessage()); // <-- BUT this happens
}
}
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
// .. not used but required
}
}
But as stated i get the following error: export error => /storage/emulated/0/ApplicaitonName/app_settings.pwt: open failed: EACCES (Permission denied)
I must be missing something obvious no?

login button not working after permission to acces files granted in android app

This problem only exist during the first run of app after installation , that the login button not working after permission to access files granted ,in the next app run the login button works perfectly. can any one please tell me what is the issue associated with this.
Providing code for login activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
if(Build.VERSION.SDK_INT>=24){
try{
Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
m.invoke(null);
}catch(Exception e){
e.printStackTrace();
}
}
int hasWriteContactsPermissionW = ContextCompat.checkSelfPermission(login.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (hasWriteContactsPermissionW != PackageManager.PERMISSION_GRANTED) {
if (!ActivityCompat.shouldShowRequestPermissionRationale(login.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
showMessageOKCancel("You need to allow access to Files", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(login.this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_ASK_PERMISSIONS);
}
});
return;
}
ActivityCompat.requestPermissions(login.this,
new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_CODE_ASK_PERMISSIONS);
return;
}
loginbtn = findViewById(R.id.loginbtn);
loginbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("MMMMMM", "CLICKEDDD");
loginbtn.setVisibility(View.GONE);
EditText emailtxt = findViewById(R.id.emailtxt);
String email = emailtxt.getText().toString();
EditText passtxt = findViewById(R.id.passwordtxt);
String pass = passtxt.getText().toString();
GlobalVar.hash = String.valueOf(hashing.md5encrypt(email + pass));
Connect();
}
});
Your code does not run at first. It is because the permission checker stops execution when permission is granted on first run. I've copied your code snippet and commented the line
if (hasWriteContactsPermissionW != PackageManager.PERMISSION_GRANTED) {
if(.....) {
// .... your code
}
return; // this statement terminates (stops ?) the function
// solution is to remove this line
}
// these lines are never reached because of the return; above
loginbtn = findViewById(R.id.loginbtn);
Solution :
Check permissions at the end of onCreate
Remove return; from block where you check permissions
Modified Code :
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
if (Build.VERSION.SDK_INT >= 24) {
try {
Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
m.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}
}
// moved this above
loginbtn = findViewById(R.id.loginbtn);
loginbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("MMMMMM", "CLICKEDDD");
loginbtn.setVisibility(View.GONE);
EditText emailtxt = findViewById(R.id.emailtxt);
String email = emailtxt.getText().toString();
EditText passtxt = findViewById(R.id.passwordtxt);
String pass = passtxt.getText().toString();
GlobalVar.hash = String.valueOf(hashing.md5encrypt(email + pass));
Connect();
}
});
// moved this below
int hasWriteContactsPermissionW = ContextCompat.checkSelfPermission(login.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (hasWriteContactsPermissionW != PackageManager.PERMISSION_GRANTED) {
if (!ActivityCompat.shouldShowRequestPermissionRationale(login.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
showMessageOKCancel("You need to allow access to Files", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(login.this, new String[] {
Manifest.permission.WRITE_EXTERNAL_STORAGE
}, REQUEST_CODE_ASK_PERMISSIONS);
}
});
return;
}
ActivityCompat.requestPermissions(login.this,
new String[] {
Manifest.permission.WRITE_EXTERNAL_STORAGE
},
REQUEST_CODE_ASK_PERMISSIONS);
return;
}
}

READ_EXTERNAL_STORAGE permission not asking for permission

I need to ask the user for external storage when the app is installed for the first time. The code which I have used asks for the camera permission but not for the storage permissions. How do I solve it?
public class MainActivity extends AppCompatActivity {
Button loginbutton;
#TargetApi(Build.VERSION_CODES.M)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.CAMERA}, 1888);
}
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},211);
}
loginbutton = (Button)findViewById(R.id.loginButton);
loginbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext() , Home.class);
startActivity(intent);
}
});
}
}
First, no need to check for individual permissions...you can check multiple permissions together.
Check for multiple permissions
By this way it will solve your problem too
you overwriting your permissions your READ_EXTERNAL_STORAGE permission overlay your previous permission, try this permissions array
declear it before oncreate and replace with your permissions
String[] permissions = new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO};
if permission allowed check and do your work here
if (checkPermissions()) {
//your work if permission allowed
}
And here is check permission method
private boolean checkPermissions() {
int result;
List<String> listPermissionsNeeded = new ArrayList<>();
for (String p:permissions) {
result = ContextCompat.checkSelfPermission(this,p);
if (result != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(p);
}
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),MULTIPLE_PERMISSIONS );
return false;
}
return true;
}
let me know if it works for you.

Android 6.0 permission and target

I need to add the new permission things to an old project, which still has to stick to ant building. The following is the previous configuration:
project.properties:
target=android-23
AndroidManifest.xml:
<uses-sdk android:minSdkVersion="13" />
I changed AndroidManifest.xml to
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="23" />
but found that on my Android 6.0 phone it still warns me that my app is not compatible with the lastest Android permission requirements. And it behaves as if it really targets pre-23.
So is there any solutions?
I just share the code to add check for permissions, which has been made mandatory procedure since Marshnmallow. For instance, I check for permission to access camera.
private void launchCamera() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MyActivity.this,
Manifest.permission.CAMERA)) {
// Showing explanation to user to require permission
// <Build a dialog here. Following shows how to handle dialog clicks>
dialog.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Yes, user wants to give permission
dialog.dismiss();
ActivityCompat.requestPermissions(MyActivity.this,
new String[] {Manifest.permission.CAMERA},
Constants.PERMISSION_CAMERA);
}
});
alog.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// No, user does not want to give permission now
dialog.dismiss();
}
});
} else {
// No explanation needed, requesting for permission now.
ActivityCompat.requestPermissions(this,
new String[] {Manifest.permission.CAMERA},
Constants.PERMISSION_CAMERA);
}
} else {
// Permission to get location has been granted already.
try {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, Constants.CAMERA_CAPTURE_REQUEST);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
Log.e(TAG, "Camera is not found!");
}
}
}
Next we have a method to implement based on user's response provided to system dialog (which pops up just after our dialog).
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == Constants.PERMISSION_CAMERA ){
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
launchCamera();
} else if (grantResults[0] == PackageManager.PERMISSION_DENIED){
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CAMERA)) {
/*Here we have to show a dialog/ something else to show user why app requires permission. This is a good practice.*/
// Handle dialog clicks again
// Build a dialog here
btnPositiveOfDialog.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Yes, I want to give permission now after reading detailed message
dialog.dismiss();
ActivityCompat.requestPermissions(UserInfoActivity.this,
new String[] {Manifest.permission.CAMERA},
Constants.PERMISSION_CAMERA);
}
});
btnNegativeOfDialog.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// No, I still don't understand detailed message and want give permission away
dialog.dismiss();
}
});
} else {
// User checked 'Never ask again'
// Build a dialog here
btnPositiveOfDialog.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Yes, go to app settings and manually enable settings
dialog.dismiss();
final Intent i = new Intent();
i.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
i.addCategory(Intent.CATEGORY_DEFAULT);
i.setData(Uri.parse("package:" + UserInfoActivity.this.getPackageName()));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
MyActivity.this.startActivity(i);
}
});
btnNegativeOfDialog.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// No, I don't want to go to user settings and give permission now.
dialog.dismiss();
}
});
dialog.show();
}
}
}
}

doesn't show picture in android 6 and above

I am trying to learn how to use the camera in an app and this is what I reached , the idea is having a button that opens the camera and that the picture will instantly show on the screen after we take the picture, the second button is from an earlier version that couldn't show the picture immediately and had to be clicked in order to show it.
Anyways my problem is that this code doesn't show the picture at android 6.. on my android 5 device it works fine.. the picture is saved in the "sdcard/camera_app/cam_image.jpg" path either way and the button doesn't work as well so I'm thinking something about the imageview has changed from android 5 to 6? the question is pretty much how to make this work for android 6 phones
public class Add_Comment_Picture extends AppCompatActivity {
static final int CAM_REQUEST = 1;
ImageView imageView;
Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add__comment__picture);
button = (Button) findViewById(R.id.button);
imageView = (ImageView) findViewById(R.id.imageView);
Button button2 = (Button) findViewById(R.id.button3);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent camera_intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File file = getFile();
camera_intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
startActivityForResult(camera_intent , CAM_REQUEST);
}
});
button2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String path = "sdcard/camera_app/cam_image.jpg";
imageView.setImageDrawable(Drawable.createFromPath(path));
}
});
}
private File getFile()
{
File folder = new File("sdcard/camera_app");
if (!folder.exists())
{
folder.mkdir();
}
File image_file = new File(folder,"cam_image.jpg");
return image_file;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
String path = "sdcard/camera_app/cam_image.jpg";
imageView.setImageDrawable(Drawable.createFromPath(path));
super.onActivityResult(requestCode, resultCode, data);
}
}
You need to give READ_EXTERNAL_STORAGE and WRITE_EXTERNAL STORANGE permissions programmatically.
MANIFEST PERMISSIONS WON'T WORK on Android 6
With marshmallow(newest version of Android). We have got some restrictions in Using Sensitive permissions like : Storage,Contacts access, etc..In edition to give these permissions in manifest, We need to request them from users at Runtime.
For more details refer this : Android M permissions
For coding reference please refer this SO question : Android marshmallow request permission?
Add this code in your activity :
#Override
protected void onStart() {
super.onStart();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int hasWritePermission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
int hasReadPermission = checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
int hasCameraPermission = checkSelfPermission(Manifest.permission.CAMERA);
List<String> permissions = new ArrayList<String>();
if (hasWritePermission != PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (hasReadPermission != PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
}
if (hasCameraPermission != PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.CAMERA);
}
if (!permissions.isEmpty()) {
requestPermissions(permissions.toArray(new String[permissions.size()]), 111);
}
}
}
Add this after onActivityResult :
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 111: {
for (int i = 0; i < permissions.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
System.out.println("Permissions --> " + "Permission Granted: " + permissions[i]);
} else if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
System.out.println("Permissions --> " + "Permission Denied: " + permissions[i]);
}
}
}
break;
default: {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
After android 6.0 permission structure has changed. You must check permission on run-time. For example you will select a picture from image gallery, User give permission for gallery access before entering gallery.
You can look this document for this newness.
https://developer.android.com/training/permissions/requesting.html
Sample code for your issue
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
Log.v(TAG,"Permission is granted");
return true;
}
If not, you need to ask the user to grant your app a permission:
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
Good luck :)

Categories

Resources