About Xamarin Camera permission - xamarin.android

I'm making Android app with Xamarin, This use zxing.
When user click a button, It show QrScan page and dialog for asking allow camera permission.
I want to show dialog asking permission by user allow permission every time clicked button.
Now, If user click deny, permission dialog ever don't shown, before restart application.
Have you any idea?
This is my source.
Android --- MainActivity.cs
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
ZXing.Net.Mobile.Forms.Android.Platform.Init();
LoadApplication(new App { OSVersion = "Android Version " + "2.0" });
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
// If this is not be, occur unexpected exception when user click deny
if(grantResults[0] == Permission.Denied)
{
return;
}
global::ZXing.Net.Mobile.Android.PermissionsHandler.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
And this is my Executing QrScan Method In PCL project which called clicked button.
public async void ImgQrScan_Clicked(object sender, EventArgs e)
{
this.TappedEvent?.Invoke(sender, e);
CustomScanViewMaker();
await Navigation.PushModalAsync(oCustomQrScanPage);
zxingPage.IsScanning = true;
string sScanResult = "";
zxingPage.OnScanResult += (result) =>
{
sScanResult = result.Text;
zxingPage.IsScanning = false;
Device.BeginInvokeOnMainThread(async () =>
{
this.OnClicked?.Invoke(sender, new QrScannerClickEventArgs(sScanResult));
await Navigation.PopModalAsync();
});
};
this.OnClicked?.Invoke(sender, new QrScannerClickEventArgs(sScanResult));
}
Thank you.

I want to show dialog asking permission by user allow permission every time clicked button.
You could try using shouldShowRequestPermissionRationale method to implement this feature, as the document said :
To help find situations where the user might need an explanation, Android provides a utiltity method, shouldShowRequestPermissionRationale(). This method returns true if the app has requested this permission previously and the user denied the request.
For its usage, you could refer to the official document Requesting Permissions at Run Time, in C#, it's something like this :
// Here, this is the current activity
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.Camera) != Permission.Granted)
{
// Should we show an explanation?
if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.Camera))
{
// Provide an additional rationale to the user if the permission was not granted
// and the user would benefit from additional context for the use of the permission.
// For example if the user has previously denied the permission.
// 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.
Log.Info(TAG, "Displaying camera permission rationale to provide additional context.");
}
else
{
// No explanation needed, we can request the permission.
ActivityCompat.RequestPermissions(this, new string[] { Manifest.Permission.Camera }, REQUEST_CAMERA);
// REQUEST_CAMERA is an app-defined int constant. The callback method gets the
// result of the request.
}
}
else
{
System.Diagnostics.Debug.WriteLine("Permission Granted!!!");
}

Related

Getting email id value null as response during apple-authentication

I'm implementing apple-authentication in react native using expo-apple-authentication package.
Below is the code which I'm calling on button's onPress.
async handleSocialLogin() {
const { mutate, BB, onSuccess, navigation } = this.props;
try {
const result = await AppleAuthentication.signInAsync({
requestedScopes: [
AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
AppleAuthentication.AppleAuthenticationScope.EMAIL,
],
});
Alert.alert(JSON.stringify(result))
// signed in
} catch (e) {
Alert.alert(e)
if (e.code === 'ERR_CANCELED') {
// handle that the user canceled the sign-in flow
} else {
// handle other errors
}
}
}
It should return me authentication-token, Full_Name and Email which I requested in scope but It is giving me null for Full_Name and Email.
As per the documentation:
requestedScopes (AppleAuthenticationScope[]) (optional) - Array of user information scopes to which your app is requesting access. Note that the user can choose to deny your app access to any scope at the time of logging in. You will still need to handle null values for any scopes you request. Additionally, note that the requested scopes will only be provided to you the first time each user signs into your app; in subsequent requests they will be null.
You have probably already logged in once and didn't catch the logs. Subsequent log in will result in this data being null

How to start gluon mobile PositionService using start() method with different Parameters like accuracy, time interval etc

Currently I am using the gluon mobile PositionService to detect user current location. But I want to configure the PositionService with diffrent settings using
Parameters API. But when I use start(Parameters parameters) I am getting redirected to location settings in android application.
Please tell me what is a best way to configure and start this service using paramters.
public void initialize() {
try {
setupLocationService();
} catch (Throwable t) {
LOGGER.log(Level.SEVERE, "Error setting up location service", t);
}
}
private void setupLocationService() {
LOGGER.log(Level.INFO, "Register position service ");
Services.get(PositionService.class).ifPresent(ps -> {
// If I uncomment following line the application presenter is not displayed
// Instead I see the Location menu in anroid settings page when user has to manulaly enable the location
//ps.start(new Parameters(Parameters.Accuracy.LOW, LocationSynchronizer.ACCEPTABLE_TIMEFRAME, LocationSynchronizer.ACCEPTABLE_ACCURACY, true));
ps.positionProperty().addListener(e -> {
Position position = ps.getPosition();
if (position != null) {
// sync location using rest API
locationSynchronizer.syncronizeLocations(position);
}
});
});
}

Flutter: Location package Not working on First Time App Install

My current app uses the Location package (link) to obtain the user's current latitude and longitude to be used to find nearby facilities.
This is the code I am using (similar to the example in the documentation)
Map<String, double> _currentLocation;
Map<String, double> _startLocation;
StreamSubscription<Map<String, double>> _locationSubscription;
String error;
bool _permission = false;
Location _location = new Location();
// Platform messages are asynchronous, so we initialize in an async method.
initPlatformState() async {
Map<String, double> location;
try {
_permission = await _location.hasPermission();
location = await _location.getLocation();
error = null;
} on PlatformException catch (e) {
if (e.code == 'PERMISSION_DENIED') {
error = 'Permission denied';
} else if (e.code == 'PERMISSION_DENIED_NEVER_ASK') {
error = 'Permission denied - please ask the user to enable it from the app settings';
}
location = null;
}
setState(() {
_startLocation = location;
print("Starting coordinates: ${_startLocation["latitude"]}, ${_startLocation["longitude"]}");
});
}
#override
void initState() {
super.initState();
initPlatformState();
_locationSubscription =
_location.onLocationChanged().listen((Map<String,double> result) {
setState(() {
_currentLocation = result;
print("Current coordinates: ${_currentLocation["latitude"]}, ${_currentLocation["longitude"]}");
});
});
}
The only problem I am facing is that whenever there is a fresh install of a new apk of the app, the app does not find the location after location permission has been granted.
After location has been granted I have set up a print statement to print out the user's location but for some reason it is not printing anything the first time only. After I restart the app then it prints out the location just fine.
First Time Opening After Install
After Restarting the App
Any experts that use the Location package that could help me with this problem?
According to plugin’s source code when you invoke getLocation method it asks ActivityCompat.requestPermissions to get required permission and then process. According to docs from Google:
This method functions asynchronously. It returns right away, and after the user responds to the prompt, the system calls the app's callback method with the results
, but flutter plugin has an issue about location callbacks for Android 6+ and as a workaround it is recommended to aim SDK 21.
So it seems that “native” part of this plugin doesn’t play well with Android 6+. There are two workarounds:
Set SDK to 21 version for your Android project, but I would definitely not recommend doing that.
Create some sort of “hello screen”, which will introduce the app and handle permissions there.
Meanwhile, I am really interested in what is wrong with the plugin cause its implementation seems good, so in case I’ll find how to fix it I’ll get back here.

Xamarin Forms does not wait for GeoLocation approval on iOS

I am have Xamarin Forms cross platform application for iOS, Android and UWP. I use the Xam.Plugin.Geolocator to get the location from each of the devices. My challenge with iOS is on the first launch of the app on a device. My code runs through and detects that IsGeolocationEnabled for the Plugin.Geolocator.Abstractions.IGeolocator object is false before the use is ever presented with the option to allow the application to use the device's location. This causes my app to inform the user that Location Services are not enabled for the application.
Basically I am hitting the line of code below before the use is ever asked about location services:
if (!App.gobj_RealGeoCoordinator.IsGeolocationEnabled)
ls_ErrorMessage = resourcestrings.GetValue("NoLocationServicesMessage");
On the other platforms, UWP at least, it seems that the app is paused while waiting for the user to respond to the request to use location services. Android just seems to automatically allow access to location if an app uses it.
Any idea how I can have the iOS detect if the request to use location services has been answered or not on the first run? Any suggestions would be greatly appreciated.
UPDATE(1):
I have all the correct items in my info.plist as seen below. I do eventually get the request to use the location just after my app has already checked IsGeolocationEnabled and decided the user has not enabled location services for the app.
UPDATE (2):
So I made a little progress using the following code.
try
{
while (!App.gobj_RealGeoCoordinator.IsGeolocationEnabled)
{
await Task.Delay(1000);
}
ViewModelObjects.AppSettings.CanAccessLocation = App.gobj_RealGeoCoordinator.IsGeolocationEnabled;
}
catch (Exception ex)
{
XXXXXXX
}
The challenge is that the plugin appears to provide me no way of knowing in the user has not responded to the location services dialog (i.e. IsGeolocationEnabled == false) versus the user said no to the location services dialog (also IsGeolocationEnabled == false). Any suggestions?
The way this type of permission request occurs on iOS is through an asynchronous dialog prompt, which is only shown if needed (and not until it is needed). Basically, you need to set up a callback from the CLLocation API. I have a helper class that I use for this purpose, which makes it even easier. Just call GetCurrentDeviceLocation() and pass it a callback function. The callback will only be invoked once the user has granted permission to the app, or if they previously granted permission:
public class GeoLocationService
{
readonly CLLocationManager _locationManager;
WeakReference<Action<Position>> _callback;
public GeoLocationService()
{
_locationManager = new CLLocationManager ();
_locationManager.AuthorizationChanged += AuthorizationChanged;
}
void AuthorizationChanged (object sender, CLAuthorizationChangedEventArgs e)
{
Action<Position> callback;
if (_callback == null || !_callback.TryGetTarget (out callback)) {
return;
}
if (IsAuthorized(e.Status)) {
var loc = _locationManager.Location;
var pos = new Position(loc.Coordinate.Latitude, loc.Coordinate.Longitude);
callback (pos);
}
}
static bool IsAuthorized(CLAuthorizationStatus status)
{
return
status == CLAuthorizationStatus.Authorized
|| status == CLAuthorizationStatus.AuthorizedAlways
|| status == CLAuthorizationStatus.AuthorizedWhenInUse;
}
public void GetCurrentDeviceLocation (Action<Position> callback)
{
_callback = new WeakReference<Action<Position>> (callback);
if (UIDevice.CurrentDevice.CheckSystemVersion (8, 0)) {
if (_locationManager.Location == null) {
_locationManager.RequestWhenInUseAuthorization ();
return;
}
}
AuthorizationChanged (null, new CLAuthorizationChangedEventArgs (CLAuthorizationStatus.Authorized));
}
}

Shiro / Vaadin loses session at page reload

I added Shiro session management (based on Kim's and Leif's webinar) to the Vaadin quick ticket dashboard demo application. When I do a browser reload in the application I get thrown back to the login page with no session. How / where can I prevent this.
I have a standard shiro.ini setup
Login button handler:
signin.addClickListener(new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
boolean loginOK = false;
Factory<SecurityManager> factory =
new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager((org.apache.shiro.mgt.SecurityManager)
securityManager);
Subject currentUser = SecurityUtils.getSubject();
//collect user principals and credentials in a gui specific manner
//such as username/password html form, X509 certificate, OpenID, etc.
//We'll use the username/password example here since it is the most common.
UsernamePasswordToken token =
new UsernamePasswordToken(username.getValue(), password.getValue());
//this is all you have to do to support 'remember me' (no config - built in!):
token.setRememberMe(true);
//currentUser.login(token);
try {
logger.log(Level.INFO, "trying login");
currentUser.login( token );
logger.log(Level.INFO, "login done");
//if no exception, that's it, we're done!
} catch ( Exception e ) {
logger.log(Level.INFO, "exception");
}
if ( currentUser.hasRole( "schwartz" ) ) {
loginOK = true;
} else {
loginOK = false;
}
if (loginOK) {
signin.removeShortcutListener(enter);
buildMainView();
} else {
if (loginPanel.getComponentCount() > 2) {
// Remove the previous error message
loginPanel.removeComponent(loginPanel.getComponent(2));
}
// Add new error message
Label error = new Label(
"Wrong username or password. <span>Hint: try empty values</span>",
ContentMode.HTML);
error.addStyleName("error");
error.setSizeUndefined();
error.addStyleName("light");
// Add animation
error.addStyleName("v-animate-reveal");
loginPanel.addComponent(error);
username.focus();
}
}
});
Use #preserveonRefresh annotation in UI init class
I recommend using Shiro's web filter. This way, your session will not be lost and you can prohibit unauthorized actions (e.g. Instantiating view objects) easily since Shiro's context is already set up when you display the login or any other view.

Resources