Stop Service from PendingIntent after Notifcation is opened - android

I want the service to perform a stopForeground and a stopSelf after the notification is clicked followed by the running of pendingIntent.
I have tried using a BroadcastReceiver which is never called as I checked during debugging. I have added it to manifest as well.
Intent intentHide = new Intent(this, StopServiceReceiver.class);
PendingIntent hide = PendingIntent.getBroadcast(this, (int) System.currentTimeMillis(), intentHide, PendingIntent.FLAG_CANCEL_CURRENT);
Added it to the builder
builder.setContentIntent(hide);
And the Broadcast Rec is done separately -
public class StopServiceReceiver extends BroadcastReceiver {
public static final int REQUEST_CODE = 333;
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, TimerService.class);
context.stopService(service);
}
}
Manifest -
<receiver
android:name=".StopServiceReceiver"
android:enabled="true"
android:process=":remote" />
This is not working. The notification and the service both are alive.
Questions - Should I use addContent instead of setContentIntent ? If yes, then what should the parameters be ?
Is there anything I went wrong with? What could possibly be wrong with such kind of implementation? Thank you.

I had the same problem in the notification.
This code is working perfectly.
void creatnotifiaction()
{
public static final String STOP = "com.example.android";
public static final int REQUEST_CODE = 333;
filter = new IntentFilter();
filter.addAction(STOP);
Intent intentHide = new Intent(STOP);
PendingIntent hide = PendingIntent.getBroadcast(this,REQUEST_CODE,intentHide,PendingIntent.FLAG_CANCEL_CURRENT);
registerReceiver(broadcastReceiver, filter);
}
There no need to separate broadcast receiver use in same class.
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#SuppressLint("ResourceAsColor")
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
Log.d("notification", "Received intent with action " + action);
switch (action) {
case STOP:
//your code to stop notifications or service.
break;
}
});
Let me know if that work for you.
Thanks...Happy coding.

Related

How do I use Intent for working perfekt in Android Studio

I try to get a variable on my Android App from 1 Activite to an other.
Ther for I using Intent but I have a Problem with it and I can´t find any answer for it. When I lauch the programm it say´s me every time 90 no matter waht I do.
MainActivitie
`public class MainActivity extends AppCompatActivity {
public static final String EXTRA_NUMBER = "com.example.akkuapp.EXTRA_NUMBER";
int level;
public TextView battery;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
battery = (TextView) this.findViewById(R.id.textakku);
this.registerReceiver(this.mBatInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
AlarmManager alarmManager = (AlarmManager) MainActivity.this.getSystemService(ALARM_SERVICE);
Intent startServiceIntent = new Intent(MainActivity.this, Hintergrundservice.class);
PendingIntent startServicePendingIntent = PendingIntent.getService(MainActivity.this, 0, startServiceIntent, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
long time = calendar.getTimeInMillis();
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 5, startServicePendingIntent);
}
public final BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver() {
#SuppressLint("SetTextI18n")
#Override
public void onReceive(Context context, Intent intent) {
level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
battery.setText(String.valueOf(level) + '%');
intent.putExtra(EXTRA_NUMBER, level);
}
};
Backgroundservice
`
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
level = intent.getIntExtra(MainActivity.EXTRA_NUMBER,90);
Toast.makeText(getApplicationContext(), String.valueOf(level), Toast.LENGTH_LONG).show();
Log.d("Hintergrundprozess", String.valueOf(level));
return flags;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
Pictur MainActivity
Pictur Hintergrundprozess (Backgroundservice)
Thank you for your Help
There are many problems here. You are using startActivity() but passing an Intent for a Service (HintergrundService). To start a Service you need to call startService().
Also, getIntentOld() is a deprecated method of Intent and is probably not what you want. You already have the Intent as it is passed into onStartCommand(). Just use intent.getIntExtra():
intent.getIntExtra(MainActivity.EXTRA_NUMBER, 90);
EDIT: Add more data after seeing more code
You have used AlarmManager to schedule the triggering of an Intent to start your Service. In that Intent you have not put any extras. This is the reason that your Service doesn't get the "extra".
When your BroadcastReceiver is triggered and onReceive() is called, you extract the battery level from the incoming Intent and add an "extra" with that value back to the same incoming Intent. The value doesn't get magically copied into the Intent that you passed to AlarmManager. You should really find some tutorials and examples and learn more about how all this works.
In general, if your Service wants to get the battery level, it can just do this:
IntentFilter ifilter =
new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = context.registerReceiver(null, ifilter);
int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
You don't need to actually register a BroadcastReceiver. The battery changed Intent is a "sticky" Intent, which means that the last one broadcast is held by the Android framework and you can always ask for the last one that was broadcast.
See https://developer.android.com/training/monitoring-device-state/battery-monitoring for more information about monitoring the battery state.

Xamarin: Android Widget with timer, stops when app killed

I have this code:
public class MyWidgetProvider : AppWidgetProvider
{
public override void OnUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
Log.Debug("WIDGET", "Updating the widget");
// Open app on click
RemoteViews views = new RemoteViews(context.PackageName, Resource.Layout.MyWidget);
Intent launchAppIntent = new Intent(context, typeof(MainActivity));
PendingIntent launchAppPendingIntent = PendingIntent.GetActivity(context, 0, launchAppIntent, PendingIntentFlags.UpdateCurrent);
views.SetOnClickPendingIntent(Resource.Id.main, launchAppPendingIntent);
appWidgetManager.UpdateAppWidget(appWidgetIds[0], views);
// Start timer
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 1000;
timer.Elapsed += OnTimedEvent;
timer.Enabled = true;
}
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
Log.Debug("WIDGET", "Updating status...");
new Handler(Looper.MainLooper).Post(() =>
{
//Run my code to periodically update the widget
});
}
}
And I would like to know why following occurs:
When I drop the widget on phone screen, the timer starts to run, this is ok.
When I click on the widget the app starts, timer continues to run, this is ok.
When I click on back button the app goes to background, timer continues to run, this is ok.
When I terminate the app in task manager the timer stops, this is bad.
When I click on the widget again the app starts but the timer does not resume operation, this is bad.
The timer resumes operation only when next OnUpdate is called (I have the lowest possible interval 30 minutes), this is bad because I need frequent updating when the screen is on (or better when the widget is visible to the user).
I would like know the basics here as I could not find any relevant information. Why the timer runs when I first drop the widget on screen (without running app) and stops when the app gets killed?
Yes I have read almost everything about widget basics, then about using AlarmManager, Service, JobService, JobIntentService, JobScheduler etc. But I am interested in this solution with timer as it is very simple and works across all present Android versions (even newest Oreo). Things to solve yet are to stop the timer when the screen goes off and start it again when it goes on. To save the phone battery.
This is how I solved it:
public static class WidgetConsts
{
public const string DebugTag = "com.myapp.WIDGET";
public const string ActionWakeup = "com.myapp.WIDGET_WAKEUP";
public const string ActionWidgetUpdate = "android.appwidget.action.APPWIDGET_UPDATE";
public const string ActionWidgetDisabled = "android.appwidget.action.APPWIDGET_DISABLED";
}
[BroadcastReceiver]
[IntentFilter(new string[] { WidgetConsts.ActionWakeup })]
public class AlarmReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action.Equals(WidgetConsts.ActionWakeup))
{
Log.Debug(WidgetConsts.DebugTag, "Wakeup alarm called");
if (MyWidgetProvider.widgetTimer == null)
{
Log.Debug(WidgetConsts.DebugTag, "Widget updating does not run, enforcing update...");
MyWidgetProvider.UpdateAppWidget(context);
}
else
{
Log.Debug(WidgetConsts.DebugTag, "Widget updating runs, no action needed");
}
}
}
}
[BroadcastReceiver]
[IntentFilter(new string[] { WidgetConsts.ActionWidgetUpdate })]
[IntentFilter(new string[] { WidgetConsts.ActionWidgetDisabled })]
[MetaData("android.appwidget.provider", Resource = "#xml/widget_info")]
public class MyWidgetProvider : AppWidgetProvider
{
public static System.Timers.Timer widgetTimer = null;
public override void OnUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
Log.Debug(WidgetConsts.DebugTag, "Updating the widget");
// Open app on click
RemoteViews views = new RemoteViews(context.PackageName, Resource.Layout.MyWidget);
Intent launchAppIntent = new Intent(context, typeof(MainActivity));
PendingIntent launchAppPendingIntent = PendingIntent.GetActivity(context, 0, launchAppIntent, PendingIntentFlags.UpdateCurrent);
views.SetOnClickPendingIntent(Resource.Id.main, launchAppPendingIntent);
appWidgetManager.UpdateAppWidget(appWidgetIds[0], views);
// set timer for updating the widget views each 5 sec
if (widgetTimer == null)
{
widgetTimer = new System.Timers.Timer();
widgetTimer.Interval = 5000;
widgetTimer.Elapsed += OnTimedEvent;
}
widgetTimer.Enabled = true;
// set alarm to wake up the app when killed, each 60 sec
// needs a fresh BroadcastReceiver because AppWidgetProvider.OnReceive is
// not virtual and overriden method in this class would not be called
AlarmManager am = (AlarmManager)context.GetSystemService(Context.AlarmService);
Intent ai = new Intent(context, typeof(AlarmReceiver));
ai.SetAction(WidgetConsts.ActionWakeup);
PendingIntent pi = PendingIntent.GetBroadcast(context, 0, ai, PendingIntentFlags.CancelCurrent);
am.SetRepeating(AlarmType.ElapsedRealtime, SystemClock.ElapsedRealtime(), 1000 * 60, pi);
}
public override void OnDisabled(Context context)
{
Log.Debug(WidgetConsts.DebugTag, "Disabling the widget");
if (widgetTimer != null)
{
Log.Debug(WidgetConsts.DebugTag, "Stopping timer");
widgetTimer.Enabled = false;
}
else
Log.Debug(WidgetConsts.DebugTag, "Timer is null");
base.OnDisabled(context);
}
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
Log.Debug(WidgetConsts.DebugTag, "Updating status...");
new Handler(Looper.MainLooper).Post(() =>
{
//Run my code to periodically update the widget
RemoteViews views = new RemoteViews(Application.Context.PackageName, Resource.Layout.MyWidget);
AppWidgetManager manager = AppWidgetManager.GetInstance(Application.Context);
ComponentName thisWidget = new ComponentName(Application.Context, Java.Lang.Class.FromType(typeof(MyWidgetProvider)));
int[] appWidgetIds = manager.GetAppWidgetIds(thisWidget);
views.SetTextViewText(Resource.Id.myText, "my text");
manager.UpdateAppWidget(appWidgetIds[0], views);
});
}
static public void UpdateAppWidget(Context context)
{
Intent intent = new Intent(context, typeof(MyWidgetProvider));
intent.SetAction(WidgetConsts.ActionWidgetUpdate);
int[] ids = AppWidgetManager.GetInstance(context).GetAppWidgetIds(new ComponentName(context, Java.Lang.Class.FromType(typeof(MyWidgetProvider))));
intent.PutExtra(AppWidgetManager.ExtraAppwidgetIds, ids);
context.SendBroadcast(intent);
}
}
Pros:
Simple solution, works on all Android systems (tested on 3.2, 4.3, 8.1).
Battery friendly on Android systems >= 6.0 with doze mode (measured with GSam Battery monitor). Not restricted by the new background execution limits in >=8.0.
Cons:
Drains battery on systems below 6.0 without doze mode, but no one cares about these today...
First,You can try to make the Widget app not be skilled.
The widget itself will not be killed. The widget is originally a broadcastreciver, and it is static. This means that a subscribed broadcast widget can be received at any time, and the onReceive() method will be called. The reason why widgets can't be run is that they should be killed for the corresponding service. If want the widget to run all the time, the service should when be killed and be restarted.
Service is a component of the Android system, it is similar to the level of Activity, but he can not run by himself, can only run in the background, and can interact with other components.
In the Android development process, each time the startService (Intent) is called, the OnStartCommand(Intent, int, int) method of the Service object is called, and then some processing is done in the onStartCommand method.
1,Create the servide not be killed
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
return START_STICKY_COMPATIBILITY;
//return super.onStartCommand(intent, flags, startId);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
flags = START_STICKY;
return super.onStartCommand(intent, flags, startId);
// return START_REDELIVER_INTENT;
}
#Override
public void onStart(Intent intent, int startId)
{
// again regsiter broadcast
IntentFilter localIntentFilter = new IntentFilter("android.intent.action.USER_PRESENT");
localIntentFilter.setPriority(Integer.MAX_VALUE);// max int
myReceiver searchReceiver = new myReceiver();
registerReceiver(searchReceiver, localIntentFilter);
super.onStart(intent, startId);
}
2,Restart the Service in the Service's onDestroy().
public void onDestroy()
{
Intent localIntent = new Intent();
localIntent.setClass(this, MyService.class); // restart Service
this.startService(localIntent);
}
3,create a broadcast and regsiter in XML
public class myReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
context.startService(new Intent(context, Google.class));
}
}
<receiver android:name=".myReceiver" >
<intent-filter android:priority="2147483647" ><!--Priority plus highest-->
<!-- when applicayion lauch invoke -->
<action android:name="android.intent.action.BOOT_COMPLETED" />
<!-- unlock invole -->
<action android:name="android.intent.action.USER_PRESENT" />
<!--context switch -->
<action android:name="android.media.RINGER_MODE_CHANGED" />
</intent-filter>
</receiver>
<service android:name=".MyService" >
Note: Unlock, start, switch scene activation broadcast needs to add permissions, such as startup completion, and mobile phone status.
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
==================================================================
Second, If Widget app not be skilled, you can listen to screen is lock or unlock.
Custom a ScreenListener and add ScreenBroadcastReceiver
private class ScreenBroadcastReceiver extends BroadcastReceiver {
private String action = null;
#Override
public void onReceive(Context context, Intent intent) {
action = intent.getAction();
if (Intent.ACTION_SCREEN_ON.equals(action)) { // screen on
mScreenStateListener.onScreenOn();
} else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // screen off
mScreenStateListener.onScreenOff();
} else if (Intent.ACTION_USER_PRESENT.equals(action)) { // screen unlock
mScreenStateListener.onUserPresent();
}
}
}
so that you can do with Timers or other showing with customer.
==============================================================================
More info:
This method not the best, there are more places to improve,just give a suggestion.

How to update widget manually?

I want to update widget manually. So, I add in an AndroidManifest filter:
<action android:name="com.myapp.WIDGET_UPDATE"/>
And I try to send broadcasts from adb console like this
am broadcast -a com.myapp.WIDGET_UPDATE
But nothing happens. Here is the code from onReceive:
public class myapp extends AppWidgetProvider {
private final static IntentFilter intentFilter = new IntentFilter("com.myapp.WIDGET_UPDATE");
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
updateWidget(context);
}
};
}
you have to put one button in layout_wid.xml file.
in onUpdate() you have to find the id of your button.and put click event to refresh your widget
Intent imageview2Intent= new Intent(context, WatchWidget.class);
PendingIntent pendingIntent= PendingIntent.getBroadcast(context,0, imageview2Intent,0);
remoteViews.setOnClickPendingIntent(R.id.widget_textview, pendingIntent);
you try this way.

Multiple custom broadcasting (how to handle)

I want to add a custom broadcast receiver to my app. and I have 3 methods that should do the broadcast. and in my onReceive method i want to identify which method did the broadcast. I have 3 methods like this
public void method01(View v){
int flag = 1;
Intent intent = new Intent();
intent.addFlags(flag);
broadcastIntent(intent);
}
public void method02(){
int flag = 2;
Intent intent = new Intent();
intent.addFlags(flag);
broadcastIntent(intent);
}
public void method03(){
int flag = 3;
Intent intent = new Intent();
intent.addFlags(flag);
broadcastIntent(intent);
}
and this is my broadcastIntent method
public void broadcastIntent(Intent intent){
sendBroadcast(intent);
}
in my onReceive method i use getFlags() method to get the flag value from the intent and send it through a if, else. but this do not work. any suggestion for improvements are welcome.
You can also use Actions to identify each one of you Intent objects.
String action1 = "first_sender";
String action2 = "second_sender";
Intent createIntent01(){
Intent intent01 = new Intent();
intent01.setAction(action1);
return intent01;
}
Intent createIntent02(){
Intent intent02 = new Intent();
intent01.setAction(action2);
return intent02;
}
And in your onReceive method you can use the getAction() method of intents to check which action was sent. This is in case you're not already using Actions.
[[EDIT]]
To register a BroadcastReceiver you need to define an IntentFilter and register the actions you wish to receive this way:
mBroadcastReceiver broadcastReceiver = new mBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(action1);
intentFilter.addAction(action2);
registerReceiver(broadcastReceiver,intentFilter);
class mBroadcastReceiver extends BroadcastReceiver{
public void onReceive(Context arg0, Intent arg1){
String action = arg1.getAction();
if(action.equals(action1)){
//do something
}else if(action.equals(action2)){
//do something else
}
}
The first problem is that ypu didn't specify a target for your intent. You can use intent filters and actions like rodkarom suggested or specify receiver's class directly (see in my example). In both cases you need either to declare your broadcast receiver in AndroidManifest.xml, or register it at runtime (see rodkarom's answer for a sample).
The method addFlags is used to specify some internal properties of Intent (like start activity corresponding to this intent in a new task) , so you cannot use it for your own data. The list of possible flags is in the documentation for setFlags method.
You can use putExtra to achieve your goal:
// an Activity is just an example
public class SenderActivity extends Activity {
// ...
void method01() {
int flag = 1;
Intent intent = new Intent(getApplicationContext(), Receiver.class); // any Context is acceptable here
intent.putExtra(MyReceiver.EXTRA_FLAG, flag); // any string will do well, you just need it to be the same here and in getExtra later
sendBroadcast(intent);
}
}
public class MyReceiver extends BroadcastReceiver {
public static final String EXTRA_FLAG = "your.package.name.EXTRA_FLAG";
// and in onReceive
public void onReceive (Context context, Intent intent) {
int flag = intent.getIntExtra(EXTRA_FLAG, someDefaultValue);
if (flag == 1) {
// ...
}
// ...
}
}
I found out the way to this and thought of sharing the code. this is the broadcasting done in my main activity for 2 different methods.
public void method1(View view){
Intent intent = new Intent();
intent.setAction("method1");
sendBroadcast(intent);
}
public void method2(View view){
Intent intent = new Intent();
intent.setAction("method2");
sendBroadcast(intent);
}
and this is how i receive it..
public class Receiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Broadcast Intent Detected.",Toast.LENGTH_LONG).show();
}
this is how i registered it on manifest.
<receiver android:name="Receiver" >
<intent-filter>
<action android:name="method1" >
</action>
<action android:name="method2" >
</action>
</intent-filter>
</receiver>
Hope this will help if any one else came up with similar problem. and big thank you to every one who posted their answers here.

addAction() & Service calling Dilemma

I'm stuck here at my previous struggle >> Prev. Struggle!
Raanan there helped! me a lot but then he I think went away as timing zone is different , now I'm stuck with my service code that I'm using to call my BroadcastReceiver() that is in the activity! and also I'm not getting with what parameter I should load the filter.addAction(action); in place of action??
Kinldy guide me!
CODE in the Server:
Toast.makeText(Server.this, hr +" , " +min, Toast.LENGTH_LONG).show();
Intent intent = new Intent(this, andRHOME.class);
//intent.putExtra("sendMessage","1");
sendBroadcast(intent);
and CODE IN THE ACITIVITY(Broadcast Receiver)
private BroadcastReceiver ReceivefrmSERVICE = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "IN DA BroadCASTER",
Toast.LENGTH_LONG).show();
sendMessage("1");
}
};
IntentFilter filter = new IntentFilter();
You need to add these line to regiester your receiver for some action for example define a Global variable like this:
public static String NOTIFCATION_BROADCAST_ACTION = "com.your_packagename.UPDATE_NOTIFICATION_INTENT";
then register the action like this in your activity onCreate() Method.
IntentFilter filter = new IntentFilter();
filter.addAction(Global.NOTIFCATION_BROADCAST_ACTION);
registerReceiver(ReceivefrmSERVICE, filter);
Then send the broadcast from your service like this
Intent broadcast = new Intent();
broadcast.setAction(Global.NOTIFCATION_BROADCAST_ACTION);
sendBroadcast(broadcast);
Then in your broadcast Receiver filter this action like this
private BroadcastReceiver ReceivefrmSERVICE = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Global.NOTIFCATION_BROADCAST_ACTION)) {
//Do your stuff here :)
}
}
};

Categories

Resources