I am trying to make a Lock Screen App, that is why I want to start my app every time the Screen is turned on. Currently I found a solution where a Receiver for Screen on/off and the methods onPause() and onResume() are used. This is the Link of the Example: http://thinkandroid.wordpress.com/2010/01/24/handling-screen-off-and-screen-on-intents/#comment-4777
I am using the example of the activity and not the service.
I am actually getting Feedback in the LogCat when the screen is turned off and on and the app is already running. The problem is that the app doesn't start when I am turning the screen on (even if it is shown under recently used apps).
I am not sure but I think the example works fine and I am just missing to add the essential code.
I hope someone can help !!
Thanks for the quick answer. I have tried to run your code but it is still not working. I am not sure what is wrong. There is no error message. The application just runs normally but won't start when the screen goes on.
To make it easier to help me here is my code ;)
This is my Receiver:
package com.example.screenlocker;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class StartMyServiceAtBootReceiver extends BroadcastReceiver {
public static boolean screenOff = true;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
screenOff = true;
Intent i = new Intent(context,LockService.class);
i.putExtra("screen_state", screenOff);
context.startService(i);
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
screenOff = false;
}
}
and this my Service:
package com.example.screenlocker;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
public class LockService extends Service {
public void onCreate(){
IntentFilter filter=new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver locker=new StartMyServiceAtBootReceiver();
registerReceiver(locker, filter);
}
#Override
public void onStart(Intent intent, int startId) {
boolean screenOn = intent.getBooleanExtra("screen_state", false);
if(screenOn){
startActivity(new Intent(this, MainActivity.class));
}
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
Maybe you know what is wrong.
The following things need to be done in order to achieve this.
1.When your application starts you must start a service for registering the SCREEN_TURN_ON and SCREEN_TURN_OFF events.
REASON If you won't start a service to register these events and just register it inside an activity.Then when activity gets destroyed it stops registering for the screen on/off events.Making a service causes it to outlive the activity's or your application's lifetime.
2.Now you need to put some code in your service (inside the onCreate method)
IntentFilter filter=new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
locker=new startLockActivity();
registerReceiver(locker, filter);
3.Make a BroadCastReciever and check for the Screen ON/OFF events and perform actions accordingly.
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
screenOff = true;
Intent i = new Intent(context,Locker.class);
i.putExtra("screen_state", screenOff);
context.startService(i);
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
screenOff = false;
}
4.Now in your service onStartCommand method put some code to get the flag sent via the receiver and start your lock activity.
boolean screenOn = intent.getBooleanExtra("screen_state", false);
if(screenOn){
startActivty(this,yourLockActivity.class);
}
Hope it helps you out.
Related
I have made an app in which a service runs in the background. But if the android system requires resources, it will stop the service. However I may still require my service to run.
Is it a bad practice to restart the service (if condition relevant to my app still holds true) in the onDestroy method of my service?
How can I make sure my service runs indefinitely (if condition relevant to my app still holds true)? Or atleast on high priority?
Probably the best you can do is use the START_STICKY flag, which tells Android to attempt to restart the service if it has stopped. Beyond that ensure that it consumes as few resources as possible, so that it is less likely to be destroyed.
Android prioritizes the UI over everything. Then processes that are related to the UI. Then processes that are consuming the least amount of resources. A Service runs in the background, so unless it has resources that are also in use on the UI or connected to the UI in some way, it should be a lower priority.
Also you cannot tell Android how to prioritize your Service (everyone would make theirs the "highest priority" right?). So it goes by how well you minimize the impact on overall resources - why kill 3 Services when it could kill 1 and regain all the resources it needs?
To help understand how to manage memory better: http://developer.android.com/training/articles/memory.html
set it START_STICKY. It Causes after killing service the service will restart again. it is my code :
android manifest :
<application
....
<service android:name=".UpdateService" />
</application>
service class :
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class UpdateService extends Service {
BroadcastReceiver mReceiver;
#Override
public void onCreate() {
super.onCreate();
// register receiver that handles screen on and screen off logic
IntentFilter filter = new IntentFilter(Intent.....);
filter.addAction(Intent....);
mReceiver = new MyReceiver();
registerReceiver(mReceiver, filter);
}
#Override
public void onDestroy() {
unregisterReceiver(mReceiver);
Log.i("onDestroy Reciever", "Called");
super.onDestroy();
}
#Override
public void onStart(Intent intent, int startId) {
Log.i("log", "action Called");
}
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
}
receiver class :
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("Log", "recevid");
}
}
in StartupActivity :
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Context context = getApplicationContext();
Intent service = new Intent(context, UpdateService.class);
context.startService(service);
}
i am trying to write a sample Android service code to test whether , the service stop itself or not after returning START_NOT_STICKY to onStartCommand. But i whenever , i closed my app , the service stop itself , whereas according to the rule START_NOT_STICKY will not allow to stop the service automatically.
MyCode :
ServiceDemo.java
package com.example.servicedemo;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent in = new Intent(this,TrackService.class);
startService(in);
}}
TrackService.java
package com.example.servicedemo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class TrackService extends Service
{
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags , int startId)
{
return START_NOT_STICKY;
}
#Override
public boolean onUnbind(Intent intent)
{
return super.onUnbind(intent);
}}
this my above code , whenever i close my app , the app service stops itself , please help me out , how can i restrict my service to stop or restart itself.
close my app means , pressing home and from slide menu swipe up app to close completely
That means that you are terminating your background process. At that point, your service is gone, and since you are returning START_NOT_STICKY, it will not automatically restart.
In other words, what is happening is perfectly normal.
Close with swipe won't kill this code.
It's a service that runs in the foreground so android treats it as if it is on the screen. It runs in a seperate process so the main process can be killed. It shows a custom notification to the user when its running so its completely ligit and it is written.
Note Eclipse ADK Users only put the service in a different process when your done debugging it.
manifest
<service
android:name="com.gosylvester.bestrides.ServiceLocationRecorder"
android:process=":myService" >
</service>
</application>
MyService class
private boolean isRecording = false;
public int onStartCommand(Intent intent, int flags, int startId) {
boolean isTrackerMarker = SettingMarker.TRACKER_MARKER_DEFAULT;
if (intent != null) {
isRecording = intent.getBooleanExtra("isrecording", isRecording);
startRecording(isRecording);
}
//if isRecording keep the service running else let os know service can be killed
if (isRecording) {
startForeground(R.id.action_record, getMyCustomNotification());
return Service.START_STICKY;
} else {
stopForeground(true);
return Service.START_NOT_STICKY;
}
}
The service does get re-created, just not re-started.
If you override the onCreate and do a Log.d or a Toast, you will see that onCreate gets called after your activity and app is destroyed and even the service onDestroy is called.
So the trick to keep it running after it is re-created is to put your code on the onCreate method and use the onStartCommand just to return START_STICKY.
Note: onCreate is called before onStartCommand, so your code will run both when it is started by startService and from the system self re-creation.
I am writing an application which catches media-button-clicks from a bt-headset. However, since my receiver is stated in the manifest-file, I am suddenly not in control of my activity any more, and what I really want to do is to "press" a software-button on the activity when somebody presses the headset button.
I've tried several solutions but have not got anything to work. Here is my current state
package com.siriforreq.activities;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class MediaButtonReceiver extends BroadcastReceiver{
private boolean gotMessage = false;
public MediaButtonReceiver(){
super();
}
public boolean isMessage(){
return this.gotMessage;
}
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("IN ON RECEIVE1");
if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
System.out.println("GOT MEDIA BUTTON");
Intent startBroadcastIntent = new Intent(context, NetworkActivity.class);
startBroadcastIntent.setAction("com.siriforerq.activities.ACTION_LOL");
startBroadcastIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
System.out.println("...sending broadcast");
context.sendBroadcast(startBroadcastIntent);
}
}
}
In the above receiver, I do catch the media button. But where do I go from now to update my Activity? What I am trying to do right now is to send another custom broadcast and catch that in another receiver within the activity, but it does not seem to work. Here is my Activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_network);
mMediaReceiverCompName = new ComponentName(getPackageName(), MediaButtonReceiver.class.getName());
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
IntentFilter btCommunicationFilter = new IntentFilter();
btCommunicationFilter.setPriority(1000);
btCommunicationFilter.addAction("com.siriforerq.activities.ACTION_LOL");
catchButtonEvent = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("Got broadcast yes");
//startTalkInteraction(); <- this is the method I want to call in the activity
}
};
registerReceiver(catchButtonEvent, btCommunicationFilter);
}
public void onResume() {
super.onResume();
mAudioManager.registerMediaButtonEventReceiver(mMediaReceiverCompName);
socketNetworkHelper = SocketNetworkHelper.getSocketNetworkHelper(ip, port);
setButtonStatus(true);
}
In the above anonymous receiver, the broadcast that is being sent from the MediaButtonReceiver never gets called and here is my problem right now. Should I think in another way or why doesn't my onReceive in the anonymous receiver-class trigger?
As it can be seen in the docs you are using the constructor Intent(class,context) which creates an Intent for a specific component. Instead you should construct your Intent like this :
Intent startBroadcastIntent = new Intent();
startBroadcastIntent.setAction("com.siriforerq.activities.ACTION_LOL");
startBroadcastIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
My application needs to make a toast when the user unlocks the screen, so I registered a BroadcastReceiver to pick up the intent ACTION_USER_PRESENT in the manifest, like so:
<receiver
android:name=".ScreenReceiver" >
<intent-filter>
<action
android:name="android.intent.action.USER_PRESENT"/>
</intent-filter>
</receiver>
And then I defined a class like this:
package com.patmahoneyjr.toastr;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class ScreenReceiver extends BroadcastReceiver {
private boolean screenOn;
private static final String TAG = "Screen Receiver";
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
screenOn = true;
Intent i = new Intent(context, toastrService.class);
i.putExtra("screen_state", screenOn);
context.startService(i);
Log.d(TAG, " The screen turned on!");
} else if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
screenOn = false;
}
}
}
But for some reason, the Log statement is printed twice, and my service makes two toasts instead of one. Does anyone know why this might be happening, and what I can do to stop it? Am I overlooking something silly?
EDIT: I'm terribly sorry everyone, but I found the problem myself... the bug was that in the service class that was supposed to receive the broadcast, I had instantiated a new ScreenReceiver and it too was picking up the intent. I misunderstood the class and thought that to receive the intent I had to have one there, but after removing that block, I only receive the intent once. Android wasn't sending the intent twice, it was just getting picked up twice... Thank you for your help everyone!
Try This:
1. Simply create your broadcast reciever.
BroadcastReceiver reciever_ob = new BroadcastReceiver(
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(Intent.ACTION_USER_PRESENT)){
//DO YOUR WORK HERE
}
}
}
2. Register your receiver before sending broadcast with above broadcast object. you can also add multiple actions.
IntentFilter actions = new IntentFilter(Intent.ACTION_USER_PRESENT);
registerReciever(reciever_ob, actions);
3. Send broadcast
Intent intent = new Intent(Intent.ACTION_USER_PRESENT);
SendBroadcast(intent);
now you can remove all your stuff which you have declared in your xml-manifest file I dont know exactly but i think it should work.
I Have a BroadcastReceiver set up to turn Bluetooth on and off according to power state (when plugged in, bluetooth is on, unplugged, bluetooth is off). This is working just fine (yay!). however, my very simple app has a single button, which also turns Bluetooth on and off, and has the text "Bluetooth on" or "Bluetooth Off", as applicable. I would like to update this single button, BUT, I only have to update it if the app is in the foreground.
Inside onResume on m,y main activity, I'm calling my updateUI method, which checks the Bluetooth state, and updates the button accordingly. however, that only applies if the program was open and in the background, and is resumed, NOT if i'm in the program while plugging/unplugging the power.
I created a new activity (CheckIfAppIsRunningActivity.java) with this code which is supposed to check if my app is running in the foreground, and if so, take it to the activity (BluetoothOnActivity) which will update the button:
package vermel.BluetoothOn;
import java.util.List;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class CheckIfAppIsRunningActivity extends Activity{
public void onCreate() {
checkStatus();
}
private BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Intent it = new Intent();
it.setClassName("vermel.BluetoothOn", "vermel.BluetoothOn.BluetoothOnActivity");
context.startActivity(it);
}
};
public void checkStatus() {
ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> runningProcInfo = activityManager.getRunningAppProcesses();
for(int i = 0; i < runningProcInfo.size(); i++){
if(runningProcInfo.get(i).processName.equals("vermel.BluetoothOn")) {
if (runningProcInfo.get(i).lru == RunningAppProcessInfo.IMPORTANCE_FOREGROUND){
//start activity
/* Intent it = new Intent();
it.setClassName("vermel.BluetoothOn", "vermel.BluetoothOn.BluetoothOnActivity");
context.startActivity(it); */
}
}
}
}
}
and i'm pointing to it from my broadcast receiver:
package vermel.BluetoothOn;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Button;
import android.widget.Toast;
public class BTDetector extends BroadcastReceiver {
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
public void onReceive(Context context , Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_POWER_CONNECTED)) {
if (!mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.enable();
//TODO if app is open, change text on button to on
//Toast.makeText(context, "turned on bluetooth", Toast.LENGTH_LONG).show();
Intent i = new Intent();
i.setClassName("vermel.BluetoothOn", "vermel.BluetoothOn.CheckIfAppIsRunningActivity");
context.startActivity(i);
}
} else if (action.equals(Intent.ACTION_POWER_DISCONNECTED)) {
if (mBluetoothAdapter.isEnabled()){
mBluetoothAdapter.disable();
//TODO if app is open, change text on button to off
//Toast.makeText(context, "turned off bluetooth", Toast.LENGTH_LONG).show();
Intent i = new Intent();
i.setClassName("vermel.BluetoothOn", "vermel.BluetoothOn.CheckIfAppIsRunningActivity");
context.startActivity(i);
}
}
}
}
a few things: yes, I know i'm not supposed to use .enable() without user permission. in a weird way, plugging in the phone IS my user permission, since this is ALL that this app does, so, it's not sneaky, since you know what you're getting when you're installing the app.
The commented stuff is mostly things i've tried in vain..
I'm very open to the fact that i'm making this WAY harder than I need to...
so, as i said, it does turn Bluetooth on and off beautifully, but simply crashes after that. I can't debug it, since the emulator doesn't have Bluetooth , and i'm disconnecting the phone to get the crash result, so, it's not logging anything, since it's now connected...
I'm new in both Java and Android, and would appreciate a bit of patience. I try reading the official android documentation, but that's like chinese to me... so, an extended explanation would be great...
Thanks for reading!