I want to use the action button "Open" on a notification on my Android Wear application, to open a Dialog with some task data on my handheld. To do this, I put my message in a PutDataMapRequest and use the following method in my Wearable code:
PutDataMapRequest dataMap = PutDataMapRequest.create("/task/" + "1");
dataMap.getDataMap().putString(DataMapKeys.TASK_MESSAGE, message);
....
dataMap.getDataMap().putLong("timestamp", System.currentTimeMillis());
PutDataRequest putDataRequest = dataMap.asPutDataRequest();
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest).setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
#Override
public void onResult(DataApi.DataItemResult dataItemResult) {
Log.d(TAG, "Sending task data: " + dataItemResult.getStatus().isSuccess());
}
});
And then, to catch it in my WearableListenerService on my handheld/mobile device:
#Override
public void onDataChanged(DataEventBuffer dataEvents) {
Log.d(TAG, "Received task data, now opening dialog..");
}
However, there is a significant delay (about 10 seconds) between the call to onResult() in the putDataItem() method in my Wear app, and the invoking of the onDataChanged() method in my mobile app. This means that when I press the "Open" Action button on the notification on my watch, the dialog opens about 10 seconds later on my phone. I would like this to be instant, if possible.
Is this possible, or am I doing something wrong here in my code?
Best,
Switch to using MessageApi. It is intended for situations like this: it doesn't have a guarantee of delivery (if the devices are not connected at the moment), but is fast. And clicking a button is exactly the situation where it should be used (because user can repeat it).
Related
My android app has a function to detect all the keycodes for TV remote.
I tried onKeyDown(up) API to detect when the user press the TV remote and override dispatchKeyEvent method too. It works except some keys : mute, volume, home, back. how can I detect those keys?
Thanks,
The system has the privilege to control those keys, so I have to find some source code to use.
I final resolved this problem. In general, AOSP dispose a led service (led controller):
public LedService() {
}
public IBinder onBind(Intent intent) {
this.handlePowerStateChanged(0);
return new LedService.LedServiceWrapper();
}
public void handlePowerStateChanged(int state) {
if (DEBUG) {
Log.d(TAG, "handlePowerStateChanged: " + state);
}
}
public void handleKeyEvent(KeyEvent event) {
if (DEBUG) {
Log.d(TAG, "handleKeyEvent: " + event);
}
}
This class use HAL to go down the level and communicate directly with system. I extend this class in my own class and use handleKeyEvent method.
Cheers,
Check the KeyEvent constants, and by the help of the following SO references.
Detect home button press in android
Check if back key was pressed in android?
Android: How to get app to remember if mute button has been pressed or not
Android - Volume Buttons used in my application
Here I am showing toast message in Xamarin Forms Android
My Code:
Inside my Android Class
public void ShortAlert(string message)
{
Toast.MakeText(Forms.Context, message, ToastLength.Short).Show();
}
I am showing this toast message when user click on A Button.But When user rapidly click the button then it will shoing continiously(5 times button click showung toast 5 times).
so I want if the user click on this button second time then previous toast should be cancel.
How to do this in Xamarin form android?
You can try cancelling the Toast than it wont show on screen for a long time
public void ShowToast(string message)
{
if (objToast!= null)
{
objToast.Cancel();
}
objToast = Toast.MakeText(Forms.Context, message, ToastLength.Short);
objToast.Show();
}
Declare objToast on class level like this
private Toast objToast;
You could add the effective time of a click, for example, only the first click is valid for multiple clicks within 3 seconds,so you could change the code like this :
public static int MIN_CLICK_DELAY_TIME = 3000;//the effective time
private long lastClickTime = 0;
public void ShortAlert(string message)
{
long currentTime = Calendar.Instance.TimeInMillis;
if (currentTime - lastClickTime > MIN_CLICK_DELAY_TIME)
{
lastClickTime = currentTime;
Toast.MakeText(Forms.Context, message, ToastLength.Short).Show();
}
}
On iOS, I only can check state of Bluetooth. I'm find the solutions on network and use it.
public class CallBluetoothIphoneService : ICallBlueTooth
{
public void LaunchBluetoothOnPhone()
{
try
{
// Is bluetooth enabled?
var bluetoothManager = new CBCentralManager();
if (bluetoothManager.State == CBCentralManagerState.PoweredOff|| bluetoothManager.State == CBCentralManagerState.Unknown)
// Does not go directly to bluetooth on every OS version though, but opens the Settings on most
UIApplication.SharedApplication.OpenUrl(new NSUrl("App-Prefs:root=Bluetooth"));
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
}
}
But when I try turn off Bluetooth and test code, state of bluetooth is "Unknown".
Then I run code, device open settings, toggle button has color green (turn on bluetooth), but when I check state of Bluetooth in code, State of Bluetooth is "Unknown", is not "Power on".
I'm using Xamarin 3.3 and test on device iOS version 12.0.
I am not sure exactly what you want to do, but if your intent is to open the Bluetooth settings page, this:
UIApplication.SharedApplication.OpenUrl(new NSUrl("App-Prefs:root=Bluetooth"));
won't work. Apple has at some points allowed this (iOS 8 IIRC) and at other points it has disallowed this (most versions of iOS). See this long SO thread about this issue: How to open Settings programmatically like in Facebook app?
Regardless, there is no need. When iOS detects that your app has created a CBCentralManager type with delegate, iOS will display an alert to the user that allows them to go to the bluetooth settings to enable bluetooth by tapping the "Settings" button in the alert.
As far as always getting state as "Unknown", you need to check the state in the delegate for the CBCentralManager. You cannot use the parameterless CBCentralManager constructor new CBCentralManager();. Check the apple docs: https://developer.apple.com/documentation/corebluetooth/cbcentralmanager?language=objc and note that there are only two listed init methods, one that takes delegate and queue parameters, and one that takes delegate, queue, and options parameters, although no one complains if you use the parameterless constructor... but you will never get the correct state if you use it. See: https://stackoverflow.com/a/36824770/2913599
So try this:
public class CallBluetoothIphoneService : ICallBluetooth
{
public void LaunchBluetoothOnPhone()
{
try
{
// Is bluetooth enabled?
var bluetoothManager = new CBCentralManager(new MySimpleCBCentralManagerDelegate(), DispatchQueue.CurrentQueue);
// This will always show state "Unknown". You need to check it in the delegate's UpdatedState method
Console.WriteLine($"State: {bluetoothManager.State.ToString()}");
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
public class MySimpleCBCentralManagerDelegate : CBCentralManagerDelegate
{
override public void UpdatedState(CBCentralManager mgr)
{
// You can check the state in this delegate method
Console.WriteLine($"UpdatedState: {mgr.State.ToString()}");
if (mgr.State == CBCentralManagerState.PoweredOn)
{
//Passing in null scans for all peripherals. Peripherals can be targeted by using CBUIIDs
CBUUID[] cbuuids = null;
mgr.ScanForPeripherals(cbuuids); //Initiates async calls of DiscoveredPeripheral
//Timeout after 30 seconds
var timer = new Timer(30 * 1000);
timer.Elapsed += (sender, e) => mgr.StopScan();
}
else
{
//Invalid state -- Bluetooth powered down, unavailable, etc.
System.Console.WriteLine("Bluetooth is not available");
}
}
public override void DiscoveredPeripheral(CBCentralManager central, CBPeripheral peripheral, NSDictionary advertisementData, NSNumber RSSI)
{
Console.WriteLine("Discovered {0}, data {1}, RSSI {2}", peripheral.Name, advertisementData, RSSI);
}
}
Bottom line: always create a CBCentralManager object with one of the following constructors:
CBCentralManager(ICBCentralManagerDelegate, DispatchQueue)
CBCentralManager(ICBCentralManagerDelegate, DispatchQueue, CBCentralInitOptions)
I have a BlackBerry App that has a Listener for the Send Button implemented in the CheckIn Screen. Data is sent through a web service. If the data is sent successfully, a confirmation message of "OK" is received. I am trying to switch screens in my BlackBerry App depending on the response received.
FieldChangeListener sendBtnListener = new FieldChangeListener() {
public void fieldChanged(Field field, int context)
{
try {
String alertMsg=sendTextCheckIn();
if(alertMsg.equals("OK"))
{
UiApplication.getUiApplication().invokeLater( new Runnable()
{
public void run ()
{
UiApplication.getUiApplication().pushScreen(new MyScreen());
}
} );
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
However, the above is throwing an App Error 104: IllegalStateException. Can anyone please guide on how to switch screens between a BlackBerry App.
EDIT: I can switch to any other screen but I CAN NOT switch to MyScreen. NOTE: MyScreen is the main (first) screen of the App. The above method sendTextCheckIn() calls another method that is placed inside MyScreen. Has this got anything to do with the error? Please advice.
The 'fieldChanged' event is already running on the UI event thread, so you shouldn't need to do the invokeLater call within it, just call pushScreen directly.
You mention that your problem with IllegalStateException only happens for MyScreen. That makes it sound like something specific with the implementation of MyScreen. Start narrowing down the problem - look at what happens in the constructor of MyScreen, and any events that might get called before the screen is visible. Some of that code is what is causing the problem.
Wrap everything that could possibly raise in exception in try/catch.
Don't do e.printStackTrace() - that won't give you much.
Instead do something like System.err.println ("KABOOM in method abc() - " + e); - seems like more effort, but trust me, that becomes INVALUABLE when debugging issues like this.
Catch Exception, unless you have a VERY good reason to catch a specific a subtype - otherwise you WILL end up with unexpected, and uncaught exceptions, which you will hunt for DAYS.
Windows Phone 7.5 / Silverlight app
If user is playing music / radio on their phone and they try to launch my application, I want to give user an option to stop the currently playing option.
Working fine:
The message popup shows up fine. When I select Cancel, the popup closes, the music keeps playing and my app starts/works as normal.
Issue:
If I select Ok i.e. to stop the currently playing music on phone, the music stops but at the same time my app also exits.
Any ideas what I am doing wrong here?
Here is the code I am using. I call this method on launching:
private void CheckAudio()
{
if (FMRadio.Instance.PowerMode == RadioPowerMode.On)
{
MessageBoxResult Choice;
Choice = MessageBox.Show("For better user experience with this application it is recommended you stop other audio applications. Do you want to stop the radio?", "Radio is currently playing!", MessageBoxButton.OKCancel);
if (Choice == MessageBoxResult.OK)
{
FMRadio.Instance.PowerMode = RadioPowerMode.Off;
}
}
if (MediaPlayer.State == MediaState.Playing)
{
MessageBoxResult Choice;
Choice = MessageBox.Show("For better user experience with this application it is recommended you stop other audio/video applications. Do you want to stop the MediaPlayer?", "MediaPlayer is currently playing!", MessageBoxButton.OKCancel);
if (Choice == MessageBoxResult.OK)
{
MediaPlayer.Stop();
}
}
}
Update:
I posted my solution below. Do let me know if I am doing anything wrong.
I found the following error was being thrown:
FrameworkDispatcher.Update has not been called. Regular
FrameworkDispatcher. Update calls are necessary for fire and forget
sound effects and framework events to function correctly.
So I added this code and now it is working fine. Now upon clicking OK, the music player stops and my app launches fine. I call the SetupTimer method from InitializeComponent in App.xaml.cs
private GameTimer gameTimer;
private void SetupTimer()
{
gameTimer = new GameTimer();
gameTimer.UpdateInterval = TimeSpan.FromMilliseconds(33);
// Call FrameworkDispatcher.Update to update the XNA Framework internals.
gameTimer.Update += new EventHandler<GameTimerEventArgs>(gameTimer_Update); //delegate { try { FrameworkDispatcher.Update(); } catch { } };
// Start the GameTimer running.
gameTimer.Start();
// Prime the pump or we'll get an exception.
FrameworkDispatcher.Update();
}
void gameTimer_Update(object sender, GameTimerEventArgs e)
{
try { FrameworkDispatcher.Update(); }
catch { }
}
If anybody sees any problem/issue with the above please do let me know. Thanks.