Network change state not getting detected in Release mode background - Xamarin.iOS - ios

In my application, I have used Xamarin.Essentials to detect network changes in background & fire notifications based on network availability. The code works perfectly on the device & simulator during Debug. However, the Xamarin.Essentials fail to detect connectivity changes in Release mode, especially in the background. The events get triggered when the application reenters into the application (when application becomes ro foreground)
Following is the code I have used
CrossConnectivity.Current.ConnectivityChanged += Current_ConnectivityChanged;
private void Connectivity_ConnectivityChanged(object sender, ConnectivityChangedEventArgs e)
{
if (_networkService.IsConnected())
{
ShowBannerNotificaiton("Internet", "Available", "data1");
}
else
{
ShowBannerNotificaiton("Internet", "Not Available", "data2");
}
}
Appreciate the solution given

Related

listen to click-event from connected button BLE peripheral, while app is in background <react-native ble manager iOS >

As the title suggests, im trying to listen for click-event from my connected BLE peripheral device even after my react-native app is killed/background mode.
While connected i have a notification subscription on my BLE peripheral device and everytime i press button on device, my app gets notified. I want this subscription to last even if the user kills the application.
The app works fine in foreground and inactive, but when i kill the app on iOS it stops responding to button click.
On android i found a library react-native-background-actions which helped solve this. Here is the background code that is currently working on android.
import BackgroundJob from "react-native-background-actions";
playing = BackgroundJob.isRunning();
const sleep = (time) =>
new Promise((resolve) => setTimeout(() => resolve(), time));
BackgroundJob.on("expiration", () => {
console.log("iOS: I am being closed!");
});
const taskRandom = async (taskData) => {
if (Platform.OS === "ios") {
console.warn(
"This task will not keep your app alive in the background by itself, use other library like react-native-track-player that use audio,",
"geolocalization, etc. to keep your app alive in the background while you excute the JS from this library."
);
}
await new Promise(async (resolve) => {
// For loop with a delay
const { delay } = taskData;
console.log(BackgroundJob.isRunning(), delay);
for (let i = 0; BackgroundJob.isRunning(); i++) {
console.log("Ran -> ", i);
// await BackgroundJob.updateNotification({
// taskDesc: "Emergency -> " + i,
// });
await sleep(delay);
}
});
};
const options = {
taskName: "Example",
taskTitle: "ExampleTask title",
taskDesc: "ExampleTask desc",
taskIcon: {
name: "ic_launcher",
type: "mipmap",
},
color: "#ff00ff",
linkingURI: "exampleScheme://chat/jane",
parameters: {
delay: 30000,
},
};
/**
* Toggles the background task
*/
export const toggleBackground = async () => {
playing = !playing;
if (playing) {
try {
console.log("Trying to start background service");
await BackgroundJob.start(taskRandom, options);
console.log("Successful start!");
} catch (e) {
console.log("Error", e);
}
} else {
console.log("Stop background service");
await BackgroundJob.stop();
}
};
I tried reading the core bluetooth background processing for iOS apps and added a restoration identifier on my start method like this:
BleManager.start({
showAlert: true,
restoreIdentifierKey: "IDENTIFIER",
queueIdentifierKey: "IDENTIFIER",
}).then(() => {
console.log("Module initialized");
});
Does anyone have a suggestion on how to keep the subscription while app is in background? react-native-background-actions suggests audio or geolocation libraries, but these are not relevant for my application.
Any help would be greatly appreciated.
You have two very different states you are talking about; Background and killed.
If your app is not onscreen but is still in memory then it is "suspended". It remains suspended until
It is brought back into the foreground by the user
A supported background event occurs and it executes briefly while before becoming suspended again.
It is removed from memory because iOS needs resources
It is removed from memory by the user "Swiping it away"
If an iOS app is suspended and you have added Bluetooth background mode to your app then it will just work; This is scenario 2.
You need to consider what you want to do if the peripheral goes out of range; Do you want to try and reconnect or do you want to give up.
If you want to try and reconnect then you simply call connect in response to a disconnection. If the peripheral comes into range then Core Bluetooth will provide a call-back to your app (even if it is suspended). This applies in both scenario 1 & 2.
An app can be in two different "killed" states; terminated by the system and terminated by the user. These are scenarios 3 & 4
If the app is terminated by the system, scenario 3, and you have set up Core Bluetooth state restoration when you initialised Core Bluetooth then iOS will relaunch your app. When relaunched you need to set up Core Bluetooth again and then the event will be delivered to your app as usual.
If the app is terminated by the user swiping up, scenario 4, then generally speaking your app is dead until the user relaunches it.
You haven't shown how you are using Core Bluetooth, so I can't offer any concrete suggestions but I can say the approach you have shown, trying to keep your app running in the background, is not the right approach and will definitely not work on iOS. There may even be a better approach on Android, but I am not familiar with that platform. Generally keeping an app around, in memory, performing useless work is just wasting memory and battery resources.

Notification not come when app is killed in vivo

I have implemented the notification code in xamarin android. I tested this code on Samsung device using android version Pie works fine,this works fine.However when
I tested on Vivo the notification does not come up when the app is killed and android version is (Pie on both).
Chinese ROMs using (Oxygen OS, MIUI etc) when the apps are swiped from the recent app tray your app gets terminated ( similar to Force Stop). And due to this every task running in the background like Services, Jobs gets killed with the app. Even High priority FCM doesn’t see the daylight in Chinese ROMs
So user needs to enable auto start in settings for app to keep background service/Job running.By default it is off.To do this in some of the devices we can use,
try this:
public class MainActivity : AppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);
Intent intent = new Intent();
string manufacturer = Android.OS.Build.Manufacturer;
switch (manufacturer)
{
case "xiaomi":
intent.SetComponent(new ComponentName("com.miui.securitycenter",
"com.miui.permcenter.autostart.AutoStartManagementActivity"));
break;
case "oppo":
intent.SetComponent(new ComponentName("com.coloros.safecenter",
"com.coloros.safecenter.permission.startup.StartupAppListActivity"));
break;
case "vivo":
intent.SetComponent(new ComponentName("com.vivo.permissionmanager",
"com.vivo.permissionmanager.activity.BgStartUpManagerActivity"));
break;
}
IList<ResolveInfo> arrayList = PackageManager.QueryIntentActivities(intent,
PackageInfoFlags.MatchDefaultOnly);
if (arrayList.Count> 0)
{
StartActivity(intent);
}
}
more info you could refer to Enable background services and Jobs (or FCM) in Chinese ROMs

Adobe Air Application - Not in background and not in Foreground - iPhone

I have an adobe air application - AS3 for iOs and Android.
Whenever the user clicks the home button, and thus the application is now in the background, the application automatically stops, which is the expected behavior. Now, if the user is in the application, and he double clicks his home button, showing all the multiple windows, the application continues running, which is not what i want. How can i access that state ( Not Background, not foreground )? If i can access it, i would then put my pausing code into that state, but how can i access that particular state?
When the user clicks the home button the app is moved to the background and suspended. The app isn't closed. The OS can close the app to free memory. If your app is a memory hog you'll see this happening.
You use events dispatched by the NativeApplication object. Below is example code to listen and handle these events.
import flash.events.Event;
import flash.desktop.NativeApplication;
import flash.desktop.SystemIdleMode;
// create listeners to NativeApplication
private var naApplication: NativeApplication;
naApplication = NativeApplication.nativeApplication;
naApplication.addEventListener(Event.ACTIVATE, eActivate);
naApplication.addEventListener(Event.DEACTIVATE, eDeactivate);
naApplication.addEventListener(Event.EXITING, eExiting);
private function eActivate(e: Event): void {
// app has opened or resumed
application.systemIdleMode = SystemIdleMode.KEEP_AWAKE;
}
private function eDeactivate(e: Event): void {
// app is going to be moved to background
application.systemIdleMode = SystemIdleMode.NORMAL;
}
private function eExiting(e: Event): void {
// app is going to be closed by user or by the OS (usually to free up memory)
// do whatever exit code here then remove all listeners (to be clean don't rely on OS to close them)
application.removeEventListener(Event.ACTIVATE, eActivate);
application.removeEventListener(Event.DEACTIVATE, eDeactivate);
application.removeEventListener(Event.EXITING, eExiting);
application.systemIdleMode = SystemIdleMode.NORMAL;
removeEventListener(Event.ENTER_FRAME, eMainTimer);
}
The systemIdleMode and ENTER_FRAME are just examples of typical code. Let me know of any questions.

Settings alarms while app is closed

How can I set local notifications with out forcing user to open app.
I need my app set a local notification for sunrise and sunset, but I don't want to ask people open app.
I know I can have up to 64 notifications via scheduleLocalNotification, but I need to set it for a year so I should be able to run app in background and set alarms for future sunrises and sunsets in background.
The simple answer is you can't. Your app can't run whenever it wants in the background; it can't schedule a timer to wake itself up to post more notifications when they are due.
The only way you could come close to something like this is by having a server which send a background push notification to your app as a wake-up call when a new batch of 64 notifications are coming close to needed to be posted.
However this would be relying on the fact the user doesn't terminate your app. If the user does then you'd have to send a non-background push notification to the user and hope they click on it to launch your app.
Android Awareness API has recently announced new features that provide a simple solution for your use-case (that avoids you having to explicitly manage location request or computing sunrise times). The way to achieve what you're trying to do is to create and register a TimeFence specified relative to sunrise/sunset.
For example:
// Create TimeFence
AwarenessFence sunriseFence =
TimeFence.aroundTimeInstant(TimeFence.TIME_INSTANT_SUNRISE,
0, 5 * ONE_MINUTE_MILLIS);
// Register fence with Awareness.
Awareness.FenceApi.updateFences(
mGoogleApiClient,
new FenceUpdateRequest.Builder()
.addFence("fenceKey", sunriseFence, myPendingIntent)
.build())
.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(#NonNull Status status) {
if (status.isSuccess()) {
Log.i(TAG, "Fence was successfully registered.");
} else {
Log.e(TAG, "Fence could not be registered: " + status);
}
}
});
You will get callbacks when the fence evaluates to TRUE at sunrise, and when it evaluates back to FALSE at 5-min after sunrise.
Please check Fence API code snippets docs for how to add your custom app logic.

Which event tells you that the device is successfully started

I am making an application that auto starts when the phone restarts. I want to run some events when the phone complets its restart. The UiApp is running even before the device finishes his reset cause I configured the app as an auto start app.
What event should I listen too and that starts when the phone completes the reboot, not in between?
Thanks
It is possible to know if the system is in startup by using :
ApplicationManager.isStartup()
You will need to poll this using a timer till it returns false. However it must be borne in mind that this means that the OS has booted and the system is able to run the application. It does not mean that the entire environment for your application to run is set up completely. For example (as noted by Michael) microSD card might not have been mounted, network connectivity might not been established, or some other service on which your application might depend is not yet available. It's up to you to verify they are available before you begin working of your application.
The approach you need to take is:
Poll if isStartup returns false (System is not in startup phase)
Implement FileSystemListener to check if microSD card is mounted.
Note that mount name for a microSD card is "SDCard".
class FileSystemListenerImpl implements FileSystemListener
{
final static String SDCARD_NAME ="SDCard/";
public FileSystemListenerImpl( )
{
}
public void rootChanged( int state, String rootName )
{
if( state == FileSystemListener.ROOT_ADDED)
{
if( SDCARD_NAME.equals(rootName))
{
_isMicroSDReady=true;
scheduleApplicationStart();
removeFileSystemListener(this);
}
}
else if( state == FileSystemListener.ROOT_REMOVED)
{
}
}
}

Resources