In the below code,getInfoFromDevice is not being executed, I also tried with a Log.d() but it could not be of further help.
In the code I am using runtime permissions to check if the user has granted permission to access external storage and if yes the function getInfoFromDevice() is called. I am not sure if the placement of the function is correct or not ? But this function is not executing. what could be the reason ?
It does not throw any error,
public class MainActivity extends Activity implements ActivityCompat.OnRequestPermissionsResultCallback {
ArrayList<String> listOfSongs = new ArrayList<String>();
ListView liststructure;
final private int REQUEST_CODE_ASK_PERMISSIONS = 123;
String MUSIC_STRING = MediaStore.Audio.Media.IS_MUSIC + "!=0";
String[] STAR = {"*"};
String orderColumns = MediaStore.Audio.AudioColumns.TITLE + " COLLATE LOCALISED ASC";
private final int REQUEST_GRANTED_BY_USER = 1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkPermissions();
liststructure = (ListView) findViewById(R.id.listView);
SongsList list = new SongsList(MainActivity.this, listOfSongs);
liststructure.setAdapter(list);
}
private void checkPermissions() {
int permissionCheck = ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.READ_EXTERNAL_STORAGE);
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_GRANTED_BY_USER);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if(requestCode == REQUEST_GRANTED_BY_USER )
{
getInfoFromDevice();
} else {
// Permission Denied
Toast.makeText(MainActivity.this, "EXTERNAL_STORAGE Denied", Toast.LENGTH_SHORT)
.show();
}
}
void getInfoFromDevice() {
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor cursor = getContentResolver().query(uri, STAR, MUSIC_STRING, null, null);
if (cursor != null)
{
if (cursor.moveToFirst()) {
do {
String name = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));
String data = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
String album = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM));
String albumID = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
listOfSongs.add(album + " " + name + " " + albumID);
} while (cursor.moveToNext());
}
}
}
}
Please let me know if you need more details.
EDIT 1
The code will look for mp3 files with the help of MediaStore library and will check if it has a permission to access external storage and if yes it will call the function getInfoFromDevice()
just change you code like below:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
liststructure = (ListView) findViewById(R.id.listView);
SongsList list = new SongsList(MainActivity.this, listOfSongs);
liststructure.setAdapter(list);
checkPermissions();
}
private void checkPermissions() {
if (Build.VERSION.SDK_INT >= 23) {
int permissionCheck = ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.READ_EXTERNAL_STORAGE);
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_GRANTED_BY_USER);
}else{
getInfoFromDevice();
}
}else{
getInfoFromDevice();
}
}
First check permission as below,
public void checkPermission(String permission) {
if (ContextCompat.checkSelfPermission(BaseActivity.this,
permission)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(BaseActivity.this,
Manifest.permission.READ_EXTERNAL_STORAGE)) {
ActivityCompat.requestPermissions(BaseActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
10);
} else {
ActivityCompat.requestPermissions(BaseActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
10);
}
}
}
then,
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case 10: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
// permission granted call your function
getInfoFromDevice();
} else {
// permission denied.
}
return;
}
}
}
You can also use below plugin to easily add run time permission without more effort,
https://android-arsenal.com/details/1/3571
Related
Ask Permission, Am Asking for permission in My simple music app to read external Storage
It Asks for permission but doesn't list the Songs in the ListView
minSdkVersion 27
targetSdkVersion 29
It Shows the list of song after i terminate the app and start it again.
Here is my code:
public class MainActivity extends AppCompatActivity {
private int STORAGE_PERMISSION_CODE = 1;
ListView lvMusic;
MediaPlayer mp;
String name[],path[];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvMusic = (ListView) findViewById(R.id.lvMusic);
mp = new MediaPlayer();
ContentResolver contentResolver = getContentResolver();
Cursor cursor = contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
null,null,null,null);
name = new String[cursor.getCount()];
path = new String[cursor.getCount()];
int i = 0;
while(cursor.moveToNext()){
name[i] =cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));
path[i] = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
i++;
}
ArrayAdapter arrayAdapter =new ArrayAdapter(this, android.R.layout.simple_list_item_1,name);
if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
requestStoragePermission();
}
lvMusic.setAdapter(arrayAdapter);
}
private void requestStoragePermission(){
if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.READ_EXTERNAL_STORAGE)){
new AlertDialog.Builder(this)
.setTitle("Permission Needed")
.setMessage("This Permission is needed to Read Files")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, STORAGE_PERMISSION_CODE);
}
})
.setNegativeButton("Cancle", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.create().show();
}else{
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, STORAGE_PERMISSION_CODE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if(requestCode == STORAGE_PERMISSION_CODE ){
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
Toast.makeText(this,"Permission Granted",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this,"Permission not Granted",Toast.LENGTH_SHORT).show();
}
}
}
}
Thanks in advance!
Create a function loadSongs() and call it when the permission is granted.
void loadSongs(){
ContentResolver contentResolver = getContentResolver();
Cursor cursor = contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
null,null,null,null);
name = new String[cursor.getCount()];
path = new String[cursor.getCount()];
int i = 0;
while(cursor.moveToNext()){
name[i] =cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));
path[i] = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
i++;
}
ArrayAdapter arrayAdapter =new ArrayAdapter(this, android.R.layout.simple_list_item_1,name);
lvMusic.setAdapter(arrayAdapter);
)
Now in your on create, check if the permission is granted or not, if granted call loadSongs()
if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
requestStoragePermission();
else
loadSongs();
Now in onRequestPermission results call loadSongs if permission is granted:
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if(requestCode == STORAGE_PERMISSION_CODE ){
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
loadSongs();
Toast.makeText(this,"Permission Granted",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this,"Permission not Granted",Toast.LENGTH_SHORT).show();
}
}
}
In my app, i am calling cursor and then sending the cursor to recyclerView adapter but the problem is: At the 1st time when user-permissions were ask then the cursor returns null and so the recyclerView doesn't populate the data.
I have read these solution but they did not solve my problem.
1. Android READ_EXTERNAL_STORAGE permission not working
2. READ_EXTERNAL_STORAGE permission for Android
3. Android 6.0 (Marshmallow) READ_CONTACTS permission allows to read Contact's name when permission is denied
4. permission.READ_CONTACTS does not seem to work
My app is showing the data when i restart the app as then it doesn't ask for user-permissions.
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
Cursor mCursor=null;
recyclerViewSongAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
requestStoragePermission();
mCursor = getSongCursor();
if(mCursor==null)
Log.v("cursor_nullification","NO");
View playButton = findViewById(R.id.myPlayButtonId);
playButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "PLAY music", Toast.LENGTH_SHORT).show();
//Intent intent = new Intent(getBaseContext(),SongPlaying.class);
//intent.putExtra("song_")
}
});
recyclerView = findViewById(R.id.SongListId);
mAdapter = new recyclerViewSongAdapter(this,mCursor);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext(),LinearLayoutManager.VERTICAL,false);
//RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(getApplicationContext(),2);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
//Toast.makeText(this, "Toast calling", Toast.LENGTH_SHORT).show();
recyclerView.setAdapter(mAdapter);
}
public Cursor getSongCursor(){
try{
Log.v("cursor_method_start","till now okay");
Uri externalUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String[] projection = new String[]{
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.SIZE,
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.TRACK,
MediaStore.Audio.Media.YEAR
};
String selection = null;
String[] selectionArgs = null;
String sortOrder = MediaStore.Audio.Media.TITLE+" ASC";
Log.v("calling_cursor_formation","Okay till now");
Cursor songCursor = getContentResolver().query(externalUri,projection,selection,selectionArgs,sortOrder);
Toast.makeText(this, "Cursor formation", Toast.LENGTH_SHORT).show();
return songCursor;
}catch (Exception e) {
Toast.makeText(this, "ERROR!!!", Toast.LENGTH_SHORT).show();
return null;
}
}
private static final int MY_PERMISSIONS_REQUEST = 100;
private void requestStoragePermission() {
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST);
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// file-related task you need to do.
}
else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
}
}
}
I am quite new to cursor so i don't know where to use them. Do i have to call the cursor in background or is this line of code correct for calling cursor and how can i get my cursor data just after taking user-permissions.
Thanks
Initially from onCreate(), you should call getSongCursor() after checking OS version & if Permission is granted on above M devices:
if (android.os.Build.VERSION.SDK_INT < M || (android.os.Build.VERSION.SDK_INT >= M && context.checkSelfPermission(GlobalConstants.WRITE_EXTERNAL_PERMISSION) == PackageManager.PERMISSION_GRANTED)){
mCursor = getSongCursor();
setAdapterInRecyclerView(); // created below
}else {
requestStoragePermission();
}
And call mCursor = getSongCursor(); after receiving permission from user :
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mCursor = getSongCursor(); // here
setAdapterInRecyclerView(); // created below
}
else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
}
}
Please feel free to ask any further
UPDATE :
create a method for setting Adapter & call after getSongCursor():
private void setAdapterInRecyclerView(){
mAdapter = new recyclerViewSongAdapter(this,mCursor);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext(),LinearLayoutManager.VERTICAL,false);
//RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(getApplicationContext(),2);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
//Toast.makeText(this, "Toast calling", Toast.LENGTH_SHORT).show();
recyclerView.setAdapter(mAdapter);
}
add below code into your mainactivity and remove null form initialization Cursor mCursor=null;
private void onStart()
{
super.onStart();
requestStoragePermission();
}
I am calling from my app. After ends that call, I am trying to get a call duration. But my code return call duration two times. Last call duration while making call and new call duration after ends a call. But I need only one call duration after user ends the new call. How can i achieve this. Here is my code. Thanks in advance.
public class MainActivity extends AppCompatActivity {
private static final int CALL_PERMISSION= 99;
private static final int READ_LOG_PERMISSION=11;
Button btnGetCallDuration;
Context mContext;
private int mFlag = 0;
String phNumber = "";
boolean flag=false;
String callDuration = "";
public static int REQ_CODE=1;
private boolean callPermission=false;
private boolean readlogPermission=false;
public static final int MULTIPLE_PERMISSIONS = 10; // code you want.
String[] permissions = new String[] {
Manifest.permission.READ_CALL_LOG,
Manifest.permission.CALL_PHONE,
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = MainActivity.this;
btnGetCallDuration = (Button) findViewById(R.id.btnGetCallDuration);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkPermissions();
}
btnGetCallDuration.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.v("onclick", "called");
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:121"));
startActivity(intent);
//flag = true;
}
});
}
private boolean checkPermissions() {
int result;
List<String> listPermissionsNeeded = new ArrayList<>();
for (String p:permissions) {
result = ContextCompat.checkSelfPermission(mContext,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;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.v("request code",requestCode+"\t"+resultCode);
if(requestCode==REQ_CODE)
{
Log.v("request code",requestCode+"");
// getCallDruation();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case MULTIPLE_PERMISSIONS: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permissions granted.
callPermission=true;
} else {
// no permissions granted.
callPermission=false;
}
return;
}
}
}
#Override
protected void onPause() {
super.onPause();
Log.v("Pause is called","pause");
flag=true;
}
public boolean checkLocationPermission() {
if (ContextCompat.checkSelfPermission(mContext,
Manifest.permission.CALL_PHONE)
!= PackageManager.PERMISSION_GRANTED) {
// Asking user if explanation is needed
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.CALL_PHONE)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.CALL_PHONE},
CALL_PERMISSION);
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.CALL_PHONE},
CALL_PERMISSION);
}
return false;
} else {
return true;
}
}
public boolean readCallLogPermission() {
if (ContextCompat.checkSelfPermission(mContext,
Manifest.permission.READ_CALL_LOG)
!= PackageManager.PERMISSION_GRANTED) {
// Asking user if explanation is needed
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.READ_CALL_LOG)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_CALL_LOG},
READ_LOG_PERMISSION);
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.CALL_PHONE},
READ_LOG_PERMISSION);
}
return false;
} else {
callPermission=true;
return callPermission;
}
}
#Override
protected void onResume() {
super.onResume();
Log.v("flag","onrsume called");
if(flag)
{
getCallDruation();
flag=false;
}
}
private void getCallDruation() {
StringBuffer sb = new StringBuffer();
Uri contacts = CallLog.Calls.CONTENT_URI;
Log.v("get duration","called");
Cursor cur = getContentResolver().query(contacts, null, null, null, android.provider.CallLog.Calls.DATE + " DESC");
int number = cur.getColumnIndex(CallLog.Calls.NUMBER);
int duration = cur.getColumnIndex(CallLog.Calls.DURATION);
sb.append("Call Details : \n");
while (cur.moveToNext()) {
phNumber = cur.getString(number);
callDuration = cur.getString(duration);
sb.append("\nPhone Number:" + phNumber+"\t"+callDuration);
break;
}
cur.close();
String str = sb.toString();
Log.v("restult",str);
Toast.makeText(mContext, phNumber + "\t\t" + callDuration, Toast.LENGTH_SHORT).show();
}
}
This above code is called from onResume() life cycle method of activity.
I have Given this to Req Multiple permission at my splash screen
public class Main_MulPer extends Activity {
public static final int R_PERM = 321;
Context context = this;
public static boolean hasPermissions(Context context, String... permissions) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.rcssa);
int PERMISSION_ALL = 1;
String[] PERMISSIONS = {Manifest.permission.CAMERA,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.ACCESS_WIFI_STATE,
Manifest.permission.NFC,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
};
if (!hasPermissions(this, PERMISSIONS)) {
ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
Main_MulPer.this.finish();
Intent ss = new Intent(Main_MulPer.this, Main_acti.class);
ss.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
ss.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ss.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
ss.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(ss);
} else {
if (!hasPermissions(this, PERMISSIONS)) ;
{
ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Main_MulPer.this.finish();
Intent i = new Intent(Main_MulPer.this, Splash_two.class);
startActivity(i);
}
}, 3000);
}
}
}
}
So here My problem is that Its Asking two Permission at a time...
If I try to grant them its moving to another Activity... So I have Given Similar 3 activities with 2 Permission on Each..
But Due to Handler its Opening new activities..
Then I removed Delay Handler... Now It opening Last activity... Directly...
Can Any one Suggest Me How to Start The Main Activity after All Permissions only...
Without permission It should Exit app... Please Help me on this
Update
Insted of Multiple permissions I have Splited the 3 activities with two permission each... But here It should Go to next activity after permission But its Going to last activity every time first two activity permission are missing
So I need to exit app and give them...
All I need is that without permission don't move to next screen
Can any one suggest me after permission only move to next activity....
Try this,
public class Main_nPRC extends Activity {
public static final String MainPP_SP = "MainPP_data";
public static final int R_PERM = 2822;
private static final int REQUEST= 112;
Context mContext = this;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.rcssa);
SharedPreferences settings = getSharedPreferences(MainPP_SP, 0);
HashMap<String, String> map = (HashMap<String, String>) settings.getAll();
if (Build.VERSION.SDK_INT >= 23) {
Log.d("TAG","### IN IF Build.VERSION.SDK_INT >= 23");
String[] PERMISSIONS = {android.Manifest.permission.CAMERA,
android.Manifest.permission.READ_PHONE_STATE,
android.Manifest.permission.INTERNET,
android.Manifest.permission.ACCESS_NETWORK_STATE,
android.Manifest.permission.ACCESS_WIFI_STATE,
android. Manifest.permission.NFC,
android.Manifest.permission.READ_EXTERNAL_STORAGE,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
};
if (!hasPermissions(mContext, PERMISSIONS)) {
Log.d("TAG","### IN IF hasPermissions");
ActivityCompat.requestPermissions((Activity) mContext, PERMISSIONS, REQUEST );
} else {
Log.d("TAG","### IN ELSE hasPermissions");
callNextActivity();
}
} else {
Log.d("TAG","### IN ELSE Build.VERSION.SDK_INT >= 23");
callNextActivity();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d("TAG","### PERMISSIONS grant");
callNextActivity();
} else {
Log.d("TAG","### PERMISSIONS Denied");
Toast.makeText(mContext, "PERMISSIONS Denied", Toast.LENGTH_LONG).show();
}
}
}
}
private static boolean hasPermissions(Context context, String... permissions) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
public void callNextActivity()
{
Intent ss = new Intent(Main_nPRC.this, NMainSS.class);
ss.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
ss.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ss.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
ss.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(ss);
finish();
}
#Override
public void onBackPressed() {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle("ⓘ Exit ! " + getString(R.string.app_name));
alertDialogBuilder
.setMessage(Html.fromHtml("<p style='text-align:center;'>Please Fill the required details</p><h3 style='text-align:center;'>Click Yes to Exit !</h4>"))
.setCancelable(false)
.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
moveTaskToBack(true);
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
}
final int PERMISSION_REQUEST_CODE = 111;
if (Build.VERSION.SDK_INT >= 23) {
if (!checkReadContactPermission() ||!checkReadPhoneStatePermission()
|| !checkWriteExternalStorage() || !checkReadExternalStorage() ||
!checkSystemAlertWindowPermission() || !checkWriteContactPermission()) {
requestPermission();
} else {
// Move to main act
}
} else {
// Move to main act
}
You have to make method for check permission for each
for ex. this is for READ CONTACT, same way add all other
private boolean checkReadContactPermission() {
int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_CONTACTS);
if (result == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
return false;
}
}
Method for request permissions
private void requestPermission() {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_CONTACTS,
Manifest.permission.WRITE_CONTACTS,
Manifest.permission.READ_PHONE_STATE,
/* Manifest.permission.CAMERA,*/
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE},
PERMISSION_REQUEST_CODE);
}
finally RequestPermissionResult
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
// if granted then 0 else -1
// i have 5 permisson to check so 0,1,2,3,4..
if (grantResults[0] == PackageManager.PERMISSION_GRANTED &&
grantResults[1] == PackageManager.PERMISSION_GRANTED &&
grantResults[2] == PackageManager.PERMISSION_GRANTED &&
grantResults[3] == PackageManager.PERMISSION_GRANTED &&
grantResults[4] == PackageManager.PERMISSION_GRANTED) {
// means all permission are granted..move to Main activity
} else {
// show alert
}
break;
}
}
When you request for permission(s) you'll receive results in onRequestPermissionsResult handle results from inside as google docs says here
Updated
The permissions you mentioned are grouped ones example
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
it will ask only one permission for that and one will be for calls(Reading phone state) and you don't need to ask for permission for accessing network state and internet
I am trying to take an image from Gallery and set it to an imageview but in Android 6 there are some permission problems. Below is the method to ask for the permission. Should I ask for read external storage or write external storage?
Here is what I have done so far:
private static final int READ_CONTACTS_PERMISSIONS_REQUEST = 1;
public void getPermissionToReadExternalStorage() {
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
if (shouldShowRequestPermissionRationale(
Manifest.permission.READ_EXTERNAL_STORAGE)) {
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
READ_CONTACTS_PERMISSIONS_REQUEST);
}}}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String permissions[],
#NonNull int[] grantResults){
// Make sure it's our original READ_CONTACTS request
if (requestCode == READ_CONTACTS_PERMISSIONS_REQUEST) {
if (grantResults.length == 1 &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getActivity(), "Read Contacts permission granted", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getActivity(), "Read Contacts permission denied", Toast.LENGTH_SHORT).show();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
Now my on click listener to pick data from the Gallery:
pro.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/*");
if (android.os.Build.VERSION.SDK_INT >= 23) {
getPermissionToReadExternalStorage();
if (getPermissionToReadExternalStorage () this???? <==)
startActivityForResult(Intent.createChooser(intent, "Select Picture"), 0);
} else {
startActivityForResult(Intent.createChooser(intent, "Select Picture"), 0);
}}
});
return v;
}
Now I want to get result of the method getPermissionToReadExternalStorage() so I can start the Activity for picking gallery for Android 6. How can I get the result of the void class?
And another thing is do I have to write method for every permission my app asks for?
So I have completely rewritten the code to request permissions.
Now it supports requesting for multiple permissions and running code with proper result.
Also it works with preMarshmallow devices, so you don't have to check and copy the code in that case.
First, create an Activity class with this code (You can extend any king of activity you need, e.g. AppCompatActivity):
public abstract class PermissionActivity extends AppCompatActivity {
private final ArrayList<PermissionListener> permissionListeners = new ArrayList<>();
#SuppressWarnings("unused")
public void requestPermissions(int requestCode, String[] requestPermissions, PermissionListener permissionListener) {
requestPermissions(requestCode, requestPermissions, null, permissionListener);
}
#SuppressWarnings("unused")
public void requestPermissions(final int requestCode, String[] requestPermissions, String message, final PermissionListener permissionListener) {
final int[] grantResults = new int[requestPermissions.length];
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ArrayList<String> list_notGranted = new ArrayList<>();
for (String requestPermission : requestPermissions)
if (ContextCompat.checkSelfPermission(this, requestPermission) != PackageManager.PERMISSION_GRANTED)
list_notGranted.add(requestPermission);
if (list_notGranted.size() > 0) {
permissionListeners.add(permissionListener);
requestPermissions = list_notGranted.toArray(new String[list_notGranted.size()]);
if (message != null) {
boolean shouldShowRequestPermissionRationale = false;
for (String permission : requestPermissions)
if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
shouldShowRequestPermissionRationale = true;
break;
}
if (shouldShowRequestPermissionRationale) {
final String[] f_requestPermissions = requestPermissions;
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(message);
DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() {
#TargetApi(Build.VERSION_CODES.M)
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
PermissionActivity.super.requestPermissions(f_requestPermissions, requestCode);
break;
default:
for (int i = 0; i < grantResults.length; i++)
grantResults[i] = PackageManager.PERMISSION_DENIED;
if (permissionListener != null)
permissionListener.onResult(requestCode, f_requestPermissions, grantResults);
break;
}
}
};
builder.setPositiveButton("OK", onClickListener);
builder.setNegativeButton("Cancel", onClickListener);
builder.show();
} else {
super.requestPermissions(requestPermissions, requestCode);
}
} else {
super.requestPermissions(requestPermissions, requestCode);
}
} else {
for (int i = 0; i < grantResults.length; i++)
grantResults[i] = PackageManager.PERMISSION_GRANTED;
if (permissionListener != null)
permissionListener.onResult(requestCode, requestPermissions, grantResults);
}
} else {
if (permissionListener != null) {
for (int i = 0; i < grantResults.length; i++)
grantResults[i] = PackageManager.PERMISSION_GRANTED;
permissionListener.onResult(requestCode, requestPermissions, grantResults);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String permissions[], #NonNull int[] grantResults) {
for (Iterator<PermissionListener> it = permissionListeners.iterator(); it.hasNext(); ) {
PermissionListener permissionListener = it.next();
if (permissionListener.onResult(requestCode, permissions, grantResults)) {
it.remove();
}
}
}
public interface PermissionListener {
boolean onResult(int requestCode, String[] requestPermissions, int[] grantResults);
}
}
If you want to request permissions from Fragments, add this class:
public class PermissionFragment extends Fragment {
#SuppressWarnings("unused")
public void requestPermissions(int requestCode, String[] requestPermissions, PermissionActivity.PermissionListener permissionListener) {
requestPermissions(requestCode, requestPermissions, null, permissionListener);
}
#SuppressWarnings("unused")
public void requestPermissions(final int requestCode, String[] requestPermissions, String message, PermissionActivity.PermissionListener permissionListener) {
((PermissionActivity) getActivity()).requestPermissions(requestCode, requestPermissions, message, permissionListener);
}
}
Your Activities and Fragments should extend these classes instead of the standart ones.
Now you are ready to request the permissions by calling a method:
requestPermissions(int requestCode, String[] requestPermissions, PermissionListener permissionListener)
If the permission is required for the app to work, you should call this method and specify the message saying why the permission is required.
requestPermissions(int requestCode, String[] requestPermissions, String message, PermissionListener permissionListener)
DONT MISSCALL THE DEFAULT METHOD, WHICH IS
// DON'T USE THIS ONE!
requestPermissions(String[] requestPermissions, int requestCode)
// DON'T USE THIS ONE!
Here is the example of requesting contacts:
private void requestAndLoadContacts() {
String[] permissions = new String[]{Manifest.permission.READ_CONTACTS};
requestPermissions(REQUEST_PERMISSIONS_CONTACTS, permissions, "Read contacts permission is required for the app to work!", new PermissionListener() {
#Override
public boolean onResult(int requestCode, String[] requestPermissions, int[] grantResults) {
// Check if the requestCode is ours
if (requestCode == REQUEST_PERMISSIONS_CONTACTS) {
// Check if the permission is correct and is granted
if (requestPermissions[0].equals(Manifest.permission.READ_CONTACTS) && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted
// Calling a method to actually load the contacts
loadContacts();
} else {
// Permission not granted
Toast.makeText(MainActivity.this, "Access denied!", Toast.LENGTH_SHORT).show();
}
return true;
}
return false;
}
});
}
NOTE:
When you implement the PermissionListener, don't forget to return true when the requestCode is the correct one, otherwise the PermissionListener won't be removed from the ArrayList and you'll most likely get a small memory leak.
EDIT
I have rewritted the code and posted in another answer.
Old answer:
Yes, you have to check and ask for permission every time.
Usually I write the code like this:
private int requestPermissionCode;
private Runnable requestPermissionRunnable;
private void runPermissionCode(String requestPermission, int requestCode, Runnable codeToRun) {
if (android.os.Build.VERSION.SDK_INT >= 23) {
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissionCode = requestCode;
requestPermissionRunnable = codeToRun;
requestPermissions(new String[]{requestPermission},
requestCode);
}
} else {
codeToRun.run();
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String permissions[],
#NonNull int[] grantResults) {
if (requestCode == requestPermissionCode) {
if (grantResults.length == 1 &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (requestPermissionRunnable != null)
requestPermissionRunnable.run();
} else {
Toast.makeText(getActivity(), "Permission denied", Toast.LENGTH_SHORT).show();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
and run it like this:
runPermissionCode(Manifest.permission.READ_EXTERNAL_STORAGE, READ_CONTACTS_PERMISSIONS_REQUEST, new Runnable() {
#Override
public void run() {
// your code here
}
});
I am sure it is not a best way, but at least it gives a possibility to request permission and make actions easier.
Initialize Your Permission
private static final int INITIAL_REQUEST = 1337;
private static final int GET_ACCOUNTS = INITIAL_REQUEST+2;
private static final int LOCATION_REQUEST =INITIAL_REQUEST+3;
private static final String[] INITIAL_PERMS = {
Manifest.permission.GET_ACCOUNTS,
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_FINE_LOCATION
};
Check for device and Request for permissions
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!canAccessAccounts()|| !canAccessLocation() ||!canAccessInternet()) {
requestPermissions(INITIAL_PERMS, INITIAL_REQUEST);
}
}
Check Permission is granted Or not
private boolean canAccessAccounts() {
return (hasPermission(Manifest.permission.GET_ACCOUNTS));
}
private boolean canAccessLocation() {
return (hasPermission(Manifest.permission.ACCESS_FINE_LOCATION));
}
private boolean canAccessInternet() {
return (hasPermission(Manifest.permission.INTERNET));
}
private boolean hasPermission(String perm) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return (PackageManager.PERMISSION_GRANTED == checkSelfPermission(perm));
}
return (true);
}
Update Permissions and Check method for permissions onRequestPermissionsResult
void UpdatePermissions(){
canAccessInternet();
canAccessLocation();
canAccessInternet();
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
UpdatePermissions();
switch(requestCode) {
case GET_ACCOUNTS:
if (canAccessAccounts()) {
}
else {
}
break;
case LOCATION_REQUEST:
if (canAccessLocation()) {
}
else {
}
break;
case INITIAL_REQUEST:
if(canAccessInternet()){
}else {
}
break;
}
}