My app has a service that add a floating button to WindowManager.
I want to remove my floating button from WindowManager When user press the power key and turn screen off. So when user turn screen on my floating button does not conceal (mask) android pattern screen lock.
I add following code to my Service but it doesn't work !
Should I add any permission or my service must run in background?!
public class Receiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF))
{
try{
// Remove Floating Button from Window Manager
MyWindowManager.removeView(floating_btn);
// Stop Service
stopSelf();
}
catch (Exception e)
{
//Log Error
}
}
}
}
Normally you would declare a receiver in your manifest. Something like this
<receiver android:name="com.whatever.client.Receiver"
<intent-filter>
<action android:name="android.intent.action.SCREEN_OFF" />
</intent-filter>
</receiver>
For some reason (not sure why), you don't seem to be able to do this for SCREEN_OFF or SCREEN_ON. So you have to register it programmatically.
As a test, I made a simple app.
public class App extends Application {
#Override
public void onCreate() {
super.onCreate();
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
startService(new Intent(context, MyService.class));
}
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(receiver, filter);
}
}
With a simple service.
public class MyService extends IntentService {
public MyService() {
super("MyService");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.e("MyService", "Screen was turned off!");
}
}
I've got the same problem and I'm working on it now. In your case it didn't work because 1) your "stopSelf()" have to in class extended by Service, not by BroadcastReceiver. 2) if you want to remove a view from window manager you have to somehow pass(the information of view) that view from that method where you'd declared it to method where you want to remove that view
Related
So I've been trying to build a music player app and despite visiting all pages on stackoverflow I'm still stuck on one issue. The code works fine for the most part, but when I press the back button to close the app the action buttons stop working, even though they work fine when I press the home button. I think the broadcast receiver is getting unregistered when the app is closed even though I don't want it to. Here is the code:
public BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getExtras().getString("actionname");
Helper.makeToast(context, action);
switch (action) {
case CreateNotification.ACTION_PREVIUOS:
//play previous
case CreateNotification.ACTION_PLAY:
if (isPlaying) {
//pause
} else {
// play
}
break;
case CreateNotification.ACTION_NEXT:
//play next
}
}
};
This is the onresume method on main activity
#Override
protected void onResume() {
super.onResume();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
registerReceiver(broadcastReceiver, new IntentFilter("TRACKS_TRACKS"));
startService(new Intent(getBaseContext(), OnClearFromRecentService.class));
}
}
This is the Service
public class OnClearFromRecentService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY_COMPATIBILITY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public void onTaskRemoved(Intent rootIntent) {
stopSelf();
}
}
In the manifest:
<receiver .services.OnClearFromRecentService" />
So my questions are: Is the broadcastreceiver automatically unregistered when I close the app? If so, how do I prevent this? How do I keep the broadcast receiver working when I close the app?
This type of receivers unregister automatically when you close your app. This is right. However you have to unregister from your receiver in onStop(). Because if you don't do this you are going to get LeakIntentMemory error message in your LogCat but your app don't crashes. You can check it from your logcat. I think that if you want to receive something when your app closed, you have to declare your receiver in AndroidManifest with an action name.
<receiver android:name=".YourReceiver" >
<intent-filter>
<action android:name="first.custom.action"> </action>
</intent-filter>
</receiver>
First,I have searched for the question and found about 2-3 stackoverflow links but I dont get a definite answer.Basically,my app needs to start a activity when the phone is docked (any type of dock) or when screen is off.I registered a broadcast receiver in manifest:
<receiver android:name=".BootReciever">
<intent-filter >
<action android:name="android.intent.action.ACTION_DOCK_EVENT"/>
<action android:name="android.intent.action.SCREEN_OFF"/>
</intent-filter>
</receiver>
And in my class:
public class BootReciever extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(Intent.ACTION_DOCK_EVENT)){
//work for dock
}
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
//work for screen off
}
}
}
But both doesnt work.My work is not done is both the cases.I read about I have to do it in services but since I have never worked with my own service and I fell android.developers.com is a bit of pro friendly,I have difficulty getting it to work.Can somebody say me how to I achieve the above?And my app has to listen for it as long service.So even when my app isnt in foreground.Thanks for your help.
The SCREEN_OFF has definitely to be registered programatically (see this link for instance, it'a a protected intent):
public class MainActivity extends Activity {
BroadcastReceiver receiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("TAG", "on or off");
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
Log.d("TAG", "Register receiver");
registerReceiver(receiver, filter);
} catch (Exception e) {
Log.d("TAG", "Caught: " + e.getStackTrace());
}
}
#Override
public void onDestroy() {
super.onDestroy();
try {
Log.d("TAG", "Unregister receiver");
unregisterReceiver(receiver);
} catch (Exception e) {
Log.d("TAG", "Caught: " + e.getStackTrace());
}
}
}
For the ACTION_DOCK_EVENT I would assume something else being wrong. May be it doesn't work due to the combination with ACTION_SCREEN_OFF, may be it's due to a naming issue (I wouldn't expect a relative path for .BootReciever, for instance; check, if a full qualified class name works).
Hope this helps .... Cheers!
Receivers for these kinds of intents need to be registered dynamically in the code.
this.receiver = new BootReceiver();
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_DOCK_EVENT);
this.registerReceiver(receiver, filter);
You could do this in any activity (register in onStart(), un-register in onStop(), see visible lifetime section) or in you application object.
The problem with dynamic registration though is your application has to be started before BootReceiver can receive intents.
I managed to get my headset buttons get recognized by my app when pressed, but one of the buttons needs to call a method that's in MyCustomActivity. The problem is onReceive's 1st parameter is a Context that cannot be cast to Activity and so I am forced to implement my BroadcastReceiver as an inner class inside MyCustomActivity.
So far so good but how do I register this inner MediaButtonEventReceiver in the manifest?
For the independent class, this was simple:
<receiver android:name=".RemoteControlReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
What is the trick/syntax to do the same for MyCustomActivity's mReceiver?
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context ctx, Intent intent) {
// ...
}
}
You don't, if it's meant to be part of the Activity, you register it dynamically:
BroadcastReceiver receiver;
#Override
protected void onCreate (Bundle b)
{
super.onCreate (b);
IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);
filter.setPriority(10000);
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context ctx, Intent intent) {
// ...
}
};
registerReceiver (receiver, filter);
}
Then don't forget to unregister in onPause() (to avoid leaking).
#Override
protected void onPause()
{
try{
unregisterReceiver (receiver);
}
catch (IllegalStateException e)
{
e.printStackTrace();
}
super.onPause();
}
This dynamic registration does mean however, that if your Activity isn't in the foreground, the button won't work. You can try unregistering in onDestroy() instead, but the surest way to avoid leaking is onPause().
Alternatively, to make the button respond no matter what, consider making a Service, and having that register your receiver.
So far so good but how do I register this inner MediaButtonEventReceiver in the manifest?
You can't. You can register it dynamically by calling registerReceiver() on the activity, though.
I am using broadcast receiver in my app to detect incomming call and it works fine. But problem is I can not send action to activity. I mean.. I want do something in activity not in receiver. I read many tutorial but they all are performing action in receiver. Any idea ?
You can declare a BroadcastReceiver as inner class of the Activity. In this case you can directly call activity's methods:
public class MyActivity extends Activity {
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
activityMethod();
}
};
private final IntentFilter filter = new IntentFilter("android.intent.action.PHONE_STATE");
#Override
protected void onStart() {
super.onResume();
registerReceiver(receiver, filter);
}
#Override
protected void onStop() {
super.onPause();
unregisterReceiver(receiver);
}
private void activityMethod() {
}
}
You can start the Activity using an Intent and put a command code in the Intent extra fields. In your Activity you can then decide the behaviour based on the command code or resort to a default behaviour if none is present.
You can start an activity from your receiver via the normal means:
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, YourActivity.class);
startActivity(i);
}
Note though that the user is going to expect that the phone application starts up since they are receiving a phone call. It is very likely a bad idea to hijack the phone call by dumping your own activity on top of the stock dialer app.
I'm using BroadcastReceiver class in android to get information about network change
using the following code:
class NetworkStatus extends BroadcastReceiver{
......
#Override
public void onReceive(Context context, Intent intent) {
}
public void startBroadCastReceiver()
{
}
public void StopBroadCastReceiver()
{
}
I want to stop the broadcast receiver and then start it again
How can I do this
Broadcast receiver likes event handler, Android system calls it automatically when a broadcast matches you defined intent. If you define the boardcast receiver in manifast file, I think the only way you can do it to return immediately when you don't want to handle the broadcast, like the following:
public void onReceive(Context context, Intent intent) {
if (stoppedBroadcast)
return;
// handle broadcast.
}
public void stopBroadcast {
stoppedBroadcast = true;
}
public void resumeBroadcast {
stoppedBroadcast = false;
}
If you want to stop recieving network changes try unregisterReciever in your registering activity/service.
When you want to enable recieving register the reciever with its IntentFilter again.