Titanium Android retrieve intent extras through notification - titanium-mobile

I have a background service that I start as soon as the app is lunched. This background service asks to the server every 5 seconds if there are new data available, as soon as there are new data I create a notification. When I click the notification app is lunched, but I am not able to retrieve the intent extra parameters that I put when I create the notification.
Below the code:
index.js
startService();
function startService(){
if(OS_ANDROID){
log("START SERVICE");
var intent = Titanium.Android.createServiceIntent({
url: 'service.js'
});
Titanium.Android.startService(intent);
}
}
//===========================================
// I tried to add this code so that I could get the intent but it does not work
if(OS_ANDROID){
log("==========================" + JSON.stringify(Ti.Android.currentActivity));
// prints : {"bubbleParent":true,"actionBar":{"navigationMode":0,"bubbleParent":true,"title":null,"apiName":"Ti.Android.ActionBar"},"apiName":"Ti.Android.Activity"}
var _intent = Ti.Android.currentActivity.getIntent();
log(JSON.stringify(_intent));
//prints {"bubbleParent":true,"action":null,"type":null,"data":null,"flags":268435456,"apiName":"Ti.Android.Intent"}
if (_intent.hasExtra('ntfId')) {
log("========= INTENT HAS EXTRA =========");
}else{
log("========= NO INTENT HAS EXTRA =========");
}
var currActivity = Titanium.Android.currentActivity;
var passedInText = currActivity.getIntent().getStringExtra(Ti.Android.EXTRA_TEXT);
log(passedInText);
//prints null
}
service.js
function createNotification(data){
log(data.id + " <<<<<<>>>>>> " + data.type);
var activity = Ti.Android.currentActivity;
var intent = Ti.Android.createIntent({
className : 'packageName.AppNameActivity',
action: Ti.Android.ACTION_MAIN,
packageName: Ti.App.id,
flags: Ti.Android.FLAG_ACTIVITY_NEW_TASK | Ti.Android.FLAG_ACTIVITY_SINGLE_TOP
});
intent.addCategory(Titanium.Android.CATEGORY_LAUNCHER);
intent.putExtra("ntfId", data.id);
var pending = Ti.Android.createPendingIntent({
intent : intent
});
var notification = Ti.Android.createNotification({
contentIntent : pending,
contentTitle : data.title,
contentText : data.desription,
tickerText : "AppName",
icon : Ti.App.Android.R.drawable.appicon,
sound: 'default',
defaults: Titanium.Android.NotificationManager.DEFAULT_VIBRATE,
flags : Titanium.Android.ACTION_DEFAULT | Titanium.Android.FLAG_AUTO_CANCEL | Titanium.Android.FLAG_SHOW_LIGHTS
});
Ti.Android.NotificationManager.notify(data.notification_id, notification);
}
I want to get "ntfId" when my app opens, so I can know which notification I clicked and show the correct data.
What I have found so far with the notifications is just how to lunch the application, and that does work but there is no clear example how to get notification detail.
I followed this link and docs , but I'm using Alloy model.
In case it is useful, I'll add my TiApp.xml too:
<android xmlns:android="http://schemas.android.com/apk/res/android">
<manifest>
<uses-permission android:name="android.permission.VIBRATE"/>
<application android:debuggable="true">
<activity
android:configChanges="keyboardHidden|orientation"
android:name="org.appcelerator.titanium.TiActivity"
android:screenOrientation="portrait"/>
<activity
android:configChanges="keyboardHidden|orientation"
android:label="Appname"
android:launchMode="singleTask"
android:name=".AppnameActivity"
android:screenOrientation="portrait" android:theme="#style/Theme.Titanium">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
<services>
<service url="service.js"/>
</services>
</android>
How do I get the extra parameters passed from the notification intent? Seems like when I do getCurrentActivity.getIntent() it's another intent totally different from what I want to get.
Can you suggest me something or point somewhere that maybe I missed looking at?
Thanks!
Last Edit
I pushed my project on gihub, TiAndroidNotification you can clone it and try, and see if you can change something.. It's not working yet, I'm still working on trying to solve this problem..
Thanks for any help or feedback!

I figure half of it out.
When the pending intent is created we should add even the activity:
var activity = Ti.Android.currentActivity;
var pending = Ti.Android.createPendingIntent({
activity:activity,
intent : intent
});
and from index.js I get it like this:
var act = Titanium.Android.currentActivity;
var _intent = act.intent;
var message = _intent.getStringExtra("ntfId");
This works ok as long as I close the application, but if the application is just in background and I click the notification it passes null and I do not understand why..

i've replaced the flags with Ti.Android.FLAG_ACTIVITY_NEW_TASK | Ti.Android.FLAG_ACTIVITY_MULTIPLE_TASK and it's working perfectly. It restarts the app, but it works.
and also you forgot to add "type : Titanium.Android.PENDING_INTENT_FOR_ACTIVITY" to pending.

here the js module I'm using
https://gist.github.com/muka/d4afae20a5732f3937e8
Seems responding properly when app is in background or foreground
Basically, the main activity listen to the newintent event and look for expected data in the intent extras received as argument
I'm curious to see if it works for different use cases, let me know.
Thanks

Related

Xamarin Forms using FirebasePushNotificationPlugin plugin with Autofac and Shell unable to display UI elements nor redirects

I'm experiencing an issue that I've tried different ways to resolve and have been unsuccessful with. Whenever receiving a message via CrossFirebasePushNotification.Current.OnNotificationReceived I get the payload and can read it, but I can't do anything "visual" in my app. In other words, I get the notification but when I want to either redirect to another page or even display a DisplayAlert message, nothing happens. MessagingCenter can be received, but any instructions within the procedure that have to do with redirecting or DisplayAlert (anything changing the UI it appears) will not be executed.
Looking for help in how to visually show in the app the user has received a message.
This is in MainShell.xaml.cs (I've also placed it in App.xaml.cs too):
CrossFirebasePushNotification.Current.OnNotificationReceived += (s, p) =>
{
System.Diagnostics.Debug.WriteLine("Received"); // this works
foreach (var data in p.Data)
{
System.Diagnostics.Debug.WriteLine($"{data.Key} : {data.Value}"); // this works
}
//TODO: Code to determine if user is signed in
if (true)
{
System.Diagnostics.Debug.WriteLine("Debug: Goto Registration page from MainShell"); // this works
//Task.Run(async () => await Shell.Current.GoToAsync("registration")); // this does not work (just ignores it and doesn't fire constructor)
//Task.Run(async () => await Current.DisplayAlert("Request Received", "A message is waiting...", "Ok")); // this does not work
MessagingCenter.Send(this, "RequestReceived"); // this works, the receiver will display debug info, but will not redirect nor display any UI messages or interact with the UI.
}
};
Thank you for any help or guidance,
Robert

Xamarin.Android Camera2 API Camera don`t appears in default apps

I downloaded the sample Сamera2 API code to my device. In another app, I want to launch a third-party camera, but I can't select the one I downloaded.
I Found solution for Xamarin.Android. I added above my CameraActivity page right near that Manifest String
[Activity (Label = "Camera2Basic", MainLauncher = true, Icon = "#drawable/icon")]
my Intent Filter which contains this code
[IntentFilter(new[] { "android.media.action.IMAGE_CAPTURE" },
Categories = new[] { Intent.CategoryDefault})]
This code write strings in Manifest, they needs for default intent call

Firefox WebExtension notifications API: How to call a function when the notification is clicked

I'm trying to develop a Firefox add on using WebExtensions. What I'm trying to do is open a new Firefox tab or window when the user clicks the notification. But it doesn't work.
When I click the notification, nothing happens.
I'm creating notifications like:
var q = chrome.notifications.create({
"type": "basic",
"iconUrl": chrome.extension.getURL("128-128q.png"),
"title": 'title',
"message": 'content'
});
chrome.notifications.onClicked.addListener(function(notificationId) {
window.open('http://www.google.com');
});
browser.notifications.onClicked.addListener(function(notificationId) {
window.open('http://www.google.com');
});
q.onClicked.addListener(function(notificationId) {
window.open('http://www.google.com');
});
var audio = new Audio('message.mp3');
audio.play();
How can I make this work?
It appears that the problem is that you are attempting to open a new URL in a way that does not work.
The following should work, using chrome.tabs.create():
var q = chrome.notifications.create("MyExtensionNotificationId", {
"type": "basic",
"iconUrl": chrome.extension.getURL("128-128q.png"),
"title": 'title',
"message": 'content'
});
chrome.notifications.onClicked.addListener(function(notificationId) {
chrome.tabs.create({url:"http://www.google.com"});
});
However, you need to be testing this in Firefox 47.0+ as support for chrome.notifications.onClicked() was only added recently. My statement of Firefox 47.0+ is based on the compatibility table. However, the compatibility table has at least one definite error. Thus, a higher version of Firefox may be required. The code I tested worked in Firefox Nightly, version 50.0a1, but did not work properly in Firefox Developer Edition, version 48.0a2. In general, given that the WebExtensions API is in active development, you should be testing against Firefox Nightly if you have questions/issues which are not functioning as you expect. You can also check the source code for the API to see what really is implemented and when it was added.
Note: this works with either chrome.notifications.onClicked or browser.notifications.onClicked. However, don't use both to add two separate anonymous functions which do the same thing as doing so will result in whatever you are doing happening twice.
I did not actually test it with your code, but I did test it with a modified version of the notify-link-clicks-i18n WebExtensions example. I modified the background-script.js file from that example to be:
/*
Log that we received the message.
Then display a notification. The notification contains the URL,
which we read from the message.
*/
function notify(message) {
console.log("notify-link-clicks-i18n: background script received message");
var title = chrome.i18n.getMessage("notificationTitle");
var content = chrome.i18n.getMessage("notificationContent", message.url);
let id = "notify-link-clicks-i18n::" + title + "::" + message.url;
chrome.notifications.create(id,{
"type": "basic",
"iconUrl": chrome.extension.getURL("icons/link-48.png"),
"title": title,
"message": content
});
}
/*
Assign `notify()` as a listener to messages from the content script.
*/
chrome.runtime.onMessage.addListener(notify);
//Add the listener for clicks on a notification:
chrome.notifications.onClicked.addListener(function(notificationId) {
console.log("Caught notification onClicked with ID:" + notificationId);
//Open a new tab with the desired URL:
browser.tabs.create({url:"http://www.google.com"});
});
My preference for something like this where a unique ID is possible is to provide a unique ID, that both identifies that the notification was displayed by my add-on and what the notification was. This allows the listener function to choose to only act on notifications which were displayed by my add-on and/or only a subset of those I display, or have different actions based on why I displayed the notification.
The reason you had trouble here in figuring out what was not working is probably because you did not reduce the issue to the minimum necessary to demonstrate the issue. In other words, it would have been a good idea to just try opening a new URL separately from the notifications onClicked listener and just try a console.log() within the listener.

Windows 8 tile notification from localhost

I am developing a simple app for windows 8. In My app I want the start tile to show images from local host that I ship with my app.
for example I have kept my images on /images/tile1.jpg like wise.
and my xml code is
<tile>
<visual>
<binding template="TileWideImage">
<image id="1" src ="http://localhost/images/tile1.jpg" />
</binding>
</visual>
which is present at /tile1.xml likewise
and my default.js code is
// For an introduction to the Blank template, see the following documentation:
// http://go.microsoft.com/fwlink/?LinkId=232509
(function () {
"use strict";
WinJS.Binding.optimizeBindingReferences = true;
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
app.onactivated = function (args) {
if (args.detail.kind === activation.ActivationKind.launch) {
if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
var notifications = Windows.UI.Notifications;
var recurrence = notifications.PeriodicUpdateRecurrence.halfHour;
var urls = [
new Windows.Foundation.Uri("http://localhost/tile1.xml"),
new Windows.Foundation.Uri("http://localhost/tile2.xml"),
new Windows.Foundation.Uri("http://localhost/tile3.xml"),
new Windows.Foundation.Uri("http://localhost/tile4.xml")
];
notifications.TileUpdateManager.createTileUpdaterForApplication().enableNotificationQueue(true);
notifications.TileUpdateManager.createTileUpdaterForApplication().startPeriodicUpdateBatch(urls, recurrence);
} else {
// TODO: This application has been reactivated from suspension.
// Restore application state here.
}
args.setPromise(WinJS.UI.processAll());
}
};
app.oncheckpoint = function (args) {
// TODO: This application is about to be suspended. Save any state
// that needs to persist across suspensions here. You might use the
// WinJS.Application.sessionState object, which is automatically
// saved and restored across suspension. If you need to complete an
// asynchronous operation before your application is suspended, call
// args.setPromise().
};
app.start();
})();
I am just unable to figure out what's wrong with the code. Please help.
Well, you can't. Loopback is not permitted, so your app won't pass certification if you're using a localhost service.
Can you deliver the images with the app itself? Alternatively, set up an external service to host your images and tiles. You really only need something like Windows Azure blob storage, don't even need to host a web service.
Lastly, you'll want to make sure you ALWAYS include a square tile image. The user always has control, so they may choose not to display your app as a wide tile.

How can I dynamically change kendo.mobile.Application's loading property?

I am developing a mobile web app using Kendo UI Mobile. Whenever we make any AJAX calls, or our DataSources make them we call app.startLoading() to show the loading icon to the user. This works very well.
However, depending on the context in which the call is made we would like to change the text that is displayed along with the loading icon. I know you can define this when I create the kendo.mobile.Application instance. How can I change it afterwards?
The documentation does not suggest a way to do this, and a browse of the source code did not help me either. Is this really not possible?
EDIT: This is using Kendo UI Mobile v.2012.3.1114
I usually make a "utility" function to do this:
var _kendoApp = new kendo.mobile.Application(document.body, {});
var showLoading = function (message) {
_kendoApp.loading = "<h1>" + (message ? message : "Loading...") + "</h1>";
_kendoApp.showLoading();
};
I am also setting a default message of "Loading..." if one isn't passed in.
Edit:
I could have sworn that worked for me in a past app I did, but judging by thr source, I think you are right, my answer above shouldn't work. My best suggestion is to add a class to the message element so you can target it, and use jQuery to change the text.
var _kendoApp;
var showLoading = function (message) {
$(".loading-message").text(message ? message : "Loading...");
_kendoApp.showLoading();
};
_kendoApp = new kendo.mobile.Application(document.body, {
loading: '<h1 class="loading-message">Loading...</h1>'
});

Resources