Post Oreo 8.0+ Action_User_Present Workaround? - c#

I want to have my app open up every single time the device is unlocked. Effectively, I need a consistent replacement for ACTION_USER_PRESENT.
(NOTE THIS IS FOR AN INTERDISCIPLINARY, PEER-REVIEWED ACADEMIC STUDY STARTING SOON AND IS VITAL FOR THE STUDY'S SUCCESS)
Before the Oero 8.0 update, ACTION_USER_PRESENT was a perfect way to start up the android app each time the device was unlocked.
Unfortunately the work-arounds I've been trying to use are just not cutting it. Effectively I've assigned a myBroadastReceiver to attempt to run the app and PowerManager to see if the device is on or not. Depending on if the device is being used will impact if in the myBroadcastReceiver code will Initiate an Intent.
Problem 1) The broadcast receiver can only be assigned to run at minimum every 15 minutes. I need it to run every time the device unlocks.
Problem 2) Sometimes the broadcast receiver doesnt even try to run for hours at a time... as if the assigned 15 minute check is more of a loose suggestion and not an explicit command.
SOME CODE:
public class classMyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context contextOfReceive, Intent intentOfReceive) {
////////////////////////////////////////////////////////////////////////////////////////////
//This loads up the user selected settings choosen at the homepage of the application.
final SharedPreferences internalAppInformation = contextOfReceive.getSharedPreferences("userPreferences", Context.MODE_PRIVATE);
final SharedPreferences.Editor editor = internalAppInformation.edit();
////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
//Code used to determine 2 things
// 1) if the Device being used or inactive
// 2) if the activity has already been prompted earlier and therefore should be in the foreground of the device
PowerManager pm = (PowerManager) contextOfReceive.getSystemService(Context.POWER_SERVICE);
boolean booleanIsScreenOn = pm.isInteractive();
boolean booleanIsActivityUp = internalAppInformation.getBoolean("booleanIsActivityUp", false);
////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
//If Screen is Off (i.e. the device is NOT BEING USED AT THE MOMENT)
//then this code should allow the Activity to Start
if ( (!booleanIsActivityUp)&&(!booleanIsScreenOn) ) {
//Initiates and Starts up the Intent PromptAndClose.class
editor.putBoolean("booleanIsActivityUp", true);
editor.commit();
editor.apply();
//THE REST OF THE CODE BELOW IS JUST CHOOSING AND
// INITIATING THE PROGRAM AND IS NOT PROBLEMATIC.
}
}
More detailed code can be provided if it will be helpful. I am worried that more code will result it too much clutter for the reader.
ADDITIONAL CODE TO DESCRIBE WHEN THE myBroadcastReceiver is Initiated.
public class Settings extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
////////////////////////////////////////////////////////////////////////////////////////////
//Sets up and starts the calendar (with the setAlarm method for re-occuring attempts to
//prompt the app to move to the foreground if the right conditions are met.
Calendar calendar = Calendar.getInstance();
//if(Build.VERSION.SDK_INT >= 23) {
Log.i("Calendar", "Set Calendar >=23");
calendar.set(
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH),
calendar.get(Calendar.HOUR),
calendar.get(Calendar.MINUTE),
30
);
setAlarm(calendar.getTimeInMillis());
int time = (int) calendar.getTimeInMillis();
String timeString = String.valueOf(time);
Log.i("TIME", "time: " + timeString);
}
private void setAlarm(long timeInMillis) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, classMyBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
assert alarmManager != null;
//RTC-Fires the pending intent at the specified time but does not wake up the device.
//The shortest interval is INTERVAL_FIFTEEN_MINUTES.
alarmManager.setInexactRepeating(AlarmManager.RTC, timeInMillis,
AlarmManager.INTERVAL_FIFTEEN_MINUTES, pendingIntent);
}
}
This code is present in the main activity of the application. The concept is that the first time the app is installed and ran, it will run this code and start and continuous loop of checking and displaying the app to the foreground of the device if the device is not being used. Once that intent is interacted with by the user and closed, the loop starts up again.

That is not going to work. Doze mode and app standby will make what you are trying to do very unreliable.
Try this: Create a foreground service. Start that foreground service when you need to start receiving this broadcast. In onCreate() of that service, call registerReceiver() register a receiver for ACTION_USER_PRESENT. So long as your service is running, you will receive the ACTION_USER_PRESENT broadcast as before.

Related

c# blazor > Can't understand why double instantiation is needed

I use this simple c# code (ok, the result is a little bit silly but it's just to try to solve my problem) to fill a grid (a Syncfusion Blazor datagrid which reads the _monitoringDatas variable to fill out ) :
namespace ligprod.Client.Pages
{
public partial class Monitoring_ligne
{
...
private Monitoring Monit;
private List<Monitoring> _monitoringDatas;
protected override async Task OnInitializedAsync()
{
...
_monitoringDatas = new List<Monitoring>();
}
Task ReceiveLidarValue(string arg)
{
_monitoringDatas = new List<Monitoring>();
Monitoring Monit = new Monitoring()
{
IdMonotoring = 1,
RealProduction = false,
Machine = "remplisseuse",
DatePassage = DateTime.Now,
};
_monitoringDatas.Add(Monit);
}
}
Why do I have to instantiate _monitoringDatas into the ReceiveLidarValue(string arg) task to make the grid filled whereas it was already instantiated in the OnInitializedAsync() Task ?
Yet, the OnInitializedAsync() Task is reached correctly. Indeed, it also contains code to get values from a Hub which works well.
ReceiveLidarValue() is called each time a particular message is thrown to a hub from a service which receive mqtt messages coming from an external electronic card which have a sensor for movements detection :
1/ Server side > As soon as the application is started the service runs and waits for messages from the electronic card.
2/ Client side > The web page (shown in my demand above) is started in a browser (manually). The OnInitializedAsync() method is called and so,-monitoringDatas is instantiated.
3/ Server side > Each time a movement is detected by the sensor, a message (with mqtt protocol) is sent by the electronic card and is finally read by the service which then send a particular message into a hub.
4/ Client side > The message into the hub is detected by the web page and the ReceiveLidarValue(string arg) Task is called.
5/ This Task build a new Monitoring object called Monit (which normally contains an Id, a bool value, the name of the machine on which the movement is detected and the date of detection). This "Monit" is added to the datagrid.
So, each time a new movement is detected, the *ReceiveLidarValue(string arg)*Task is launched and a new Monitoring object is created and added to the datagrid.
All this process works well, but If I comment or erase the _monitoringDatas = new List<Monitoring>(); instantiation into the ReceiveLidarValue(string arg) Task, the grid is not filled (without any error). And Of course, if I leave this second instantiation in the code, the datagrid will be filled but it will always contain only one line replacing the previous one instead of having the new line written after the previous one.
You haven't explained where ReceiveLidarValue gets called, so it's possible it's being called before OnInitializedAsync() is called. You also didn't explain why you think you have to instantiate _monitoringDatas twice. If you are receiving a null ref exception, then my comment above is probably correct. If not, please fill in more details.

UWP scheduled Notification, Toast after app is closed

now, I'm developing some notification app about the online contest.
image:
I managed to get HttpResponse, and parse it to my Class, and add my app as a startup program.
the problem is that I can't find a good way to How notify my app user.
yesterday, I founded Appointment class and I used it. but always, Appointment should be accepted by user's hand. and It is quite slow, and sometime it crashed.
while (mys.Count != 0)
{
Contest contest = mys.Pop();
var appointment = new Appointment();
appointment.Location = "Codeforces";
appointment.Subject = contest.name;
appointment.StartTime = contest.startDate;
appointment.Reminder = TimeSpan.FromHours(1);
var rect = new Rect();
string tmp = await AppointmentManager.ShowAddAppointmentAsync(appointment, rect);
list.Add(contest); //<- observable collection
}
so I changed my mind to use toast notification class. because I think it doesn't need to be accepted by user.
the main question is"
I wonder how can i push notification about the events which will be held in several days.
I mean
my App user just once execute my App.
my App Queried to website, and get some event. (I did {1, 2})
for all appropriate event, I want to push all event to Toast Notification that is valid after my App is closed or my Computer re-boot.
I downloaded Karaoke one App from MS Store, and it pushes Notification periodically 24 hours, even it has no background process(I think), and even I never execute app after rebooting.
below image is Karaoke one App Notification.
How can i Implement it?.
Thanks for read.

Foreground services and repetitive tasks which need to be executed on time

I'm developing an app which basically performs some tasks on timer tick (in this case - searching for beacons) and sends results to the server. My goal was to create an app which does its job constantly in the background. Fortunately, I'm using logging all over the code, so when we started to test it we found that sometime later the timer's callback wasn't being called on time. There were some pauses which obviously had been caused by standby and doze mode. At that moment I was using a background service and System.Threading.Timer. Then, after some research, I rewrote the services to use Alarm Manager + Wake locks, but the pauses were still there. The next try was to make the service foreground and use it with a Handler to post delayed tasks and everything seemed to be fine while the device was connected to the computer. When the device is not connected to a charger those pauses are here again. The interesting thing is that we cannot actually predict this behavior. Sometimes it works perfectly fine and sometimes not. And this is really strange because the code to schedule it is pretty simple and straightforward:
...
private int scanThreadsCount = 0;
private Android.OS.Handler handler = new Android.OS.Handler();
private bool LocationInProgress
{
get { return Interlocked.CompareExchange(ref scanThreadsCount, 0, 0) != 0; }
}
public void ForceLocation()
{
if (!LocationInProgress) DoLocation();
}
private async void DoLocation()
{
Interlocked.Increment(ref scanThreadsCount);
Logger.Debug("Location is started");
try
{
// Location...
}
catch (Exception e)
{
Logger.Error(e, "Location cannot be performed due to an unexpected error");
}
finally
{
if (LocationInterval > 0)
{
# It's here. The location interval is 60 seconds
# and the service is running in the foreground!
# But in the screenshot we can see the delay which
# sometimes reaches 10 minutes or even more
handler.PostDelayed(ForceLocation, LocationInterval * 1000);
}
Logger.Debug("Location has been finished");
Interlocked.Decrement(ref scanThreadsCount);
}
}
...
Actually it can be ok, but I need that service to do its job strictly on time, but the callback is being called with a few seconds delay or a few minutes and that's not acceptable.
The Android documentation says that foreground services are not restricted by standby and doze mode, but I cannot really find the cause of that strange behavior. Why is the callback not being called on time? Where do these 10 minutes pauses come from? It's pretty frustrating because I cannot move further unless I have the robust basis. Does anybody know the reason of such a strange behavior or any suggestions how I can achieve the callback to be executed on time?
P.S. The current version of the app is here. I know, it's quite boring trying to figure out what is wrong with one's code, but there are only 3 files which have to do with that problem:
~/Services/BeaconService.cs
~/Services/BeaconServiceScanFunctionality.cs
~/Services/BeaconServiceSyncFunctionality.cs
The project was provided for those who would probably want to try it in action and figure it out by themselves.
Any help will be appreciated!
Thanks in advance

Windows Phone 8 notifications and background tasks

I have searched the official forums and documentation and all other places, but haven't been able to find a concrete answer.
Q. In Windows Phone 8, is it possible for an application to respond to a Push Notification, and perform a task, while it is in the background?
As far as I can understand, for Toast and Tile Notifications, when the app is not in the foreground, there are no hooks at all for it to be able to respond to the incoming message.
I think "raw notifications" are the correct choice for this, since I am not required to update the app tile, or even show a Toast Notification. But, I haven't been able to find an example, or in the documentations, if I can do this.
I have found several links which talk about doing this for Windows store apps, but I want to find out if this can be done for Windows Phone 8.
I have checked this other thread,
Windows Phone 8 Background Task with notifications
Where one of the answer suggests that Whatsapp actually has a hack for this, to download the messages after a push notification is received. So, is the answer to my question, a NO?
Answer to your question is not exactly "NO",
and you are right whatsapp uses hack for this,
whatsapp someyow use AudioAgent, as they are allowed to run in background,
i dont know how exactly they do it, i am also searching for the same answer, let's see if i find something will post here
This has changed in Windows Phone 8.1. From Raw notification overview (Windows Runtime apps)
Receiving a raw notification
There are two avenues through which your app can be receive raw
notifications:
Through notification delivery events while your application is running.
Through background tasks triggered by the raw notification if your app is enabled to run background tasks.
An app can use both mechanisms to receive raw notifications. If an app
implements both the notification delivery event handler and background
tasks that are triggered by raw notifications, the notification
delivery event will take priority when the app is running.
If the app is running, the notification delivery event will take priority over the background task and the app will have the first opportunity to process the notification.
The notification delivery event handler can specify, by setting the event's PushNotificationReceivedEventArgs.Cancel property to true, that the raw notification should not be passed to its background task once the handler exits. If the Cancel property is set to false or is not set (the default value is false), the raw notification will trigger the background task after the notification delivery event handler has done its work.
Here is a complete guide on receiving push notifications in the background for Windows Phone 8.1:
Get a push notifications channel URI:
PushNotificationChannel _channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
string ChannelUri = _channel.Uri;
Make sure you actually get the URI by logging it. Save the URI and run this on every app launch as the URI gets updated quite frequently.
Create a Windows Runtime Component project inside your solution:
Right click on solution -> Add -> New Project -> select "Windows Runtime Component (Windows Phone)". Call this project "Tasks" or whatever you prefer.
Create a new class extending an IBackgroundTask inside your newly created project. I called mine "NotificationReceiver":
using Windows.ApplicationModel.Background;
namespace Tasks {
public sealed class NotificationReceiver : IBackgroundTask {
public void Run(IBackgroundTaskInstance taskInstance) {
// TODO: implement your task here
}
}
}
Your task will be implemented here inside "Run" function.
Reference your Runtime Component in your main project:
Click on your Windows Phone project -> right click on "References" -> Add Reference -> Tick your Runtime Component and press OK.
Edit your app manifest:
Double-click on your package manifest -> Declarations -> add "Location" and "Push notification" to Supported task types, add your background task class name to Entry point: mine is called "Tasks.NotificationReceiver". Save your changes.
Unregister and register your background task every time the app is launched. I am giving the complete solution, just call "setupBackgroundTask()":
private void setupBackgroundTask() {
requestAccess();
UnregisterBackgroundTask();
RegisterBackgroundTask();
}
private void RegisterBackgroundTask() {
BackgroundTaskBuilder taskBuilder = new BackgroundTaskBuilder();
PushNotificationTrigger trigger = new PushNotificationTrigger();
taskBuilder.SetTrigger(trigger);
taskBuilder.TaskEntryPoint = "Tasks.NotificationReceiver";
taskBuilder.Name = "pushTask";
try {
BackgroundTaskRegistration task = taskBuilder.Register();
Logger.log("TASK REGISTERED");
} catch (Exception ex) {
Logger.log("FAILED TO REGISTER TASK");
UnregisterBackgroundTask();
}
}
private bool UnregisterBackgroundTask() {
foreach (var iter in BackgroundTaskRegistration.AllTasks) {
IBackgroundTaskRegistration task = iter.Value;
if (task.Name == "pushTask") {
task.Unregister(true);
Logger.log("TASK UNREGISTERED");
return true;
}
}
return false;
}
private async void requestAccess() {
BackgroundAccessStatus backgroundStatus = await BackgroundExecutionManager.RequestAccessAsync();
}
Get RawNotification object inside your task:
RawNotification notification = (RawNotification) taskInstance.TriggerDetails;

How to programmatically detect when the OS (Windows) is waking up or going to sleep

Background
My son likes to use his laptop when he's not supposed to and I just thought it would be handy if I could write an application that would email me whenever he opened / closed his laptop.
(I'd even settle for something that notified me when there was network traffic on the machine)
Question
How do you programmatically detect when an OS is waking up or going to sleep? I found this link from this related post. But that covers OS X. I'm looking for the same thing for Windows 7.
(I'd like to do this in Java, if possible, but I'd settle for C#/C++)
Easiest way is not to write any code at all, even though this is stack overflow. Click Start, type Schedule and choose Scheduled Tasks. Set one up (click Create Task) and set a Trigger when the machine is unlocked. For the Action, have it send you an email.
Repeat for startup and when a user logs in, if you want. Done.
You're going to want to create a window and watch for the WM_POWERBROADCAST message (http://msdn.microsoft.com/en-us/library/aa373248%28v=vs.85%29.aspx) and check the wParam for your desired action. For example, your window should receive a WM_POWERBROADCAST with PBT_APMSUSPEND as the wParam when the system is about to enter a suspended state (i.e. closing a laptop). Resuming seems to have a few different wParam values: PBT_APMRESUMESUSPEND, PBT_APMRESUMECRITICAL and PBT_APMRESUMEAUTOMATIC
I search for a long time and found that this was the best way, the 'Sleep'-event was never working before:
private ManagementEventWatcher managementEventWatcher;
private readonly Dictionary<string, string> powerValues = new Dictionary<string, string>
{
{"4", "Entering Suspend"},
{"7", "Resume from Suspend"},
{"10", "Power Status Change"},
{"11", "OEM Event"},
{"18", "Resume Automatic"}
};
public void InitPowerEvents()
{
var q = new WqlEventQuery();
var scope = new ManagementScope("root\\CIMV2");
q.EventClassName = "Win32_PowerManagementEvent";
managementEventWatcher = new ManagementEventWatcher(scope, q);
managementEventWatcher.EventArrived += PowerEventArrive;
managementEventWatcher.Start();
}
private void PowerEventArrive(object sender, EventArrivedEventArgs e)
{
foreach (PropertyData pd in e.NewEvent.Properties)
{
if (pd == null || pd.Value == null) continue;
var name = powerValues.ContainsKey(pd.Value.ToString())
? powerValues[pd.Value.ToString()]
: pd.Value.ToString();
Console.WriteLine("PowerEvent:"+name);
}
}
public void Stop()
{
managementEventWatcher.Stop();
}
A very simple, perhaps crude, but effective way may be to have a program with a timer firing every minute. If the timer fires and it's been, say, 5 minutes of real time since its last execution then you can likely assume that the computer was sleeping since it's unlikely that your thread was unable to be scheduled for so long.
The other reason for the difference may be a clock adjustment, like DST or a manual change, but that kind of "noise" should be very low, in your scenario.
You could write a simple app and register it as a Windows service, to be started automatically at system startup. This app could then do whatever you want when it starts. And if it's a proper Windows app, it can register to get notification about impending system shutdown too (I don't remember the details but I implemented this in a C++ MFC app many years ago).
If you prefer Java, you could register your app as a service via a suitable service wrapper like Tanuki (it seems they have a free Community License option). Although this might be overkill. And it may be possible to get notification about the JVM shutting down when the system is closing (but I have no concrete experience with this).
http://www.pinvoke.net/default.aspx/powrprof.CallNtPowerInformation - Check out the link. It has almost all win32api for all windows function. You can call power management feature directly in your windows 7 laptop. For that create a Windows Service , that will use these specific api to notify the machine state.

Categories

Resources