Custom Lock Screen Delay When Wake - android

I'm trying to make a custom lock screen app, but I'm not sure if I'm going about it the right way. I have a broadcast receiver that listens to when the screen is turned on and starts my lock screen activity. This receiver is registered inside a service, which also disables the default lock screen.
The problem is, there is a slight delay between when the screen is turned on and the lock screen activity shows up. How would I go about doing it so that it shows up right away?
My code for the service:
#Override
public void onCreate() {
super.onCreate();
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver powerReceiver = new PowerReceiver();
registerReceiver(powerReceiver, filter);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
KeyguardManager keyguardManager = (KeyguardManager)getSystemService(Service.KEYGUARD_SERVICE);
KeyguardLock lock = keyguardManager.newKeyguardLock(KEYGUARD_SERVICE);
lock.disableKeyguard();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
and the receiver:
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
Intent showScreen = new Intent(context, LockScreen.class);
showScreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(showScreen);
}
}

Turn your app into a home screen replacement app and when the user successfully unlocks the custom lock screen you can take them to the default home app.
You can find more info in this question and these questions.

Related

Broadcast receiver stops registering broadcasts after a few seconds

#Override
protected void onStart() {
startService(new Intent(this, jam_service.class));
super.onStart();
As soon as I create my main activity, I start my service that looks like this
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
IntentFilter intentFilter = new IntentFilter(myBroadcastReceiver.BroadcastTypes.METADATA_CHANGED);
IntentFilter(myBroadcastReceiver.BroadcastTypes.PLAYBACK_STATE_CHANGED);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
registerReceiver(broadcastReceiver, intentFilter);
return START_STICKY;
}
Which registers this broadcast receiver
public void onReceive(Context context, Intent intent) {
c.writeNewUser(intent.getStringExtra("track"),"user", intent.getStringExtra("track"));
The broadcast receiver detects when the user changes songs in Spotify, and it works sometimes for a short period of time after launching my app and then switching to Spotify, or when my app is open and changing Spotify songs from the notification bar. I want this receiver to never stop listening to broadcasts, even after my app has been in the background for a while. Why does it stop working?

Service not running: app closed and smartphone screen off

I made an application with: an activity (MainActivity) that starts a service (SmartphoneListener).
Activity
public class MainActivity extends Activity implements GoogleApiClient.ConnectionCallbacks{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this,SmartphoneListener.class);
startService(intent);
}
}
The service is used to detect (on smartphone) if the connection with smartwatch is lost.
Service
public class SmartphoneListener extends WearableListenerService {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
powerManager = (PowerManager) getSystemService(POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"MyWakelockTag"); //Service running even if the screen is off.
wakeLock.acquire();
return START_STICKY;
}
#Override
public void onPeerDisconnected(Node node){
Toast.makeText(getApplicationContext(),"Communication with smartwatch lost",Toast.LENGTH_SHORT).show();
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
registerReceiver(mIntentReceiver, filter);
}
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver(){
public void onReceive(Context context, Intent intent) {
//
}
};
...
}
If my application is open and the smartphone screen is off I can detect if I lost my connection with smartwatch (the mIntentReceiver code is executed).
Then If I close my application and the smartphone screen is off I can't detect if I lost my connection with smartwatch (the mIntentReceiver code is not executed).
I don't know why.
Try to add
filter.addAction(Intent.ACTION_SCREEN_OFF);
to your IntentFilter. Hope it help!
You explained in the reply to my comment that you are "closing" the app by swiping it from the recent tasks list. This action causes the process for your app to be killed. Because you return START_STICKY from onStartCommand() in your service, the system will create a new instance of your app in a new process and call onStartCommand() to restart your service. That is the only entry made into your app. No activities are recreated. I know very little about Wear. I'm guessing that your app performs some configuration processing to locate and connect to nodes. If that processing is done in some activity, such as your launch activity, it will not be performed when your app is recreated to restart your service.

Broadcast Receiver in a service but intent not getting caught on service once process is killed

I have a simple widget that does some calculations once the screen comes on and displays them and clears all the fields once the screen goes off ... i have a broadcast receiver setup in my service which listens to ACTION_SCREEN_ON and ACTION_SCREEN_OFF.
This works perfectly as long as the phone doesn't go to sleep for a long period of time or there is heavy usage of the phone - once this happens my widget process is killed (the service is still running but the process is killed) after this when the screen goes off and comes back on my widget doesn't update as the ACTION_SCREEN_ON intent is not caught by my service :(
public class CDTservice extends Service {
#Override
public void onCreate() {
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
m_receiver = new ScreenBroadcastReceiver();
registerReceiver(m_receiver, filter);
Log.d("Widgettool", "works");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
start();
Toast.makeText(getBaseContext(), "SERVICE ON", Toast.LENGTH_SHORT).show();
return START_REDELIVER_INTENT;
}
#Override
public void onDestroy() {
stop();
unregisterReceiver(m_receiver);
}
public void start()
{
RemoteViews View = new RemoteViews(this.getPackageName(), R.layout.main);
updatewidgetclass x= new updatewidgetclass(this, View, widgetId);
x.start(); // does calculations and displays on widget
}
public void stop()
{
RemoteViews Viewclear = new RemoteViews(this.getPackageName(), R.layout.main);
updatewidgetclass y = new updatewidgetclass(this, Viewclear, widgetId);
y.stop(); // clears resources and stops
}
private class ScreenBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
Log.d("ON SCREEN ON", "might hang here");
start();
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
stop();
}
}
}
sometimes when the widget process is not claimed by the android system the widget works perfectly for days and perfectly displays the values ACTION_SCREEN_ON
the problem arises when - i check in settings>apps>running - i can see my widget name and it says 0 processes and 1 service
i assume the broadcast receive is happening on the main process and hence its not receiving it when the process gets killed.
I have a work around in place for this but would really like to fix the issue.
Any helps is highly appreciated
I agree with #CommonsWare that having a service running in the bg at all times just to detect when the screen turns on and off is a very bad idea. Do you really need ACTION_SCREEN_ON, or will ACTION_USER_PRESENT (phone unlocked) suffice? This way, you do not need a service at all, and you can just define the receiver in the manifest.
If you really wanted to, you could register your service/ACTION_SCREEN_OFFreceiver in your ACTION_USER_PRESENT receiver so that the service is only running when the user is actually using the device.
I know this doesn't really answer your question, but it does provide a useful workaround to your problem.

Problems with android lock in custom lock screen app

I built a custom lock screen app that uses a broadcast receiver and service to listen for when the user turns on or off the screen and from there launch my activity. The activity is supposed to completely replace the lock screen. In order to do this my app is supposed to disable the android stock lock so that my app can function as the new lock screen.
Instead what happens is once the application is first installed the the service first started the application appears to be working. and when the user first turns off the screen of their phone when they turn it back on they are presented with my app running on top and is able to unlock their phone with my app. But then once inside the android OS if the user presses the home button the next time they turn off the screen and turn it back on instead of being brought back to my application they are brought to the stock unlock screen with my application open underneath it, when it should be on top.
Here is my code:
My Service:
public class MyService extends Service {
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
super.onCreate();
Log.d("MyService","Service STARTED");
final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
final BroadcastReceiver mReceiver = new ScreenReceiver();
registerReceiver(mReceiver, filter);
}
}
My broadcast receiver:
public class ScreenReceiver extends BroadcastReceiver {
public static ArrayList<String> runningApplications = new ArrayList<String>();
private Context ctext;
public static boolean screenIsLocked;
public static KeyguardManager keyguardManager;
public static KeyguardLock lock;
#Override
public void onReceive(final Context context, final Intent intent) {
ctext = context;
keyguardManager = (KeyguardManager)ctext.getSystemService(Activity.KEYGUARD_SERVICE);
lock = keyguardManager.newKeyguardLock(Context.KEYGUARD_SERVICE);
lock.disableKeyguard();
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
screenIsLocked = true;
Log.d("ScreenReceiver", "False");
Intent intenti = new Intent();
intenti.setClass(context, starterActivity.class);
intenti.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intenti.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intenti);
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
screenIsLocked = false;
Log.d("ScreenReceiver", "True");
Intent intenti = new Intent();
intenti.setClass(context, starterActivity.class);
intenti.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intenti.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intenti);
}
}
My activity that is started is basically empty with just one unlock button that calls finish(); when pressed.
The behavior of keyguard-related logic can vary from device to device. That's because lockscreens are often custom-made by device manufacturers (i.e. not stock), some of them respect the keyguard logic you use, some don't.
Also, afaik the newer way to control keyguard is to use window flags:
// inside activity
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
This will not solve the problem though, devices still have their say about this.
E.g. from my experience, Galaxy Nexus will show your activity's window above keyguard but will not dismiss it (you'd think Google-branded device should respect the flag, eh), so if you hit the back button in your activity - you'll get standard lockscreen --- while HTC One X seems to handle the dismiss part properly: your activity window will cause standard lockscreen to get dismissed as expected.
I found no way to force all devices to behave properly. Android API is not meant to enable you to create custom lock screens (at least not currently). Take a look at the ones in the store - they all have the exact same problem of not being stable enough.
As Dianne Hackborn says in this Google Groups answer, anything you can do in this regard is a hack so expect it to break from time to time.
I tried to compile your code and got the same error you were talking about. I tried to modify it to make it to work and finally got the problem!!!
public class ScreenReceiver extends BroadcastReceiver {
public static ArrayList<String> runningApplications = new ArrayList<String>();
private Context ctext;
public static boolean screenIsLocked;
public static KeyguardManager keyguardManager;
public static KeyguardLock lock;
#Override
public void onReceive(final Context context, final Intent intent) {
ctext = context;
keyguardManager = (KeyguardManager)ctext.getSystemService(Activity.KEYGUARD_SERVICE);
lock = keyguardManager.newKeyguardLock(Context.KEYGUARD_SERVICE);
lock.disableKeyguard();
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
screenIsLocked = true;
Log.d("ScreenReceiver", "False");
Intent intenti = new Intent();
intenti.setClass(context, starterActivity.class);
intenti.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intenti.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intenti);
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
screenIsLocked = false;
Log.d("ScreenReceiver", "True");
Intent intenti = new Intent();
intenti.setClass(context, starterActivity.class);
intenti.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intenti.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intenti);
}
}
With this change to the broadcast receiver class I was able to overcome the problem
Try it and tell me if there is any problem.
EDIT:I think the problem might lie in the finish() method....Android dumps apps when it requires memory...I think finish() might be helping android in trashing the app(and this might be the reason why your problem occurs randomly)

How to reveal that screen is locked?

In my application I need to know when device is locked (on HTC's it looks like short press on "power" button). So the question is: which event is triggered when device is locked? Or device is going to sleep?
You should extend BroadcastReceiver and implement onReceive, like this:
public class YourBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_SCREEN_OFF.equalsIgnoreCase(intent.getAction())) {
//screen has been switched off!
}
}
}
Then you just have to register it and you'll start receiving events when the screen is switched off:
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
appBroadcastReceiver = new AppBroadcastReceiver(yourActivity);
registerReceiver(appBroadcastReceiver, filter);
There is a better way:
KeyguardManager myKM = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
if( myKM.inKeyguardRestrictedInputMode()) {
//it is locked
} else {
//it is not locked
}
In addition to the above answer, in-case you want to trigger some action when your app is at the foreground:
You could use the event called onResume() to trigger your own function when your app takes the spotlight from a previously resting state, i.e, if your app was at the background(paused/minimized...)
protected void onResume()
{
super.onResume();
//call user-defined function here
}

Categories

Resources