Trying to Poke my Android and Turn on the Screen Programmatically - java

I am building an alarm kind of application for Android.
I set a certain timer to run and then fire after a certain time interval (after the user presses a button) which I call in the onCreate method.
final int interval = 20000; // 20 Second
Handler handler = new Handler();
Runnable runnable = new Runnable(){
public void run() {
Toast.makeText(getApplicationContext(), "Timer to Wake",Toast.LENGTH_SHORT).show();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON|WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
};
handler.postAtTime(runnable, System.currentTimeMillis()+interval);
handler.postDelayed(runnable, interval);
I've also disabled the keyboard in the onCreate method with:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD|
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
In the Android developer docs, it says:
Window flag: when set as a window is being added or made visible, once the window has been shown then the system will poke the power manager's user activity (as if the user had woken up the device) to turn the screen on.
Now after I fire the timer with a press of the button, I immediately turn off the screen. After waiting 20 second though, the screen isn't poked and the device doesn't awaken. What could be the issue here? When I do turn on the screen though with the power button after waiting another 20 seconds, I do find that the keyboard is disabled. Also the screen is perpetually awake when I do leave the screen on. So I know the flags are working. I just need it to "wake" up when the timer fires!

you should use AlarmManager and PendingIntent
AlarmManager am=(AlarmManager)getApplicationContext getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, SampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),(9 * 1000), pendingIntent);

Turns out, I had to properly group the right methods in the correct area. I had previously split the FLAG_DISMISS_KEYGUARD and FLAG_TURN_SCREEN_ON in different areas.
To successfully turn on the screen:
public void run() {
Toast.makeText(getApplicationContext(), "Timer to Wake", Toast.LENGTH_SHORT).show();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}

Related

Android: Changing Views visibility on Activity start | Hide Notification panel on Notification Button click

My app has a Notification that holds a Button.
When the user clicks the Button, the app should open (if it was closed) and show a custom dialog, which I've created by a bunch of views.
Showing the dialog means setting its Visibility to View.VISIBLE.
I use a BroadcastReceiver to receive the Notifications Button click, and it works (I've used Toast messages to check it, and it does - the Receiver is getting called when the Button is clicked, and it reaches to the function that changes the dialogs Visibility to View.VISIBLE)
When I click the Button, the app does open, but the dialog won't show.
Also, I've noticed that when I click the Button, the Notification panel does not hide (unlike when clicking the Notification itself), and I thought maybe it has something to do with it.
So I found this answer, but it didn't work for me (below there's another answer, much newer, but I didn't understand what he did there or how can I do it).
I also checked using Toast messages whether the Visibility parameter of the dialog is changing or not, and it is changing to View.VISIBLE (0), and still, the dialog is not shown.
If I'm in the app and trying to show the dialog, it works, the dialog shows on an in-app button click, the issue occurs when trying to show the dialog as soon as opening the app using the Notifications Button click
Is the Notification Panel the problem?
If it is, why is it happening and how can I hide the notification panel?
If it's not, what is it, and how can I solve this?
Edit
I was asked for the code that inits and shows the notification, so here it is:
#RequiresApi(api = Build.VERSION_CODES.M)
private void updateNotification() {
isBatteryOptimizationActive = App.isBatteryOptimizationActive();
clearAllTimerNotificationActionButtons();
if (isBatteryOptimizationActive) {
initBatteryOptimizationActiveNotification();
} else {
if (notificationJustStarted) {
initNotificationBase();
}
initAndStartPomodoroTimerNotification();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
NotificationManager manager = getSystemService(NotificationManager.class);
manager.notify(TIMER_NOTIFICATION_ID, pomodoroNotificationBuilder.build());
}
}
private void initNotificationBase() {
pomodoroNotificationBuilder = new NotificationCompat.Builder(this, CHANNEL_ID);
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
pomodoroNotificationBuilder
.setContentTitle(getString(R.string.timer_notification_background_allowed_title))
.setOngoing(true)
.setAutoCancel(false)
.setSmallIcon(R.drawable.tomato)
.setContentIntent(pendingIntent)
.setNotificationSilent()
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
notificationJustStarted = false;
}
#RequiresApi(api = Build.VERSION_CODES.M)
private void initAndStartTimerNotification() {
String enableScreenOverlayText = "",
actionButtonTitle;
PendingIntent pendingIntent;
if (!Settings.canDrawOverlays(this)) {
/** Initialize the notification in case "draw over other apps" setting is disabled */
Intent notificationIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
actionButtonTitle = "Enable";
enableScreenOverlayText = String.format("To be able stopping the timer from the notification:\nClick Enable -> Search for %s -> Allow Display over other apps", getString(R.string.app_name));
} else {
/** Initialize the notification in case "draw over other apps" setting is enabled */
Intent stopActionIntent = new Intent(this, PomodoroService.class);
stopActionIntent.setAction(ACTION_STOP_SERVICE);
stopActionIntent.putExtra(POMODORO_SERVICE_STOP_FOR_REAL_EXTRA_NAME, false);
pendingIntent = PendingIntent.getService(this, 1, stopActionIntent, PendingIntent.FLAG_IMMUTABLE);
actionButtonTitle = "Stop";
}
pomodoroNotificationBuilder
.setContentText(String.format("%s is in progress\nThis session remains: %s until finished", goalName, PublicMethods.formatStopWatchTime(millisRemaining)))
.setStyle(new NotificationCompat.BigTextStyle().bigText(enableScreenOverlayText))
.addAction(R.drawable.stop, actionButtonTitle, pendingIntent);
}
How can I hide the notification panel?
I see that you are receiving the action button click in the Receiver. So, then it becomes an easy task to dismiss it. In the receiver, add this line:
NotificationManager manager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
manager.cancel(TIMER_NOTIFICATION_ID);
When I click the Button, the app does open, but the dialog won't show.
You need to pass an intent extra that you are wanting to show the dialog. Then, you can, in the onCreate() get that extra and then show the dialog accordingly.

Timer in android intent service

i have a class to get notification from my server I don't use firebase cloud messaging so I am getting data with the intentservice class. However I want to check the notification in per 60 seconds but timer is not work in
protected void onHandleIntent(Intent intent) {
it starts normally when I start the app but after that it doesn't check in time.
is there any way to check the notification every 60 seconds at the background ?
note: i don't use GCM firebase and I will never use it
IntentService starts the service when you send it an intent, runs whatever you define for that intent, then ends the service. If you are intending for the timer to be run then perhaps do it outside of the service. Perhaps you could use a Handler and post a delayed runnable firing the intent, although I must strongly advise against this in the long term since doing 60 second checks using the phone's radio will drain its battery fast. GCM's Firebase is meant to handle that issue since it "batches" the network requests, and if you don't want to do that then perhaps use a JobScheduler. Android manages the phone's radio pretty nicely and efficiently so unless 60 seconds is absolutely necessary, then it's not really advisable to do this; users could complain of battery drain.
On that handler thing:
private static Handler handler = new Handler(Looper.getMainLooper);
In your activity, then
private Runnable runnable = new Runnable() {
#Override
public void run() {
try{
//Start your intent service here.
} finally {
handler.postDelayed(runnable, 60000);
}
}
};
The try finally block is if your process somehow may trigger an error. If not necessary then you can remove it.
Then in your Activity's onCreate() or wherever you need to start the repeated trigger:
runnable.run();
You can use Alarm manager
Intent alarmIntent = new Intent(context, MyService.class);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, alarmIntent, 0);
AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
manager.setRepeating(AlarmManager.RTC_WAKEUP, 60000, 60000, pendingIntent);

android stopwatch/timer app - switching back to app when time runs out

I'm developing an app, as mentioned in title. I need somehow to manage that application will be running/counting time even when user starts/switches to another application. Well, as I learned from another discussion at stackoverflow.com, there is no need to create service that works in background and pointlessly burden processor with counting time when app is not active.
Everything what is needed to be done is to store current time when user switch to another app, compare it to time when he switches back and update the UI according to difference between these times. That's for stopwatch mode. When in timer mode, I need to automatically switch back to application according to time, that is app's UI showing when going o background. What could be the best solution suitable for this and can you give me please some simple examples for this?
Use AlarmManager for that. AlarmManager allows you to schedule tasks and get notified when they are fired.
So use AlarmManager
public class MainActivity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//call function where you want
timeout();
}
public void timeout()
{ //time in milliseconds 1 minute
Long time = new GregorianCalendar().getTimeInMillis()+60*1000; //i.e.60*1000=1minute
// create an Intent and set the class which will execute when Alarm triggers, here we have
Intent intentAlarm = new Intent(this, AlarmReciever.class);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP,time, PendingIntent.getBroadcast(this,1, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT));
}
}
Here is broadcast class:
public class AlarmReciever extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
// show dialog or what you want
}
}
Don't forgot to edit AndroidMainfest:
//permission
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
//our receiver
<receiver android:name=".AlarmReciever"/>

Android - Location Manager requestLocationUpdates bottleneck

I have an Android background service that report positions from time to time. When I test locally over wifi it works pretty well, however when testing in 3G connection for example (sometimes on Edge) I have perceived that the application apparently enters in a bottleneck and do not execute the onLocationChanged method. That's okay because maybe lost signal or so on. However after a while (maybe when connection is re-established) it start updating all requests at once, in a matter of a few seconds many many times the method onLocationChanged is executed.
Does anyone have ideas how to solve that? Is it possible to add timeout into the method locationManager.requestLocationUpdates?
My Listener
public class MyListener implements LocationListener {
#Override
public void onLocationChanged(Location loc) {
//report location to server
HttlCallToUpdatePostion(loc.Latitude, loc.Longitude, loc.Accuracy);
}
}
My Service
Handler handler = null;
LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
MyListener listener = new MyListener();
protected void doWork() {
Looper.prepare();
handler = new Handler();
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 5000, listener);
Looper.loop();
}
I wrote an app, exactly what you need.
When it was a service only I met the same problem. While the UI went to background and screen off the service went to background and it scheduled the system calls, once when triggered the buffer was flushed and I had like 10-50 updates.
The solution it is: an Alarm must be set and scheduled with 5000 value and a BroadcastRreceiver will receive and it will handle properly. Than you will meet other problems, which is not asked here.
For me this was a SOLUTION and the app is in use!
Edit:
Alarm setup code part:
Intent intent = new Intent(getApplicationContext(), AlarmReceiver.class);
// In reality, you would want to have a static variable for the request
// code instead of 192837
PendingIntent sender = PendingIntent.getBroadcast(this, 192837, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Get the AlarmManager service
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
// am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);
am.setRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis(), timerInterval, sender);
AndroidManifest.xml :
<receiver android:process=":remote" android:name=".broadcastreceiver.AlarmReceiver"/>
class implementation part:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Context appContext = context.getApplicationContext();
...
check for power saving mode in adorid system setting: it must be disable to permit location manager to generete update location when the screen is off

Activity freezes when running service

I have a button that when pressed, starts a service. This service starts logging information from the device. However, when I press the run, the screen temporarily freezes for about 8 seconds whilst it logs, and then once it is finished the screen unfreezes, a toast message shows (that's meant to show as soon as you press the button) and then I can do whatever. If i go on the application screen again, when the application is logging (note: the service is always running so that doesnt freeze it, just the logging) then the activity is frozen again and doesnt let me do anything until the logging is complete.
I have tried asynctasks and running on a new runnable/new thread but none of these have seemed to work for me. Whether i am implementing them correctly or not I'm unsure, but I'd like to fix the problem.
Here is my onStartCommand in the service class:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// THIS WOULD BE THE METHOD THAT RUNS WHATEVER YOU WANT TO DO EVERY SO OFTEN SO FOR ME THIS IS GETTING ALL DATA ETC
getProcessInfo();
// LOG DELAY = SECONDS BETWEEN RUNNING SERVICE/METHOD. SET AT THE TOP
myPendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Alarmmgr.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+LOG_DELAY*1000, myPendingIntent);
Intent notificationIntent = new Intent(this, LogOrCheck.class);
PendingIntent contentIntent = PendingIntent.getActivity(this,
101, notificationIntent,
PendingIntent.FLAG_NO_CREATE);
NotificationManager nm = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
Resources res = this.getResources();
Notification.Builder builder = new Notification.Builder(this);
builder.setContentIntent(contentIntent)
.setSmallIcon(R.drawable.arrow_up_float)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.arrow_down_float))
.setWhen(System.currentTimeMillis())
.setAutoCancel(true)
.setContentTitle("Androigenius")
.setContentText("Service running OK");
Notification n = builder.getNotification();
startForeground(100, n);
return Service.START_STICKY;
}
And here is where I call startService:
but1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (isClicked) {
Context context = getApplicationContext();
Toast toast = Toast.makeText(context, "Please press 'MINIMIZE' at the top to continue logging.", Toast.LENGTH_LONG);
toast.setGravity(Gravity.TOP|Gravity.RIGHT, 10, 55);
toast.show();
System.out.println("Start logging");
but1.setText("Stop Logging");
but1.setTextColor(Color.RED);
// START SERVICE, DONE. (STOP IS BELOW).
startService(myIntent);
isClicked = false;
}
else if (!isClicked) {
System.out.println("Stop Logging");
but1.setText("Start Logging");
// STOP SERVICE, DONE.
stopService(myIntent);
but1.setTextColor(getResources().getColor(color.cornblue));
isClicked = true;
}
Services run on the UI thread which is causing the 'freeze'. Using an IntentService will create a service that automatically runs in the background, not on the UI thread. Here is some details of the IntentService class:
IntentService Class
By default, the Service also run in the main thread of your applicaiton, in which your UI operations occur. Therefore, if you perform a long task in your onStartCommand() method, it will block the main thread.
To avoid the problem, you have to migration the logging task into a separate thread. You may use AsycTask class to do so. Please refer to http://developer.android.com/reference/android/os/AsyncTask.html for how to use the class.

Categories

Resources