I am using a custom folder in the Messagelist to display when my application gets new message.
Each message contains the title "New information received".
Right now, when the message is clicked it opens a new email compose window.
I have overridden ApplicationMessageFolderListener, but actionPerformed does not seem to be invoked when the message is clicked.
I want to launch my application when the user goes into the Messages application and clicks on my custom message. How do I achieve this?
Target platform: Blackberry 4.0 and above.
use the following code:
static class OpenContextMenu extends ApplicationMenuItem {
public OpenContextMenu( int order ) {
super( order );
}
public Object run( Object context ) {
if( context instanceof NewMessage ) {
try {
NewMessage message = (NewMessage) context;
if( message.isNew() ) {
message.markRead();
ApplicationMessageFolderRegistry reg = ApplicationMessageFolderRegistry.getInstance();
ApplicationMessageFolder folder = reg.getApplicationFolder( MessageList.INBOX_FOLDER_ID );
folder.fireElementUpdated( message, message );
//changeIndicator(-1);
}
Inbox inbox = message.getInbox();
Template template = inbox.getTemplate();
//Launch the mainscreen
UiApplication.getUiApplication().requestForeground();
}
catch (Exception ex) {
Dialog.alert();
}
}
return context;
}
public String toString() {
return "Name of the menu item";
}
}
Related
I wrote my own custom error handler for the UI in Vaadin flow. But when I throw the exception my view crash and not show my human readable error message.
I did this in other application using Vaadin 8 and works perfectly. The idea its throw a SgiException in my backend services like:
Product not found
Incorrect value for field "XXX"
Not available stock for the product.
etc.
And then show a system notification
public static void setDefaultErrorHandler(ErrorEvent errorEvent) {
Throwable t = DefaultErrorHandler.findRelevantThrowable(errorEvent.getThrowable());
String message;
if (t != null) {
message = t.getMessage();
} else {
message = "";
}
log.error(message, t);
SgiException sgiException = getCauseOfType(t, SgiException.class);
if (sgiException != null) {
NotificationBuilder.exception(sgiException.getCode(), sgiException.getMessage());
return;
} else {
NotificationBuilder.exception(UNKNOW_ERROR, (message == null ? "" : message));
return;
}
}
private static <T extends Throwable> T getCauseOfType(Throwable th, Class<T> type) {
while (th != null) {
if (type.isAssignableFrom(th.getClass())) {
return (T) th;
} else {
th = th.getCause();
}
}
return null;
}
And this is how I set the custom error handler:
#PostConstruct
public void configBaseView() {
VaadinSession.getCurrent().setErrorHandler(Util::setDefaultErrorHandler);
}
In the view show this:
Note:
Debugging the application, seeing the code it's running, looks the method its called for some reason not show the notification.
This is a nasty behaviour that can't currently be overridden in Vaadin 10. Follow and vote (thumb up or comment) this issue to get it solved: https://github.com/vaadin/flow/issues/801
I am working on an Android App using Xamarin, in which server sends an OTP and the user needs to enter this OTP in the App, to SignUp for my App. What I want is, that my App should be able to automatically read the OTP sent by the server and to be filled in edit text field of OTP.
I'm almost done to read the message but unable to set the otp in edit text field.
SMS broadcast receiver class:
[BroadcastReceiver(Enabled = true, Label = "SMS Receiver")]
[IntentFilter(new string[] { "android.provider.Telephony.SMS_RECEIVED" })]
public class SMSBroadcastReceiver : BroadcastReceiver
{
private const string IntentAction = "android.provider.Telephony.SMS_RECEIVED";
public override void OnReceive(Context context, Intent intent)
{
try
{
if (intent.Action != IntentAction) return;
var bundle = intent.Extras;
if (bundle == null) return;
var pdus = bundle.Get("pdus");
// var castedPdus = JNIEnv.GetArray(pdus.Handle);
var castedPdus = JNIEnv.GetArray<Java.Lang.Object>(pdus.Handle);
var msgs = new SmsMessage[castedPdus.Length];
var sb = new StringBuilder();
string sender = null;
for (var i = 0; i < msgs.Length; i++)
{
var bytes = new byte[JNIEnv.GetArrayLength(castedPdus[i].Handle)];
JNIEnv.CopyArray(castedPdus[i].Handle, bytes);
string format = bundle.GetString("format");
msgs[i] = SmsMessage.CreateFromPdu(bytes,format);
if (sender == null)
sender = msgs[i].OriginatingAddress;
sb.Append(string.Format("SMS From: {0}{1}Body: {2}{1}", msgs[i].OriginatingAddress,System.Environment.NewLine, msgs[i].MessageBody));
Toast.MakeText(context, sb.ToString(), ToastLength.Long).Show();
}
}
catch (System.Exception ex)
{
Toast.MakeText(context, ex.Message, ToastLength.Long).Show();
}
}
}
Here is my main activity:
[Activity(Label = "UserSms", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
SMSBroadcastReceiver smsReceiver = new SMSBroadcastReceiver();
TextView msg = FindViewById<TextView>(Resource.Id.editTextOtp);
Button btn = FindViewById<Button>(Resource.Id.button3);
RegisterReceiver(smsReceiver, new IntentFilter("android.provider.Telephony.SMS_RECEIVED"));
}
}
How can I achieve this? Any help or guidance in this regard would be highly appreciated.
Update
public void onSMSReceived(string msgs)
{
EditText OtpNumber = (EditText)FindViewById(Resource.Id.editTextOtp);
try
{
OtpNumber.SetText(msgs.ToString(),null);
}
catch (System.Exception ex)
{
}
}
Your are on the finishing line. You only need to do these thing:
Create an interface which will have public method onSMSReceived(String smsMsg)
Instantiate that interface.
Implement that interface in MainActivity activity.
Override onSMSReceived(String smsMsg) in your MainActivity
Notify MainActivity using above created interface from your SMS Broadcast Receiver.
Populate message received in onSMSReceived(String smsMsg) in your MainActivity.
You are done.
I didn't get exactly how you're doing it, but i did in two ways,
1.User has to enter it manually,
2.We have to read automatically through the programming,
But i faced one problem in reading sms automatically, like sending sms and reading sms are calling at the same time may be like register click event, I found one more way to detect automatically like sending otps two times and storing generated otps in a list of string and comparing with message.body
Here the problem is we have to send otp two times, still i'm figuring out how to call reading sms part after sometime,,,!
If you want that solution plz mail me at sailokeshgoud#gmail.com
I am using this code to show notification in notification bar. When the notification is tapped, main activity is launched. Is it possible to launch the view model instead of activity in Xamarin forms app with MvvmCross.
Intent notificationIntent = new Intent(context,typeof(MainActivity));
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pIntent = PendingIntent.getActivity(context, code,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager manager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder notify = new NotificationCompat.Builder(
context);
notify.setContentIntent(pIntent);
notify.setSmallIcon(R.drawable.app_icon);
notify.setContentTitle(“Title”);
manager.notify(reqCode, notify.build());
My idea was to make use of PutExtra in combination with MessagingCenter.
First, you show the notification in the notification bar:
Intent intent = new Intent(Forms.Context, typeof(MainActivity));
if (openPage)
{
intent.SetFlags(ActivityFlags.SingleTop);
intent.PutExtra("OpenPage", "SomePage");
}
const int pendingIntentId = 0;
PendingIntent pendingIntent = PendingIntent.GetActivity(Forms.Context, pendingIntentId, intent, PendingIntentFlags.OneShot);
var nMgr = (NotificationManager)Android.App.Application.Context.GetSystemService(Context.NotificationService);
Notification.Builder notBuilder = new Notification.Builder(Android.App.Application.Context)
.SetContentIntent(pendingIntent)
.SetContentTitle("SomeApp")
.SetContentText(message)
.SetDefaults(NotificationDefaults.Sound | NotificationDefaults.Vibrate)
.SetSmallIcon(Resource.Drawable.ic_launcher)
.SetAutoCancel(true);
var notification = notBuilder.Build();
nMgr.Notify(0, notification);
In MainActivity.cs you check for the extra content:
protected override void OnNewIntent(Intent intent)
{
// Send message to the PCL (XF) if a certain page should be opened.
if (intent.HasExtra("OpenPage"))
{
string pageName = intent.GetStringExtra("OpenPage") ?? "None";
if (pageName != "None")
{
var message = new OpenPageMessage { PageName = pageName };
MessagingCenter.Send(message, Message.Msg_OpenPage);
}
}
base.OnNewIntent(intent);
}
And your central navigation instance (e.g. MainPage), subscribes to this message:
MessagingCenter.Subscribe<Message.OpenPageMessage>(this, Message.Msg_OpenPage, (async) message =>
{
// Loads a certain page if a message is received
switch (message.PageName)
{
case "SomePage":
await Navigation.PushModalAsync(new SomePage(), true);
break;
default:
break;
}
});
Additionally, here is my Message.cs:
public class Message
{
public const string Msg_OpenPage = "OpenPage";
public class OpenPageMessage {
public string PageName { get; set; }
}
}
With the help of this source.
Edit
There are issues if you have multiple push notifications at a time, where notfications where overwritten. One could use a different requestCode or use FLAG_UPDATE_CURRENT.
I am developing one application where i will launch a url in the browser from which i will launch my application.
Suppose if i will click google.com, and press enter, it will launch my application. For that i tried with the HttpFilterRegistry API.
For reference i am using the HTTPFilterDemo application. But currently while launching the app, i am getting the NullPointerException.
I wrote the below code i the openFilter Method:
public Connection openFilter(String name, int mode, boolean timeouts) throws IOException {
Logger.out("Protocol", "it is inside the openFilter method");
_url = name.substring(2);
_requestHeaders = new HttpHeaders();
_responseHeaders = new HttpHeaders();
_responseHeaders.setProperty(HttpProtocolConstants.HEADER_CONTENT_TYPE, "text/html");
Logger.out("Protocol", "here it is come ::::44444444");
final int modHandle = CodeModuleManager.getModuleHandle("AppLaunchBrowser");
Logger.out("Protocol", "here is the module handle:::" + modHandle);
final ApplicationDescriptor[] apDes = CodeModuleManager.getApplicationDescriptors(modHandle);
final ApplicationDescriptor appDescriptor = new ApplicationDescriptor(apDes[0], new String[] {});
Logger.out("Protocol", "here is the app descriptor:::" + appDescriptor);
try {
final int appCode = ApplicationManager.getApplicationManager().runApplication(appDescriptor, true);
Logger.out("Protocol", "here is the app code:::" + appCode);
} catch (ApplicationManagerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// }
return this;
}
And in the application class i am creating alternative entry point and using like below:
public class AppLaunch extends UiApplication{
public static void main(String args[])
{
Logger.out("AppLaunch", args+"length of the arguments::::" +args.length);
if((args != null) && (args.length > 0) && (args[0].equals("background")))
{
Logger.out("AppLaunch", "in the alternate entry point");
// Logger.out("AppLaunch", args+"length of the arguments::::" +args.length);
HttpFilterRegistry.registerFilter("www.google.co.in", "com.innominds.ca", false);
}
else
{
Logger.out("AppLaunch", "Inside the Applaunch");
AppLaunch theApp = new AppLaunch();
theApp.requestForeground();
Logger.out("AppLaunch", "created the app launch object");
theApp.enterEventDispatcher();
// Logger.out("AppLaunch", "in the alternate entry point");
// HttpFilterRegistry.registerFilter("www.google.co.in", "com.innominds.ca", false);
}
}
public AppLaunch()
{
checkPermissions();
showTestScreen();
}
private void checkPermissions()
{
ApplicationPermissionsManager apm = ApplicationPermissionsManager.getInstance();
ApplicationPermissions original = apm.getApplicationPermissions();
if(original.getPermission(ApplicationPermissions.PERMISSION_BROWSER_FILTER) == ApplicationPermissions.VALUE_ALLOW)
{
// All of the necessary permissions are currently available
return;
}
ApplicationPermissions permRequest = new ApplicationPermissions();
permRequest.addPermission(ApplicationPermissions.PERMISSION_BROWSER_FILTER);
boolean acceptance = ApplicationPermissionsManager.getInstance().invokePermissionsRequest(permRequest);
if(acceptance)
{
// User has accepted all of the permissions
return;
}
else
{
}
}
private void showTestScreen()
{
UiApplication.getUiApplication().pushScreen(new AppLaunchScreen());
}
}
Finally i was able to resolve this issue. Actually NPE is coming in some other callback methods because i was implementing the FilterBaseInterface.
I created app which user can start from menu and from icon. I do not use GlobalEventListener in my app, just register ApplicationMenuitem. And now I am getting error: previous instance still active when launch my app.
Steps to reproduce not so trivial:
launch app from icon
do not close it, just switch to another app
launch app from icon again
I founded article in blackberry's forum about it , but I can't find solution where I should remove my ApplicationMenuItem: it added on phone boot and should show all the time.
My code:
public class Jingu extends UiApplication {
public static void main(String[] args) {
ApplicationManager app = ApplicationManager.getApplicationManager();
boolean keepGoing = true;
while (keepGoing) {
if (app.inStartup()) {
try {
Thread.sleep(1000);
} catch (Exception e) {}
} else {
keepGoing = false;
}
}
Jingu theApp = new Jingu();
theApp.initMenuItem();
theApp.showMainScreen();
theApp.enterEventDispatcher();
}
public Jingu() {
}
public void showMainScreen() {
showScreen(new JinguMainScreen(this));
}
public void initMenuItem() {
// Create menu item
Object o = RuntimeStore.getRuntimeStore().get(JinguMenuItem.MY_MENU_ID);
// register only if not done already.
if (o == null) {
new JinguMenuItem(this).registerInstance();
}
}
public void showScreen(Screen aScreen) {
synchronized (Application.getEventLock()) {
try {
UiApplication.getUiApplication().popScreen(aScreen);
} catch (Exception e) {
}
UiApplication.getUiApplication().pushScreen(aScreen);
}
}
}
public class JinguMenuItem extends ApplicationMenuItem {
public static final long MY_MENU_ID = 0xb9739d5240d5943dL;
private final Jingu jingu;
public JinguMenuItem(Jingu jingu) {
super(0x350100);
this.jingu = jingu;
}
public void registerInstance() {
Object menuItem = RuntimeStore.getRuntimeStore().remove(MY_MENU_ID);
if (menuItem == null) {
ApplicationMenuItemRepository amir = ApplicationMenuItemRepository.getInstance();
amir.addMenuItem(ApplicationMenuItemRepository.MENUITEM_SYSTEM, this);
RuntimeStore.getRuntimeStore().put(MY_MENU_ID, this);
}
}
public Object run(Object context) {
jingu.setDefaultFont(Font.getDefault());
jingu.setMainApp(false);
jingu.setBbmEditField(null);
jingu.showMainScreen();
return context;
}
public String toString() {
return "My Menu";
}
}
plz advice where I should delete ApplicationMenuItem in my app?
my regards,
Vadim
If you are registering an ApplicationMenuItem from your application, as a user I would consider it bad style for your application to remove and exit, even if RIM provided a way to do this. You may want to separate your application into two parts. One provides the minimal support for responding to the ApplicationMenuItem selection, that starts automatically and runs in the background. The other has all the rest and can run and exit as needed.
My solution for this situation is:
create alternative entry point and run it on app load
register menu in it
do not use runtimeStore