Cannot get network location from BB10 device - geolocation

I am porting an Android app to BlackBerry 10 OS using the Java Runtime support. My app is working fine on Android devices currently, but I cannot get location updates from the BlackBerry device.
My manifest requests the COARSE_LOCATION permission:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
In my code, I request location updates from an Activity:
LocationListener listener = new LocationListener()
{
public void onLocationChanged(Location location)
{
Log.v(TAG, "onLocationChanged");
// Code to save returned location...
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
LocationManager lm = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener);
Log.v(TAG, "Registered network location listeners");
I see the "registered listeners" log line printed from the device, but I never see "onLocationChanged" get logged, and my code that saves the supplied location is never invoked.
In some other place, I try to fetch the last known location:
LocationManager lm = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
Location lastLocation = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
lastLocation is always null.
To be clear, this code works fine on Android devices and is well tested.
Also relevant: the BB10 device reports that my app has the GPS location permission, but not the regular location permission, even though my manifest requests COARSE_LOCATION only. Might be related?
UPDATE:
I have an open ticket with BlackBerry Support. They say "This is a known issue it is in the process of being fixed with internal development."

Do you have read geo location permission set in your bar descriptor xml file ?
http://developer.blackberry.com/air/documentation/bb10/r_barfile_dtd_ref_permission.html

The problem was in the BlackBerry Android runtime. It has been fixed in OS 10.1.
The support ticket is here (now closed): https://www.blackberry.com/jira/browse/BBTEN-999
See this forum thread also: http://supportforums.blackberry.com/t5/Android-Runtime-Development/Can-not-fetch-location-using-network-provider/m-p/2424553#M5040

Related

Oauth2 flow in Flutter app

In the Flutter app I'm currently building, I need to authenticate users against a custom (so non-Google/Facebook/Twitter/etc) authorization server.
In order to achieve this, the users should fill in their credentials in a webpage. To this purpose, the WebView-plugin can be used. However, when the page is redirected after the user authenticated, the WebView should be closed, and the code passed on to the (Flutter) function that initially called the WebView.
Having done some research already, I came accross the following options:
This blog post uses a local server, which still requires the user to manually close the window, which is not a real solution (in my opinion).
This issue marks integration with any OAuth provider as done, but does not provide any details on the user authentication inside the browser.
This issue is exactly like I am describing, but at the bottom it is mentioned that the WebView plugin provides a way to close the WebView. While it does indeed have a close()-function, I cannot find a way to trigger it on the redirect-URI and return the verification code.
Does a solution exist, that closes the browser automatically once the redirect-URI is opened (and also returns the verification code)?
Thanks in advance!
I haven't tried this, but my idea is to use FlutterWebviewPlugin to send the user to a URL like https://www.facebook.com/v2.8/dialog/oauth?client_id={app-id}&redirect_uri=fbAPP_ID://authorize. Then add native handlers for application:openURL:options: (on iOS) and onNewIntent (Android) and modify AndroidManifest.xml and Info.plist to register the app to receive URLs from the fbAPP_ID scheme. You can use the platform channels to pass the deep link parameters back to Dart-land and call close() on the webview on the Dart side.
On request of #Igor, I'll post the code we used to solve this.
The idea is based both on the answer of #CollinJackson, and on how the AppAuth library does the same thing. Note: I don't have the iOS code here, but the code should be pretty trivial to anyone who regularly does iOS development.
Android-specific code
First, create a new Activity, and register it in the manifest to receive the URIs:
<activity
android:name=".UriReceiverActivity"
android:parentActivityName=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="organization" android:host="login.oauth2" />
<!-- Triggering URI would be organization://login.oauth2 -->
</intent-filter>
</activity>
In your Java-code, by default, there is one Activity (MainActivity).
Start a new MethodChannel in this activity:
public class MainActivity extends FlutterActivity implements MethodChannel.MethodCallHandler {
private static final String CHANNEL_NAME = "organization/oauth2";
public static MethodChannel channel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
channel = new MethodChannel(getFlutterView(), CHANNEL_NAME);
channel.setMethodCallHandler(this);
}
}
Note that this code is incomplete, since we also handle calls from this. Just implemented this method, and the method calls you might add. For example, we launch Chrome custom tabs using this channel. However, to get keys back to Dart-land, this is not necessary (just implement the method).
Since the channel is public, we can call it in our UriReceiverActivity:
public class UriReceiverActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Uri data = getIntent().getData();
Map<String, Object> map = new HashMap<>();
map.put("URL", data.toString());
MainActivity.channel.invokeMethod("onURL", map);
// Now that all data has been sent back to Dart-land, we should re-open the Flutter
// activity. Due to the manifest-setting of the MainActivity ("singleTop), only a single
// instance will exist, popping the old one back up and destroying the preceding
// activities on the backstack, such as the custom tab.
// Flags taken from how the AppAuth-library accomplishes the same thing
Intent mainIntent = new Intent(this, MainActivity.class);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(mainIntent);
finish();
}
}
This is heavily inspired by this code.
Now, the Flutter app is re-opened, and the URL (with token) is sent back to Dart-land.
Flutter code
In Dart, we have a singleton listening in on the channel (I'll only post fragments of the code, since it's not that nice and quite scattered around the file):
// Member declaration
_platform = const MethodChannel('organization/oauth2');
// Instantiation in constructor
_platform.setMethodCallHandler(_handleMessages);
// Actual message handler:
void _handleMessages(MethodCall call) {
switch (call.method) {
case "onURL":
// Do something nice using call.arguments["URL"]
}
}
On iOS, do the same as on Android, by sending the URL down the channel with that name and under the same command. The Dart code then doesn't need any changes.
As for launching the browser, we just use the url_launcher plugin. Note that we are not restricted to using a WebView, we can use any browser on the device.
Note that there are probably easier ways to do this, but since we had to make this quite early in Flutter's alpha, we couldn't look at other implementations. I should probably simplify it at some stage, but we haven't found time for that yet.

Azure mobileServiceClient InvokeApiAsync never returns in my Xamarin iOS app

I am using the Azure MobilServiceClient to call my custom controller and method and it just never returns. Using the same code in my Test project works just fine, but in my iOS app it just goes silent. Hanging the app.
I call it like this:
var parameters = new Dictionary<string, string> { { "loginProvider", loginProvider }, { "providerKey", providerKey } };
var result = await App.MobileService.InvokeApiAsync<AuthResult>("Auth", HttpMethod.Get, parameters);
I can look in the Azure Log Stream and see that the call is received as expected. Looking the same both from my test project and the App project. No errors.
What else can I try? Where else can I look?
I tried putting the same code piece into the sample code I can download from the Azure portal and it goes silent just like my own app.
Thanks
Found the source of my problems: async deadlock.
I moved out my async api calls from the PCL app constructor and configured my calls with
.ConfigureAwait (false)

Invoking access prompt and show it to the user

A little background:
I developed a game in Libgdx and upload it to iTunes app store. My app got rejected with a following reason: (This is not the question but I would like to give you a little background of what I am trying to achieve)
> 17.1 Details
Additionally, we noticed that your app does not obtain user consent before collecting the user's personal data.
Specifically, users scores are posted to a high score feature. Please see the attached screenshot(s) for additional information.
Next Steps
To collect personal data with your app, you must make it clear to the user that their personal data will be uploaded to your server and you must obtain the user's consent before the data is uploaded.
- Starting with iOS 6, there are keys for specifying the reason the app will access the user's protected data. When the access prompt is displayed, the purpose specified in these keys is displayed in that dialog box. If your application will be transmitting protected user data, the usage string in your access request should clearly inform the user that their data will be uploaded to your server if they consent.
My app only upload high score to my server. But okay if Apple states that the user should know about this I will make it clear.
Actual mission:
I dont know anything about objective-c programming since I made this app in Java. But I know that iOS have some security dialogs which prompts the user if they are Okay to use the following feature or data in the app.
I would like to invoke this kind of dialog (with my own message)
I also know that it should be defined in my info.plist file, but I dont know how to access it at runtime and show it in my game.
Does somebody have a clue how to open this up?
You could try my libgdx extension for dialog windows: https://github.com/TomGrill/gdx-dialogs
or:
You need to interface with platform specifig code: https://github.com/libgdx/libgdx/wiki/Interfacing-with-platform-specific-code
Use UIAlertView class in your iOS interface implementation to open an AlertView:
Code example:
UIAlertViewDelegateAdapter delegate = new UIAlertViewDelegateAdapter() {
#Override
public void didDismiss(UIAlertView alertView, long buttonIndex) {
//handle button click based on buttonIndex
}
#Override
public void clicked(UIAlertView alertView, long buttonIndex) {
}
#Override
public void cancel(UIAlertView alertView) {
}
#Override
public void willPresent(UIAlertView alertView) {
}
#Override
public void didPresent(UIAlertView alertView) {
}
#Override
public void willDismiss(UIAlertView alertView, long buttonIndex) {
}
#Override
public boolean shouldEnableFirstOtherButton(UIAlertView alertView) {
return false;
}
};
String[] otherButtons = new String[1];
otherButtons[0] = "No";
String firstButton = "Yes";
UIAlertView alertView = new UIAlertView("Title", "message", delegate, firstButton, otherButtons);
alertView.show();

Deny the location permission and later grant the location for xamarin iOS 8 application return always false

I am working in a iOS/xamarin app. (iOS 8).
I was using this tutorial to know the user location:
http://www.themethodology.net/2014/10/getting-permission-to-access-user.html
And the follow codes works to know if the uses has the location services enabled and if the applications is authorized to use the location.
CLLocationManager clm = new CLLocationManager ();
public bool LocationServicesEnabled {
get {return CLLocationManager.LocationServicesEnabled;}
}
public bool IsAuthorized {
get {return CLAuthorizationStatus.Authorized == _authstatusLast;}
}
But, if the user select the first time: Don't allow, after that, he changes the permission in:
Privacy >> Location >> MyApp >> ON
The IsAuthorized method is always false.
Someone has an idea about how solve this issue?
I found the way to know if the application has permission to use the location services (Not if the service is enabled).
public bool IsAuthorized {
get {return CLLocationManager.Status == CLAuthorizationStatus.AuthorizedWhenInUse ;}
}
You can use CLAuthorizationStatus.AuthorizedWhenInUse when the app is using AuthorizeWhenIsInUser and if you are using AuthorizedAlways you need change that in the CLAutorizationStatus.
Also, is necessary for iOS 8 modify the keys in your plist file:
More information about the plist here.
http://www.themethodology.net/2014/10/getting-permission-to-access-user.html

Obtaining cellsite gps location on Blackberry Curve 8520

Details of my phone:
Model:Blackberry Curve 8520
Version :5.0.0.1036
data services :on
When I am installing google maps I am able to see the location ,so there is a chance of obtaining the current location using this phone.
I am trying to develop an application which will show the current location of the phone,by using the cell site locations because this phone model does not have an in-built GPS device.
I am using the following code:
BlackBerryCriteria bc=new BlackBerryCriteria(GPSInfo. GPS_MODE_CELLSITE );
try {
LocationProvider lp=LocationProvider.getInstance(bc);
if(lp !=null)
{
Location loc=lp.getLocation(-1);
add (new EditField(loc.getQualifiedCoordinates().getLatitude()+"\n"+loc.getQualifiedCoordinates().getLongitude(),""));
}
else
{
add(new EditField("unable to find the location provider", ""));
}
} catch (LocationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}}
I am installing the alx file on the bb phone using desktop manager.
On starting the application it is giving me an Uncaught exception:
NET.RIM.DEVICE.API.SYSTEM.UNSupportedOperationException.
The device might currently not support GPS_MODE_CELLSITE. Check using
GPSInfo.isGPSModeAvailable(GPS_MODE_CELLSITE)
and use another mode if neccessary.
It might not support GPS_MODE_CELLSITE because:
There is no valid SIM card in your phone (ok, i assume you have one :)
Check if your device and carrier have available GPS mode you are using (here)
If your carrier is Verizone, check for Verizon GPSSettings signing requirement
Your APN settings are not correct (Options > Device > Advanced Settings > TCP IP)
You don't have a BlackBerry Service Plan (not too sure about that one)

Resources