I building an application that sampling GPS on starting.
As you probably know, permissions are requested during run-time from Android M and above.
So, in my case I'm starting with checking if permissions are needed, like this:
private void permissionForAndroidM()
{
if (Build.VERSION.SDK_INT > 22) {
String[] allPermissionNeeded = {
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO};
List<String> permissionNeeded = new ArrayList<>();
for (String permission : allPermissionNeeded)
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED)
permissionNeeded.add(permission);
if (permissionNeeded.size() > 0) {
requestPermissions(permissionNeeded.toArray(new String[0]), 0);
}
}
}
but Android continuing running the code and asking for GPS data ( = crash, because the user didn't accept the permission request).
I find many solutions about waiting for user input (like using DialogInterface.OnClickListener
, link, but it's cannot implemented in this case, because I'm not creating the dialog).
Bottom line, the question: How can I wait for user answer from the Android permission dialog ?
You can handle user response overriding method
public void onRequestPermissionsResult(
int requestCode,
String[] permissions,
int[] grantResults
)
from your activity.
Android continuing running the code and asking for GPS data ( = crash, because the user didn't accept the permission request).
Like many things in Android, requestPermissions()
is asynchronous. The user has not even been prompted for the permissions by the time this method returns.
How can I wait for user answer from the Android permission dialog ?
You don't.
If you find that you already have the permission, you do your work. If you find that you have to request permission, you delay doing that work until you get the permission, in onRequestPermissionsResult()
.
I worked it the below way:
1- Created a Boolean
helper to check permissions granted:
public class UtilPermissions {
public static boolean hasPermissions(Context context, String... allPermissionNeeded)
{
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& context != null && allPermissionNeeded != null)
for (String permission : allPermissionNeeded)
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED)
return false;
return true;
}
}
2- Created a Splash
screen as:
public class Splash extends Activity {
private static final int PERMISSION_ALL = 0;
private Handler h;
private Runnable r;
/*
SharedPreferences mPrefs;
final String settingScreenShownPref = "settingScreenShown";
final String versionCheckedPref = "versionChecked";
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
h = new Handler();
r = new Runnable() {
@Override
public void run() {
Toast.makeText(Splash.this, "Runnable started", Toast.LENGTH_SHORT).show();
/* // (OPTIONAL) these lines to check if the `First run` ativity is required
int versionCode = BuildConfig.VERSION_CODE;
String versionName = BuildConfig.VERSION_NAME;
mPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor editor = mPrefs.edit();
Boolean settingScreenShown = mPrefs.getBoolean(settingScreenShownPref, false);
int savedVersionCode = mPrefs.getInt(versionCheckedPref, 1);
if (!settingScreenShown || savedVersionCode != versionCode) {
startActivity(new Intent(Splash.this, FirstRun.class));
editor.putBoolean(settingScreenShownPref, true);
editor.putInt(versionCheckedPref, versionCode);
editor.commit();
}
else
*/
startActivity(new Intent(Splash.this, MainActivity.class));
finish();
}
};
String[] PERMISSIONS = {
READ_PHONE_STATE,
MODIFY_AUDIO_SETTINGS,
ACCESS_FINE_LOCATION,
READ_SMS
};
if(!UtilPermissions.hasPermissions(this, PERMISSIONS)){
ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
}
else
h.postDelayed(r, 1500);
}
// Put the below OnRequestPermissionsResult code here
}
3- Created the OnRequestPermissionsResult
as below:
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
int index = 0;
Map<String, Integer> PermissionsMap = new HashMap<String, Integer>();
for (String permission : permissions){
PermissionsMap.put(permission, grantResults[index]);
index++;
}
if((PermissionsMap.get(ACCESS_FINE_LOCATION) != 0)
|| PermissionsMap.get(READ_SMS) != 0){
Toast.makeText(this, "Location and SMS permissions are a must", Toast.LENGTH_SHORT).show();
finish();
}
else
{
h.postDelayed(r, 1500);
}
}
4- Defined the Splash
screen as Launcher
in the AndroidManifest.xml
as:
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
</activity>
<activity
android:name=".Splash"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
5- In the styles.xml
defined the SplashTheme
as:
<style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowBackground">@drawable/Splash</item>
</style>
6- The @drawable/Splash.xmls
is:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@color/lightgray"/>
<item>
<bitmap
android:gravity="center"
android:src="@mipmap/ic_launcher"/>
</item>
</layer-list>
7- In the values/colors.xmls
the lightgray
color had been defined as below:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="lightgray">#D3D3D3</color>
</resources>
After asking a permission, with a while loop, you can check if the permission is granted continuously , if granted you can change the value and exit while loop.
Boolean isAnswered = true;
while(isAnswered){
if (ActivityCompat.checkSelfPermission(getApplication(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getApplication(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Log.d("isanswered", String.valueOf(isAnswered));
}
else{
isAnswered = false;
Log.d("isanswered", String.valueOf(isAnswered));
}
}