launch Blackberry app from link in mail - blackberry

I can not be more clear with the title :D
Is it possible? to launch an application on a blackbeery just cliking on a "link" inside a mail? i read about taping a url and going to the application but this is much more specific.
thx in advance

Actually you can listen incoming emails.
You can implement menu item that will be available in mail app.
But you can also implement content handler with specific URI to launch your app.
All examples are available in BB samples.

Look in the RIM sample apps, more specifically HTTPFilterDemo.
You have to register a filter for the type of link you need the app to be triggered by (you'll need to put this code in the main method of you app):
HttpFilterRegistry.registerFilter("www.rim.com","com.rim.samples.device.httpfilterdemo.filter");
where "www.rim.com" is obviously the link that should open the app and the second parameter is the package that contains the "Protocol" class. The Protocol class has a callback method:
public Connection openFilter( String name, int mode, boolean timeouts ) throws IOException {
This method will be called each time the user clicks on a link that has the form specified by you. So, to open the app, in the "openFilter" method, do:
int modHandle = CodeModuleManager.getModuleHandle("YourAppModuleName");
ApplicationDescriptor[] apDes = CodeModuleManager.getApplicationDescriptors(modHandle);
try {
ApplicationManager.getApplicationManager().runApplication(apDes[0]);
} catch (ApplicationManagerException e) {
e.printStackTrace();
}

Related

How to close browser tab with Xamarin.Android?

So, I wrote a Nuget that allows dev in my company to quickly setup authorization using OIDC. Part of that, of course, is handing off the authentication step to a browser so I'm simply invoking Browse.OpenAsync with LaunchMode = BrowserLaunchMode.SystemPreferred. I also set up a HTTP listener that awaits the ahtority's authorization code callback. All works find but the browser window is of course still sitting at the top, hiding the initiating app.
I do realise I can use deep linking to simply "call up" the app again but that has two implications I would like to avoid: The need to register custom URI schema with the mobile OS and, above all, the need to register that (custom) callback URI with my company's API management system (which doesn't like anything but "http" or "https" URI schemes). Those requirements makes it more complicated for our devs to get started and, like I mentioned, it doesn't work very well with our API management system, so I'm looking for a simpler solution.
For iOS I can simply fetch the key window's view controller and dismiss it, like so:
async Task<Outcome> IPlatformService.TryCloseTopWindowAsync(bool isModalWindow, bool animated)
{
var window = UIApplication.SharedApplication.KeyWindow;
var viewController = window?.RootViewController;
if (viewController is null)
return Outcome.Fail("Couldn't obtain top window view controller");
try
{
if (isModalWindow)
{
viewController.DismissModalViewController(animated);
return Outcome.Success();
}
await viewController.DismissViewControllerAsync(animated);
return Outcome.Success();
}
catch (Exception ex)
{
return Outcome.Fail(ex);
}
}
Unfortunately, I'm not very good with Android's (Java based) APIs so I'm wondering if it's possible to do something similar here? Can I get the top app (activated by my own app) and dismiss it? If so; how?

How to handle custom URL scheme in Xamarin Forms

I have a Xamarin Forms Shell app but I'm focusing on the ios platform at the moment.
Example custom url: myawesomeapp:report?id=22
On iOS, I have added the custom URL scheme 'myawesomeapp' to info.plist. And now clicking on the custom url brings up my app successfully and OpenUrl in AppDelegate gets hit.
But how can I process the id=22 to take me to that particular record?
My app structure is using AppShell. I have an ItemsPage.xaml that lists reports and selecting one will bring up that report on ItemDetailPage.xaml. This is the flow that I want to simulate when following the custom url.
Thanks in advance.
Ideal approach would be to create a method in your App.xaml.cs which will accept the given query and then you can call that method from the OpenUrl.
Here's the example:
App.xaml.cs
public void ParseAndPerformNavigation(string query)
{
//Do string operation and get the parameter
//Perform Navigation
}
Your updated OpenUrl should be something like this:
public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{
var App = (App)Xamarin.Forms.Application.Current;
App.ParseAndPerformNavigation(url.AbsoluteString);
return false;
}

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.

Is there a Lync API for creating add-ons that run as soon as the user signs into Lync?

I can see custom menu items and custom conversation windows and events inside them but nothing referring to how you'd execute code once a user signs into Lync. Does such an API exist?
I guess my alternative would be creating a Lync Automation object/my own client using the Suppressed ui and building whatever features I want into one of those?
There's nothing you can build into the Lync application, but you could run a separate application which can subscribe to the SignIn state of the user. That way, you'd know when a user signs-in, and could take appropriate action. You wouldn't need to create a SuppressedUI application for that, just something that ran in the background, or taskbar or something.
Here's a bare bones example:
namespace ThoughtStuff
{
class Program
{
static void Main(string[] args)
{
var client = LyncClient.GetClient();
client.StateChanged += client_StateChanged;
}
static void client_StateChanged(object sender, ClientStateChangedEventArgs e)
{
if (e.NewState == ClientState.SignedIn)
{
//do something on sign in
}
}
}
}
You might get errors if you try and attach to Lync in the SDK code using LyncClient.GetClient() if the Lync exe isn't running...but if you know that's likely to be a problem (such as if your application might be running before the user starts Lync), then you can gracefully handle it and retry in code.

Authenticating via oAUTH with providers using Phonegap for Blackberry

We are currently working on the finishing touches of an application which uses Phonegap and have hit some issues with the Blackberry port.
So far, we've been reviewing the content available online and can't find a really finale answer to this. Seems like the "right" way to make and oauth authentication process for either Twitter, Facebook or Foursquare would be to use the ChildBrowser plugin, instantiate a window and then use that to handle the process.
Rightly so, there seems to be a lack of a ChildBrowser plugin for Blackberry. We've been looking so far at a couple of private projects on Github that look like they build/use that capability but we are not sure on how to control the created window.
Most (or all?) of those plugins refer to invoking the native Blackberry browser to handle the URLS, but then how would be manage to work on the callbacks, get the tokens and close the windows since it's another process.
For example, we have this concept code:
function openWindow() {
if (typeof blackberry !== 'undefined') {
app_id = SOMETHING_HERE;
redirect = 'http://www.facebook.com/connect/login_success.html';
url = 'https://graph.facebook.com/oauth/authorizeclient_id='+app_id+'&redirect_uri='+redirect+'&display=touch&scope=publish_stream';
var args = new blackberry.invoke.BrowserArguments(url);
blackberry.invoke.invoke(blackberry.invoke.APP_BROWSER, args);
}
}
Which works for opening the URL, but that's it. Is there a way to get a handle on the window and inject some listener to events? What should be our correct approach?
Thanks!
I am not PhoneGap user, but we did have to handle a very similar scenario - native app invokes the mobile browser to prompt the oAuth flow and then be able to handle a callback to the aative app.
This is possible on the BlackBerry using the BrowserContentProviderRegistry API. You can register your app to be invoked whenever a particular MIME type is returned to the browser. Sounds complicated but its fairly straightforward when all the pieces are in play.
Here is the rough flow -
Native app invokes browser to the oAuth page. This is part is easy and seems like you got this part.
The oAuth redirect needs to go to a URL that you can control. Something like http://mycompany.com/oAuthRedirectHandler.asp.
The oAuthRedirectorHandler.asp has simple code like this (we chose classic ASP but this can be done in PHP or any language, you can also ignore the Android block below) -
<html><body>
<h1>Redirect page</h1>
If you are not re-directed, please open the application manually.
<% strUA = Request.ServerVariables("HTTP_USER_AGENT")
if (InStr(strUA, "BlackBerry")) then
Response.Write("Opening appplication on BlackBerry")
Response.ContentType="application/x-MyCustomApp"
elseif (InStr(strUA, "Android")) then
Response.Write("Opening appplication on Android")
Response.Redirect("MyCustomApp://mycompany.com")
end if %>
</body> </html>
In your BlackBerry code you want a new BrowserContentProvider like this -
final class CustomBrowserProvider extends BrowserContentProvider{
String[] ACCEPT = new String[]{"application/x-MyCustomApp};
String appName;
CustomBrowserProvider(String appName){
this.appName = ApplicationDescriptor.currentApplicationDescriptor().getModuleName();
//cache this appName from the constructor in the invocation code below.
}
public String[] getSupportedMimeTypes() { return ACCEPT;}
public String[] getAccept(RenderingOptions context){return ACCEPT;}
public BrowserContent getBrowserContent( BrowserContentProviderContext context) throws RenderingException {
//this is where the callback happens
//this is happening in a separate process, raise your main app here using the appName that got passed in
//I dont have a sanitized ready to go sample to post here on how to do this, but not too complicated
//as a hint use the ApplicationDescriptor and CodeModuleManager classes
return null;
}
}
Now, in your application initialization, register this new BrowserPlugin like this -
BrowserContentProviderRegistry converterRegistry = BrowserContentProviderRegistry.getInstance();
converterRegistry.register(new CustomBrowserProvider());
Hope this helps. This has worked pretty well for us. The one downside we've had here is that when the user returns to the browser app, they are left with an empty page and there is no good way to close that in the BB.

Resources