how to handle runtime permission auth in android M - android-permissions

I want to know the best practise to ask user for permission check and the code to run if user declines that particular permission access.

This example set states for CONTACTS permission
private static final int PERMISSIONS_REQUEST_READ_CONTACTS = 1;
private static String[] PERMISSIONS_CONTACT = {Manifest.permission.READ_CONTACTS}
if (checkSelfPermission(PERMISSIONS_CONTACT)) {
Log.i(TAG,
"Contact permissions have already been granted. Displaying contact details.");
} else {
Log.i(TAG, "Contact permissions has NOT been granted. Requesting permission.");
requestPermissions(PERMISSIONS_CONTACT, PERMISSIONS_REQUEST_READ_CONTACTS);
}
…
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case PERMISSIONS_REQUEST_READ_CONTACTS: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! do the
// calendar task you need to do.
Log.d(TAG, "permission granted");
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Log.d(TAG, "permission denied");
}
return;
}
}
}
You can follow the link
http://www.applicoinc.com/blog/android-m-permissions-review/

Dexter is an Android library that simplifies the process of requesting permissions at runtime.
Usage of Dexter

Some hint:
Always check for permission before calling operations on Google Play Services because they require permission but the management is in charge of you;
Don't ask for granted permissions: when you call request permissions with multiple permissions the system doesn't care if one or two permissions are already granted, the dialog is shown for all! So keep track only of permissions really needed. It could be strange for user grant already granted permissions;
Always check if it's needed to show a reason to the user using the method shouldShowRequestPermissionRationale() it could be not really obvious why you are asking a permission;
Send a notification to the user if you are checking for permission in background, in a service for example and allow it to grant the permission going with a tap in the app details system activity directly.

Take a look here - there's a flowchart that explains the whole process quite well.
Bottom line is that according to Android's documentation, you should always check and ask for permission if you don't have it (Android will automatically return DENIED in the callback if the user said to never ask again) and you should display a short message if the user has already declined you once in the past but hasn't marked the never ask again option.

For Example Camera Run time permission :
This Code you have to put in to camera button click
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
givePerMissons();
} else {
openCamera();
}
public void givePerMissons() {
if ((Utils.checkPermission(MainActivity.this, Manifest.permission.CAMERA)) {
openCamera();
} else {
Utils.givePermisson(MainActivity.this, Manifest.permission.CAMERA, Utils.PERMISSOIN);
if (!Utils.permissionsList.isEmpty()) {
requestPermissions(Utils.permissionsList.toArray(new String[Utils.permissionsList.size()]), Utils.PERMISSOIN_CODE);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case Utils.PERMISSOIN_CODE: {
if ((Utils.checkPermission(MainActivity.this, Manifest.permission.CAMERA)) {
openCamera();
} else {
Toast.makeText(getApplicationContext(),"Write Your message",Toast.LENGTH_LONG).show();
}
}
}
}
This Code you have to put in your utils Class:
public static final List<String> permissionsList = new ArrayList<String>();
public static void givePermisson(Context context, String permisson, String permissonType) {
int per = context.checkSelfPermission(permisson);
if (per != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(permisson);
} else if (per != PackageManager.PERMISSION_DENIED) {
}
}
public static boolean checkPermission(Context context, String permission) {
try {
PackageManager pm = context.getPackageManager();
if (pm.checkPermission(permission, context.getPackageName()) == PackageManager.PERMISSION_GRANTED) {
return true;
} } catch (Exception e) {
e.printStackTrace();
}
return false;
}

if ( ActivityCompat.shouldShowRequestPermissionRationale (this, Manifest.permission.CAMERA) || ActivityCompat.shouldShowRequestPermissionRationale (this,
Manifest.permission.RECORD_AUDIO) ) {
Toast.makeText (this,
R.string.permissions_needed,
Toast.LENGTH_LONG).show ();
} else {
ActivityCompat.requestPermissions (
this,
new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO},
CAMERA_MIC_PERMISSION_REQUEST_CODE);
}

Related

How can I allow in-app purchases through my .NET MAUI application?

I'm looking for documentation on this and I'm not finding it.
The main things I need to accomplish are:
Allow the user to purchase an add-on through the Microsoft Store.
Determine if they've already purchased an add-on so the appropriate application features can be enabled.
These two things can be accomplished easily for a UWP app as described here:
https://learn.microsoft.com/en-us/windows/uwp/monetize/enable-subscription-add-ons-for-your-app#code-examples
But I can't find an equivalent for .NET MAUI.
So in fact you can use the UWP code examples from Microsoft. The trick is to wrap everything that's Windows specific in a statement like this:
#if WINDOWS
...
#endif
So my code looks like this:
#if WINDOWS
using Windows.Services.Store;
#endif
namespace MyProject.Data
{
public class AddOnService
{
#if WINDOWS
private StoreContext context = null;
StoreProduct subscriptionStoreProduct;
// Assign this variable to the Store ID of your subscription add-on.
private string subscriptionStoreId = "INSERT-STORE-ID";
public async Task<bool> SetupSubscriptionInfoAsync()
{
if (context == null)
{
context = StoreContext.GetDefault();
// If your app is a desktop app that uses the Desktop Bridge, you
// may need additional code to configure the StoreContext object.
// For more info, see https://aka.ms/storecontext-for-desktop.
}
bool userOwnsSubscription = await CheckIfUserHasSubscriptionAsync();
if (userOwnsSubscription)
{
// Unlock all the subscription add-on features here.
return true;
}
// Get the StoreProduct that represents the subscription add-on.
subscriptionStoreProduct = await GetSubscriptionProductAsync();
if (subscriptionStoreProduct == null)
{
return true;
}
// Check if the first SKU is a trial and notify the customer that a trial is available.
// If a trial is available, the Skus array will always have 2 purchasable SKUs and the
// first one is the trial. Otherwise, this array will only have one SKU.
StoreSku sku = subscriptionStoreProduct.Skus[0];
if (sku.SubscriptionInfo.HasTrialPeriod)
{
// You can display the subscription trial info to the customer here. You can use
// sku.SubscriptionInfo.TrialPeriod and sku.SubscriptionInfo.TrialPeriodUnit
// to get the trial details.
}
else
{
// You can display the subscription purchase info to the customer here. You can use
// sku.SubscriptionInfo.BillingPeriod and sku.SubscriptionInfo.BillingPeriodUnit
// to provide the renewal details.
}
// Prompt the customer to purchase the subscription.
await PromptUserToPurchaseAsync();
return false;
}
private async Task<StoreProduct> GetSubscriptionProductAsync()
{
// Load the sellable add-ons for this app and check if the trial is still
// available for this customer. If they previously acquired a trial they won't
// be able to get a trial again, and the StoreProduct.Skus property will
// only contain one SKU.
StoreProductQueryResult result =
await context.GetAssociatedStoreProductsAsync(new string[] { "Durable" });
if (result.ExtendedError != null)
{
System.Diagnostics.Debug.WriteLine("Something went wrong while getting the add-ons. " +
"ExtendedError:" + result.ExtendedError);
return null;
}
// Look for the product that represents the subscription.
foreach (var item in result.Products)
{
StoreProduct product = item.Value;
if (product.StoreId == subscriptionStoreId)
{
return product;
}
}
System.Diagnostics.Debug.WriteLine("The subscription was not found.");
return null;
}
private async Task<bool> CheckIfUserHasSubscriptionAsync()
{
StoreAppLicense appLicense = await context.GetAppLicenseAsync();
// Check if the customer has the rights to the subscription.
foreach (var addOnLicense in appLicense.AddOnLicenses)
{
StoreLicense license = addOnLicense.Value;
if (license.SkuStoreId.StartsWith(subscriptionStoreId))
{
if (license.IsActive)
{
// The expiration date is available in the license.ExpirationDate property.
return true;
}
}
}
// The customer does not have a license to the subscription.
return false;
}
private async Task PromptUserToPurchaseAsync()
{
// Request a purchase of the subscription product. If a trial is available it will be offered
// to the customer. Otherwise, the non-trial SKU will be offered.
StorePurchaseResult result = await subscriptionStoreProduct.RequestPurchaseAsync();
// Capture the error message for the operation, if any.
string extendedError = string.Empty;
if (result.ExtendedError != null)
{
extendedError = result.ExtendedError.Message;
}
switch (result.Status)
{
case StorePurchaseStatus.Succeeded:
// Show a UI to acknowledge that the customer has purchased your subscription
// and unlock the features of the subscription.
break;
case StorePurchaseStatus.NotPurchased:
System.Diagnostics.Debug.WriteLine("The purchase did not complete. " +
"The customer may have cancelled the purchase. ExtendedError: " + extendedError);
break;
case StorePurchaseStatus.ServerError:
case StorePurchaseStatus.NetworkError:
System.Diagnostics.Debug.WriteLine("The purchase was unsuccessful due to a server or network error. " +
"ExtendedError: " + extendedError);
break;
case StorePurchaseStatus.AlreadyPurchased:
System.Diagnostics.Debug.WriteLine("The customer already owns this subscription." +
"ExtendedError: " + extendedError);
break;
}
}
#else
public async Task<bool> SetupSubscriptionInfoAsync()
{
return false;
}
#endif
}
}
I'll be modifying this some to suit my needs but I was able to debug it and step through the code to verify that the code is indeed executing as expected on Windows.

Facebook Login with Unity 5 - Always return me Graph API Error: Bad request

I just start write my first game with unity.
I Created on facebook app - in games category.
I downloaded Facebook idk and added to unity.
I changed app id in Facebook settings.
Now I tried my code:
public class LoginScript : MonoBehaviour {
public string resultstr { get; set; }
public Text LableResult { get; set; }
List<string> perms = new List<string> (){"public_profile", "email", "user_friends"};
// Use this for initialization
void Start () {
LableResult = gameObject.GetComponent<Text> ();
LableResult.text = "Test";
if (!FB.IsInitialized) {
// Initialize the Facebook SDK
FB.Init (InitCallback, OnHideUnity);
} else {
// Already initialized, signal an app activation App Event
FB.ActivateApp ();
}
}
private void InitCallback ()
{
if (FB.IsInitialized) {
// Signal an app activation App Event
FB.ActivateApp ();
// Continue with Facebook SDK
// ...
} else {
Debug.Log ("Failed to Initialize the Facebook SDK");
}
}
private void OnHideUnity (bool isGameShown)
{
if (!isGameShown) {
// Pause the game - we will need to hide
Time.timeScale = 0;
} else {
// Resume the game - we're getting focus again
Time.timeScale = 1;
}
}
// Update is called once per frame
void Update () {
}
private void AuthCallback (ILoginResult result)
{
if (FB.IsLoggedIn) {
// AccessToken class will have session details
var aToken = Facebook.Unity.AccessToken.CurrentAccessToken;
// Print current access token's User ID
Debug.Log (aToken.UserId);
// Print current access token's granted permissions
foreach (string perm in aToken.Permissions) {
Debug.Log (perm);
}
} else {
Debug.Log ("User cancelled login");
}
}
// On Facebook login button
public void OnFacebook ()
{
FB.LogInWithReadPermissions (perms, AuthCallback);
}
}
But I'm ALWAYS getting in Result:
Graph Api Error: 400 Bad request
And callback_id 2 (sometimes I've seen 3)
Login I try in Mock window with token from facebook.
I tried deploy on iPhone - and game just crashed when I click on login button
Please to close this topic. I fixed it. It was my fail )) (Used app token instead user token )) (Happends)))))
The same thing happened to me!
Remember to check the user token part, which won't be set by default!

Android permission at runtime with external class

I apologize for my English.
I try for a few hours to create a class that allows a request for permission to run time. I think the basic system makes the code unreadable if you have permission requested in several different activity.
So I created the following class
public class PermissionsHelper {
public interface PermissionHelperListener{
void accepted();
void rejected();
}
private static PermissionsHelper mInstance;
private static AppCompatActivity mContext;
public static ArrayList<PermissionHelperListener> permissionHelperListeners;
public static PermissionsHelper getInstance(AppCompatActivity context){
mContext = context;
if(mInstance == null){
mInstance = new PermissionsHelper();
}
return mInstance;
}
public void requestPermissions(String perm, PermissionHelperListener permissionHelperListener){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (mContext.checkSelfPermission(perm) != PackageManager.PERMISSION_GRANTED) {
int index = permissionHelperListeners.size();
permissionHelperListeners.add(permissionHelperListener);
mContext.requestPermissions(new String[]{perm}, index);
}
}
}
public void requestPermissions (String[] perms, PermissionHelperListener permissionHelperListener){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int index = permissionHelperListeners.size();
permissionHelperListeners.add(permissionHelperListener);
mContext.requestPermissions(perms, index);
}
}
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
permissionHelperListeners.get(requestCode).accepted();
} else {
permissionHelperListeners.get(requestCode).rejected();
}
permissionHelperListeners.remove(requestCode);
}
}
I call my class in onRequestPermissionsResultlike this
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
PermissionsHelper.getInstance(this).onRequestPermissionsResult(requestCode, permissions, grantResults);
}
everything is right until now. but when I use requestPermissions in my activity there is always the warning to check permission. I used #SuppressWarnings("ALL") and it work but I do not really like it. is there an other way to remove this warning or ask permissions with a callback like this ?
Thanks a lot
Updated:
I've found an awesome solution for this.
Just rename the method that you are using to check the permissions in your helper class to 'checkSelfPermission'. I'm guessing Lint scans the code for these words to decide when to show that dreaded red underline.
Older Answer:
Another way would be to use a try and catch block with a security exception.
try {
//code with the warning goes here
} catch (SecurityException e){
//do nothing here or ask for permission and recall this method
//again if the user grants the permission
}

Facebook share in wp8 App

I need to share a message on Facebook in my windows phone App by clicking share button. when click share button , if user has not logged in to Facebook, first we redirect to log in screen and then need to ask permission to publish.
public partial class FacebookLoginPage : PhoneApplicationPage
{
string uriToLaunch ;
// Create a Uri object from a URI string
Uri uri = null;
public FacebookLoginPage()
{
InitializeComponent();
uriToLaunch = #"fbconnect://authorize?client_id={AppID}&
scope=public_profile,publish_actions,read_stream&
redirect_uri=msft-{ProductId}%3a%2f%2fauthorize";
uri = new Uri(uriToLaunch);
this.Loaded += FacebookLoginPage_Loaded;
}
private void FacebookLoginPage_Loaded(object sender, RoutedEventArgs e)
{
DefaultLaunch();
}
// Launch the URI
async void DefaultLaunch()
{
// Launch the URI
var success = await Windows.System.Launcher.LaunchUriAsync(uri);
if (success)
{
// URI launched
}
else
{
// URI launch failed
}
}
}
I used above code , but permission screen not appears for publish. Output was as follows.
I followed example and used an AppId, then it works well. I feel that there is special configuration in Facebook App side . Please help me If anyone have idea about it.

Not showing FB login screen

I am not able to show facebook login screen, i have downloaded facebook blackberry API https://sourceforge.net/projects/facebook-bb-sdk/,
but it shows me the current user of facebook, if there is no logged in user then it should open log in screen, but its not showing, i am using the below code:
To retrieve the current user (Synchronously):
User user = fb.getCurrentUser();
To retrieve the current user (Asynchronously):
fb.getCurrentUser(new BasicAsyncCallback() {
public void onComplete(com.blackberry.facebook.inf.Object[] objects, final java.lang.Object state) {
user = (User) objects[0];
// do whatever you want
}
public void onException(final Exception e, final java.lang.Object state) {
e.printStackTrace();
// do whatever you want
}
});
my problem is i want the face book login screen, when device does not have any face book user.
You are trying to get the current user asynchronously. Don't do that if you want to see the login screen. Do this instead:
Runnable a = new Runnable(){
public void run(){
ApplicationSettings as = new ApplicationSettings(YOUR_FACEBOOK_NEXT_URL, YOUR_FACEBOOK_APPLICATION_ID, YOUR_FACEBOOK_APPLICATION_SECRET, Facebook.Permissions.ALL_PERMISSIONS);
Facebook fb = Facebook.getInstance(as);
try {
User user = fb.getCurrentUser();
if( user != null){
//do whatever
}
} catch(FacebookException e){
//Crazy happened!
}
}
};
UiApplication.getUiApplication().invokeLater(a);
I think this should solve your problem. Cheers.