I asked a question similar to this yesterday but have changed my code a fair bit and have a different issue now.
I have a toggle button that sets an alarm manager with a pending intent that should trigger after 5 seconds. I have it on a one shot setting, so i want the message to appear once (as later I will be implementing this for a date value).
I get no errors with this code, but I cant seem to trigger my intent that then shows my toast message.
Here's how I have defined the activity of the 'DateAlarm' class in the xml:
<activity
android:name=".DateAlarm"
android:label="#string/app_name" >
<intent-filter>
<action android:name="com.example.flybase2.DateAlarm" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Heres my my toggle button onClick method for my toggle button with the alarm manager:
case (R.id.toggleButton1):
Integer dobMonth = setDate.getMonth();
Integer dobYear = setDate.getYear();
Integer dobDate = setDate.getDayOfMonth();
Date set;
set = new Date(dobYear - 1900, dobMonth, dobDate);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, DateAlarm.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
am.set(AlarmManager.RTC_WAKEUP,System.currentTimeMillis() + (5 * 1000), pendingIntent);
break;
And my final 'DateAlarm' class that holds the action of the intent.
package com.example.flybase2;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.widget.Toast;
public class DateAlarm extends Activity {
Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Toast.makeText(context, "Appointment is today", Toast.LENGTH_LONG).show();
}
}
You have two problems:
You are using PendingIntent.getService() instead of PendingIntent.getActivity() Since DateAlarm extends Activity, you want PendingIntent.getActivity().
In DateAlarm your context variable is null. In onCreate() you should initialize it. Also note that since Activity extends Context, this variable isn't needed. However if you do want to use that variable do:
super.onCreate(savedInstanceState);
context = this;
or
Context context = this; //right from the global declaration
Related
Goal: click the button to jump out of the notification, the user can jump from the notification to another page.
The notification is displayed but clicking the notification cannot jump to the page.
I think the PendingIntent is wrong.
How to fix it?
public class MainActivity extends AppCompatActivity {
private String CHANNEL_ID = "Coder";
NotificationManager manager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID, "DemoCode", NotificationManager.IMPORTANCE_DEFAULT);
manager = getSystemService(NotificationManager.class);
assert manager != null;
manager.createNotificationChannel(channel);
}
Button btDefault,btCustom;
btDefault = findViewById(R.id.button_DefaultNotification);
btCustom = findViewById(R.id.button_CustomNotification);
btDefault.setOnClickListener(onDefaultClick);
}
private final View.OnClickListener onDefaultClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent nextIntent = new Intent(MainActivity.this, secondActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 0, nextIntent,PendingIntent.FLAG_IMMUTABLE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this, CHANNEL_ID);
builder.setContentTitle("Notification");
builder.setContentText("You have a new message");
builder.setSmallIcon(R.drawable.ic_baseline_accessible_forward_24);
builder.setContentIntent(pendingIntent);
builder.setAutoCancel(true);
manager.notify(1, builder.build());
}
Check if this works for you. As mentioned in android api
You should consider user's expected navigation experience. So for making the best navigation using pendingIntent with Notification, you should do as follow:
1. First define your app's hierarchy inside AndroidManifest.xml:
<activity
android:name=".MainActivity"
... >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- MainActivity is the parent for SecondActivity -->
<activity
android:name=".SecondActivity"
android:parentActivityName=".MainActivity" />
...
</activity>
Now you told android that when a notification clicked, SecondActivity would be the child of MainActivity when user is navigating up.
2. Create PendingIntent using TaskStackBuilder:
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
PendingIntent pendingIntent = TaskStackBuilder.create(MainActivity.this)
.addNextIntentWithParentStack(intent)
.getPendingIntent(0, PendingIntent.FLAG_IMMUTABLE)
Then you can set the PendingIntent we created to the notification. And now if user touches the notification, android system will navigate him to SecondActivity while holding MainActivity in back stack.
I am writing my first app and I'm trying to fire a notification at a specific time every day that reports some information.
For starter, I created the following class that I use to restart the alarms after a reboot and to start the alarms from the main app (this to have just one piece of code to reuse).
public class SetAlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
startReminderService(context);
}
public void checkServiceRunning(Context context) {
Intent reminderIntent = new Intent(context, AlarmReceiver.class);
reminderIntent.setAction("MyReminder");
// I check if a reminder is already active
boolean reminderActive = (PendingIntent.getBroadcast(context, REMINDER_SERVICE,
reminderIntent,
PendingIntent.FLAG_NO_CREATE) != null);
Log.d("test", "The reminder is active?" + reminderActive);
if (!reminderActive) {
startReminderService(context);
}
}
public void startReminderService(Context context) {
Calendar serviceNotificationTime = Calendar.getInstance();
serviceNotificationTime.set(Calendar.HOUR_OF_DAY, 9);
serviceNotificationTime.set(Calendar.MINUTE, 0);
serviceNotificationTime.set(Calendar.SECOND, 0);
Intent reminderIntent = new Intent(context, AlarmReceiver.class);
reminderIntent.setAction("MyReminder");
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context,
REMINDER_SERVICE,
reminderIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager serviceAlarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
serviceAlarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
serviceNotificationTime.getTimeInMillis(),
AlarmManager.INTERVAL_DAY,
pendingIntent);
if (pendingIntent != null) {
Log.d("test", "Background service set up and running.");
} else {
Log.d("test", "Failed to set up background service!");
}
}
}
After that I updated the manifest with the following lines:
<receiver
android:name="com.mycompany.myapp.services.SetAlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver
android:name="com.mycompany.myapp.services.AlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="MyReminder" />
</intent-filter>
</receiver>
So far, everything goes right. When the phone reboots, the reminder is correctly restarted and (if the reminder time is in the past) it fires immediately.
The AlarmReceiver class is the following:
public class AlarmReceiver extends BroadcastReceiver {
private Context ctx;
#Override
public void onReceive(Context context, Intent intent) {
this.ctx = context;
remindStuff();
}
private void remindStuff() {
....
some code
....
// I check if the alarm is still on (probably awful, since it just fired)
SetAlarmReceiver setAlarmReceiver = new SetAlarmReceiver();
setAlarmReceiver.checkServiceRunning(ctx);
}
}
I use the same approach to check if the alarm is on from the main activity:
private void checkServicesRunning() {
SetAlarmReceiver setAlarmReceiver = new SetAlarmReceiver();
setAlarmReceiver.checkServiceRunning(getApplicationContext());
}
Everything looks correct to me, I've tried any solution I found, reading tons of questions like mine on StackOverflow but I still can't understand what I'm doing wrong.
The alarm fires correctly right after BOOT_COMPLETED is triggered by the system and it fires correctly when I just enabled the alarm (only if the notification time is in the past - f.e. when it's 10pm and the alarm must fire at 9am).
When the checkServiceRunning method runs, it tells me that the alarm is already enabled (returning true in the Logcat) but when I close the app and I re-run it after a while, the alarm looks like it's been canceled and it's being recreated by the app.
Any hint?
Thanks.
EDIT: I tried the command 'adb shell dumpsys alarm' and it actually shows my alarm running correctly so, at this point, I think the issue is something else but I cannot understand what...
I am using AlarmManager to create an alarm by playing a sound. To do this, I first create a PendingIntent, for which I have to create a class called AlarmReceiver, which extends BroadcastReceiver. In this new class, I override the onReceive method, in which I also start the sound. However, from what I've tested, the onReceive method is not even called from the MainActivity.
After some research, I found out that I should declare the receiver in the manifest file. Thus, I declare it, but it doesn't recognize the name of the class, AlarmReceiver, it shows it in red. I don't fully understand how to properly declare in the manifest file. I know there are other similar SO questions and I've checked them all, but I am still not able to get it work.
The code for the MainActivity is:
package com.example.alarmsound;
public class MainActivity extends AppCompatActivity {
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
final MediaPlayer mp = MediaPlayer.create(context, R.raw.music);
Log.d("Music", "It went here.");
mp.start();
Button stop = (Button) findViewById(R.id.stopAlarm);
stop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mp.stop();
}
});
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_main);
Calendar t = Calendar.getInstance();
t.add(Calendar.SECOND, 5);
Context context = this;
AlarmManager alarmMgr;
alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmMgr.set(AlarmManager.RTC_WAKEUP, t.getTimeInMillis(), pendingIntent);
}
}
And the declaration in Manifest is:
<receiver android:name="com.example.alarmsound.AlarmReceiver">
<intent-filter>
<action android:name="com.example.alarmsound.MainActivity" />
</intent-filter>
</receiver>
I could also be doing something wrong in the MainActivity, even though I think I'm doing everything right there.
Change the first line of the receiver declaration to:
<receiver android:name="com.example.alarmsound.MainActivity$AlarmReceiver">. That should let Android detect your class through the manifest.
The $ symbol is used to reference inner classes in the Android Manifest.
Okay. So as you mentioned the the AlarmReceiver class cannot be recognized in the AndroidManifest.xml. So I tried it out in Android Studio and it seems the format should be something like this:
<receiver android:name=".MainActivity$AlarmReceiver">
<intent-filter>
<action android:name="com.example.alarmsound.MainActivity" />
</intent-filter>
</receiver>
Tried running the code but it returns an error where the app crashes. Anyways, I think that's a different concern now.
I am attempting to convert some code I found in a tutorial for my own use. Originally, the code launched the system contacts list when the user would click a notification generated by my app. I am trying to start an Activity of my own instead of launching the contact list, but it's not working. More specifically, nothing happens. There is no error, and my Activity doesn't load either. The notification window disappears after clicking, and the original Activity is still visible.
Here is my code:
public class MyBroadcastReceiver extends BroadcastReceiver {
private NotificationManager mNotificationManager;
private int SIMPLE_NOTFICATION_ID;
public void onReceive(Context context, Intent intent){
Bundle extras = intent.getExtras();
String deal = (String) extras.get("Deal");
String title = "Deal found at " + (String) extras.get("LocationName");
mNotificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notifyDetails = new Notification(R.drawable.icon, title,System.currentTimeMillis());
Class ourClass;
try {
ourClass = Class.forName("com.kjdv.gpsVegas.ViewTarget");
Intent startMyActivity = new Intent(context, ourClass);
PendingIntent myIntent = PendingIntent.getActivity(context, 0,startMyActivity, 0);
notifyDetails.setLatestEventInfo(context, title, deal, myIntent);
notifyDetails.flags |= Notification.FLAG_AUTO_CANCEL;
notifyDetails.flags |= Notification.DEFAULT_SOUND;
mNotificationManager.notify(SIMPLE_NOTFICATION_ID, notifyDetails);
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
This is my entry in the AndroidManifext.xml file...
<activity android:name=".ViewTarget" android:label="#string/app_name" >
<intent-filter>
<action android:name="com.kjdv.gpsVegas.ViewTarget" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
And this is my Activity that I want to launch...
public class ViewTarget extends ListActivity {
public ListAdapter getListAdapter() {
return super.getListAdapter();
}
public ListView getListView() {
return super.getListView();
}
public void setListAdapter(ListAdapter adapter) {
super.setListAdapter(adapter);
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.locations);
Log.v("db", "Inside ViewTarget");
}
}
Which Android version are you running on? You might wanna try using NotificationCompat instead. This class is include in the latest support package.
Intent notificationIntent = new Intent(context, ViewTarget.class);
PendingIntent contentIntent = PendingIntent.getActivity(context,
0, notificationIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
NotificationManager nm = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Resources res = context.getResources();
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setContentIntent(contentIntent)
.setSmallIcon(R.drawable.app_icon)
.setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.app_icon))
.setTicker(payload)
.setWhen(System.currentTimeMillis())
.setAutoCancel(true)
.setContentTitle("Message")
.setContentText(payload);
Notification n = builder.getNotification();
n.defaults |= Notification.DEFAULT_ALL;
nm.notify(0, n);
EDIT:
I know this is an old thread/question but this answer helped me for showing the activity when tapping the notification.
For those people that this isn't working is probably because you haven't "registered" the activity in your manifest. For example:
<activity
android:name="com.package.name.NameOfActivityToLaunch"
android:label="Title of Activity" >
<intent-filter>
<action android:name="com.package.name.NAMEOFACTIVITYTOLAUNCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
And, hopefully, this should work.
Hope it helped...
you should set action and category for Intent.
Intent startMyActivity = new Intent(context, ourClass);
startMyActivity .setAction(Intent.ACTION_MAIN);
startMyActivity .addCategory(Intent.CATEGORY_LAUNCHER);
it works
I figured out the problem. I forgot to include the package name in the activity declaration in the Manifest file.
Wrong:
activity android:name=".ViewTarget" android:label="#string/app_name"
Correct:
activity android:name="com.kjdv.gpsVegas.ViewTarget" android:label="#string/app_name"
Can you try removing the Intent filter, so it looks like this:
<activity android:name=".ViewTarget" android:label="#string/app_name" />
Also, not sure if this code will work:
ourClass = Class.forName("com.kjdv.gpsVegas.ViewTarget");
Intent startMyActivity = new Intent(context, ourClass);
Can you try it like this instead:
Intent startMyActivity = new Intent(context, ViewTarget.class);
In order to launch an Activity from an Intent, you need to add a flag:
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
This is true even if you declare the class in the Intent's constructor.
check this code
public class TestActivity extends Activity {
private static final int UNIQUE_ID = 882;
public static NotificationManager nm;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Intent navigationIntent = new Intent();
navigationIntent.setClass(classname.this, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, navigationIntent,
0);
String body = "New notificattion added!!!";
String title = "Notification";
Notification n = new Notification(R.drawable.icon, body,
System.currentTimeMillis());
//this is for giving number on the notification icon
n.number = Integer.parseInt(responseText);
n.setLatestEventInfo(this, title, body, pi);
n.defaults = Notification.DEFAULT_ALL;
nm.notify(UNIQUE_ID, n);
I'm going by the following code example to dynamically build a preference activity.
http://www.linuxtopia.org/online_books/android/devguide/guide/samples/ApiDemos/src/com/example/android/apis/app/PreferencesFromCode.html
The preference dialog shows, but I'm not able to see any changes after closing it.
Here's where I'm defining the activity in AndroidManifest.xml
<activity
android:name="PreferencesActivity" android:label="#string/preferences_name">
</activity>
Here's where I'm defining the receiver.
<receiver
android:name="FroyVisualReceiver"
android:label="#string/app_name"
android:exported="false">
<intent-filter>
<action android:name="com.starlon.froyvisuals.PREFS_UPDATE"/>
</intent-filter>
</receiver>
And here's the BroadcastReceiver. I never see the "WTF" in logcat. What am I doing wrong?
package com.starlon.froyvisuals;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.Context;
import android.util.Log;
public class FroyVisualsReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Log.e("WTFWTF", "WTFWTFWTFW");
String action = intent.getAction();
if(action.equals("com.starlon.froyvisuals.PREFS_UPDATE"))
{
((FroyVisuals)context).updatePrefs();
}
}
}
Oh here's onPause where I'm broadcasting the PREFS_UPDATE intent.I do see the logcat message. This method is part of my PreferenceActivity.
/** another activity comes over this activity */
#Override
public void onPause()
{
Log.i(TAG, "onPause ================================ ");
super.onPause();
Intent i = new Intent(this, FroyVisualsReceiver.class);
i.setAction("com.starlon.froyvisuals.PREFS_UPDATE");
sendBroadcast(i);
}
Edit: I think it may have to do with this line. 'this' points to my PreferenceActivity.
Intent i = new Intent(this, FroyVisualsReceiver.class);
Try a simple Intent:
Intent i = new Intent();
i.setAction("com.starlon.froyvisuals.PREFS_UPDATE");
sendBroadcast(i);