Wait until permisison request result received in Android - android

I've seen SO question Can you request permissions synchronously in Android Marshmallow (API 23)'s runtime permissions model?. The answer is no.
Hence, I added a code as below (simplified version):
public class MyActivity ... {
private boolean hasGotPermissionRequestResult = false;
#Override
public void onCreate(...) {
if (ContextCompat.checkSelfPermission(...) == PackageManager.PERMISSION_DENIED) {
ActivityCompat.requestPermission(...);
while (!hasGotPermissionRequestResult) {}
}
}
#Override
public void onRequestPermissionResult(...) {
// whether granted or not
hasGotPermissionRequestResult = true;
}
}
However, I am not sure whether my approach is nice, safe and efficient.

Well, what you trying to achieve simply ain't possible, however there are several ways to overcome this:
Only trigger the method you wanna call when the permission is granted.
If you'd like to make the User only uses your app because that particular permission is so important that your app will not function without it, then use an educated screen to tell the users why you would want to use this permission in an intro screen kinda way.
I've created a library just for this kind of scenario where the library simplify the Permissions for you, it can be also used as a stand Alone Activity that has an Intro to your permission. you could check it out in Github PermissionHelper Github

Related

Runtime permissions in capsulated objects - how to handle properly?

I was wondering, how to handle the runtime permission in capsulated objects.
So, let's say we have a loggerobject which needs to write to disk.
The only thing the objects should do is writing to the disk.
Shall this object also handle runtime permissions?
Shall the object be in the beginning unable to write (by a flag) and the flag will swap if we get the permission?
I will be glad to know, how some of you do this.
Thank you!
The permission is granted for the whole app, not for individual objects.
If you get the permission for your app once, you don't need to request it again and again.
In your case you can check and request the necessary permissions before writing to a file or even before the creation of your object.
The best practice is to request the permissions in the context just before using the features which require the permissions.
Check my library for handling permissions easily. Just get a reference of context and you can request permissions from anywhere.
https://github.com/nabinbhandari/Android-Permissions
There is no one clear answer for your question. Your question is related to the software architecture in general. So there might be a lot of different opinions. I will give you mine.
Often times you want a class to have a single responsibility and do only one job. Therefore, a logger only logs messages but it doesn't care a lot about permissions.
So I would say it's often a question about how to design your API and make it easy to work with.
For example, let's say we have an interface for Logger:
interface Logger {
void d(String tag, String message);
}
Then we introduce a concrete implementation called FileLogger:
final class FileLogger implements Logger {
#Override
public void d(String tag, String message) {
// write a message to a file somehow
}
}
The question here is should FileLogger#d fails with SecurityException if the permission has not been granted yet? Or should it just warn a developer somehow?
Personally, in this case I would modify FileLogger to not fail if the permission has not been granted yet, but the permission itself must be granted in another part of the application.
final class FileLogger implements Logger {
#Override
public void d(String tag, String messsage) {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
// write a log to a file
}
}
}
Let's take a look at another example. Imagine we have an interface called LocationApi:
interface LocationApi {
#Nullable
Location getLastLocation();
}
A user must grant a permission to the application so it can obtain his last location. Is it a critical to fail immediately if the app doesn't have a permission? I would say yes!
The implementation of this interface would look something like this:
final class LocationApiImpl implements LocationApi {
#Nullable
public Location getLastLocation() {
if (ContextCompat.checkSelfPermission(..) != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException();
}
// obtain a location
}
}
P.S. There is a special annotation RequiresPermission that can help you to indicate that a method requires a permission, otherwise it might throw SecurityException.
Then we can modify LocationApi interface like this:
interface LocationApi {
#RequiresPermission(Manifest.permission.ACCESS_FINE_LOCATION)
#Nullable
Location getLastLocation();
}

How to check if user has given camera or location permissions (android) UNITY

I really struggle with this since a while :( as I need an solution that works within UNITY3D.
I need to check if the user has given the permission to access the Android device camera (and location on a second level).
Normally the app start by asking for this permissions at launch, but if the user denies the access for the camera I need to know and check that later.
Otherwise the user could hit the camera UI button I made and try to access the camera via webcamtexture... and that leads into a crash of the app.
Since Android API 23 you cannot ignore or already grant permissions by changing the android manifest like I tried after reading several posts about that.
Thank's to everyone who has an idea to solve this.
Check this library: https://github.com/sanukin39/UniAndroidPermission
In that library I got these methods to check and request Permission.
public static void requestPermission(String permissionStr){
if(!hasPermission(permissionStr)) {
UnityPlayer.currentActivity.requestPermissions(new String[]{permissionStr}, 0);
}
}
public static boolean hasPermission(String permissionStr) {
if(Build.VERSION.SDK_INT < 23) {
return true;
}
Context context = UnityPlayer.currentActivity.getApplicationContext();
return context.checkCallingOrSelfPermission(permissionStr) == PackageManager.PERMISSION_GRANTED;
}
Hope it helps:)

Both methods run after permissions granted

I'm using Google's EasyPermissions library. In my app I have two buttons, one to record video and one to capture image. Since both require Camera Permissions they are both annotated with #AfterPermissionGranted.
So my method to record video looks like this :
#Override
#AfterPermissionGranted(RC_CAMERA_PERM)
public void openCameraToRecordVideo() {
if (EasyPermissions.hasPermissions(this, Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// Code here
}
And similarly for taking pictures :
#Override
#AfterPermissionGranted(RC_CAMERA_PERM)
public void openCameraToCaptureImage() {
if (EasyPermissions.hasPermissions(this, Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// Code here
}
They are both annotated with Permissions since I don't know which one user will click first.
What happens is when user clicks one button and accepts the permissions then both methods run one after the other. Which is obviously not the behavior I want.
I'd really appreciate any help on how to handle this situation.
Thank you.
Remove AfterPermissionGranted from both openCameraX function. Defined a private field lastAction. Write a new function openCamera with a AfterPermissionGranted annotation that check is lastAction is set and if so, call related function. In each openCameraX, check if you have camera permission and if not, update lastAction and start request camera permission.
Actually, what you are doing is asking the same permission two times with different function name so remove either openCameraToCaptureImage() method or openCameraToRecordVideo() method.

Check for access to notifications using NotificationListenerService

I'm using the >=4.3 NotificationListenerService to access notifications. On the first start, my app takes the user to the "Access Notifications" system panel, but I'd like to take the user there whenever the checkbox for my app in "Access Notifications" is disabled. I haven't found a isNotificationAccessEnabled()-method anywhere, but I definitely know that it's possible because apps like Krome do this, too.
Edit June 15th, 2016
I'm not sure which version of the support library this was added to, but it looks like this functionality is now built in. Simply use:
NotificationManagerCompat.getEnabledListenerPackages(context); (link to docs)
This returns a Set<String> that you can iterate through to find your package name. Note however that I haven't personally tested this. But it looks like it's probably preferred to use this in place of my old solution below.
Old Solution
This code is working for my app:
ContentResolver contentResolver = context.getContentResolver();
String enabledNotificationListeners = Settings.Secure.getString(contentResolver, "enabled_notification_listeners");
String packageName = context.getPackageName();
// check to see if the enabledNotificationListeners String contains our package name
if (enabledNotificationListeners == null || !enabledNotificationListeners.contains(packageName))
{
// in this situation we know that the user has not granted the app the Notification access permission
throw new Exception();
}
else
{
doSomethingThatRequiresNotificationAccessPermission();
}
Typical values that I've seen for the enabledNotificationsListeners String look like this:
User has given none of their apps Notification access permission
null or ""
User has given one app Notification access permission
"com.woodblockwithoutco.remotecontrollerexample/com.woodblockwithoutco.remotecontrollerexample.RemoteControlService"
User has given two apps Notification access permission
"com.scootrnova.android/com.scootrnova.android.ListenerService:com.woodblockwithoutco.remotecontrollerexample/com.woodblockwithoutco.remotecontrollerexample.RemoteControlService"
This implementation is very straightforward and works great :)
P.S. I got the idea to use the hardcoded "enabled_notification_listeners" String from this answer.
Starting with Android 8.1 (SDK 27) you can call isNotificationListenerAccessGranted on the NotificationManager. This is the correct API to use. Older Android versions should use getEnabledListenerPackages as a second best option. Relying on your listener callbacks can give incorrect results. See explanation below.
Im developer of Krome. What have I done to check if service is enabled is add public static variable that changes to true in onBind method and to false in unbind. That is how this service work.
Edit:
public static boolean isNotificationAccessEnabled = false;
#Override
public void onListenerConnected() {
isNotificationAccessEnabled = true;
}
#Override
public void onListenerDisconnected() {
isNotificationAccessEnabled = false;
}
Works well with slightly modified #Damians answer
public class NotifyListener extends NotificationListenerService{
public static boolean listnerConnected = false;
#Override
public IBinder onBind(Intent intent) {
Log.d(name,"onBind Called");
listnerConnected = true;
return super.onBind(intent);
}
#Override
public void onDestroy()
{
super.onDestroy();
Log.e("destroy", "called");
listnerConnected = false;
}
}
Starting with Android 8.1 (SDK 27) you can call isNotificationListenerAccessGranted on the NotificationManager. This is the correct API to use, not the one of the accepted answer. See explanation below.
Like shai tibber also already said the accepted answer is incorrect.
onListenerConnected() and onListenerDisconnect() can get called even when there is no NotificationListener access granted. So relying on this callbacks to set a boolean will give wrong results. And getEnabledListenerPackages(context‌​) will just return all the packages that have an enabled notification listener defined in there AndroidManifest (android:enabled=true). It's NOT directly related to the user access. The documentation states exactly that:
Get the set of packages that have an enabled notification listener component within them.

LVL licensing in a Live Wallpaper?

Has anybody had success integrating the Licensing Verification Library (LVL) with a Live Wallpaper? If it were just running an Activity, it'd be crystal clear to just extend my Activity from the Licensing Activity, which in turn extends Activity. But Live Wallpapers are a Service, and I'm not sure how the two are intended to interact.
I'm using code derived from this: http://www.droidforums.net/forum/android-app-developers/69899-market-license-easy-implementation-protect-your-apps.html which seems to be the code that nearly everything I can find on the web refers to.
I notice that wallpaper settings are an activity, and I have those working properly, but for some reason I can't grok the Licensing stuff...
It's actually really quite simple, you don't need to use any Activity class to implement licensing into a WallpaperService.
Make sure you've followed the directions carefully at http://developer.android.com/guide/publishing/licensing.html
Here's how I did it:
Your extended Engine class should include something similar to the following... (code not essential to your question has been removed)
class startYourEngines extends Engine {
public startYourEngines() {
super();
licenseStatus(); //custom license check method (for modularity)
//the rest of your engine would go here
}
public void onDestroy() {
super.onDestroy();
licenseChecker.onDestroy(); //we call this to close IPC connections
}
//prep work
private static final String BASE64_PUBLIC_KEY = //OMITTED//;
private LicenseCheckerCallback licenseCallback;
private LicenseChecker licenseChecker;
private byte[] salt = "rAnd0mStr!ng".getBytes();
private AESObfuscator aes;
private String deviceId;
//our custom license check method
private void licenseStatus() {
deviceId = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
aes = new AESObfuscator(salt, getPackageName(), deviceId);
licenseCallback = new licenseVerification();
licenseChecker = new LicenseChecker(context, new ServerManagedPolicy(context, aes), BASE64_PUBLIC_KEY);
licenseChecker.checkAccess(licenseCallback);
}
//our callback method
private class licenseVerification implements LicenseCheckerCallback {
#Override
public void allow() {
//allow full app use
}
#Override
public void dontAllow() {
//prevent or limit app use
}
#Override
public void applicationError(ApplicationErrorCode errorCode) {
//error handling here
}
}
}
Licensing on the Android platform was created with versatility in mind. Just be sure to read through the documentation, and you shouldn't have any issues.
I have only written applications that start activities, but looking at my source code, it seems that the only reason that you would have to have an Activity do the license check is to show dialogs.
In all of the examples available on line, the LicenseCheckerCallback implementation always shows a dialog in the allow() and dontAllow() methods. Why not just show a toast in dontAllow() and exit your wallpaper service (call stopSelf(YourService.this))?
Let me know if you want more information, because I dont think you are limited to only using an activity for license checking. As an aside, make sure that you dont keep whole strings, etc in your app or in the preferences. Anyone with root access can access your preferences and if your app is decompiled, your strings are visible...
I think I've actually got it working now. I'm extending LicenseCheckActivity to my own Activity class that I'm calling in the manifest file with the usual MAIN action and LAUNCH category. I instantiate my class, do the license check, and then either allow the wallpaper to function or not based on that result (though the best way to do that is still something I need to sort out).
It almost seems too easy that I think I must be missing something. I'd appreciate anybody with experience with selling a licensed live wallpaper on the Android Market to share whatever wisdom they care to.

Categories

Resources