I made a custom layout for my notification, it has two buttons one for play and one for pausing the music. When i click on each button a broadcast is sent to the respective class.
Now i want to keep only one button and (toggle)change the icon of the button when the user taps the button from play to pause and vice versa, I tried several things to change the icon(my real problem) but failed so far.
In PlayerActivity.java I displays the notification by calling this line.
NotificationGenerator.customBigNotification(getApplicationContext());
Here is the code of NotifcationGenerator :
package com.example.user.musicplayer;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.support.v4.app.NotificationCompat;
import android.widget.RemoteViews;
public class NotificationGenerator {
private static final int NOTIFICATION_ID_OPEN_ACTIVITY = 1;
private static final int NOTIFICATION_ID_CUSTOM_BIG = 1;
public static void customBigNotification(Context context){
RemoteViews expandedView = new RemoteViews(context.getPackageName(), R.layout.big_notification);
NotificationCompat.Builder nc = new NotificationCompat.Builder(context);
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notifyIntent = new Intent(context, PlayerActivity.class);
notifyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
notifyIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
String id = "mymusicplayer";
CharSequence name = "player";
String description = "player";
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel mChannel = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
mChannel = new NotificationChannel(id, name, importance);
mChannel.setDescription(description);
mChannel.enableLights(true);
mChannel.setLightColor(Color.RED);
mChannel.enableVibration(true);
mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
nm.createNotificationChannel(mChannel);
}
nc.setContentIntent(pendingIntent);
nc.setSmallIcon(R.drawable.ic_action_play);
nc.setAutoCancel(true);
nc.setCustomBigContentView(expandedView);
nc.setContentTitle("Music Player");
nc.setContentText("Control Audio");
nc.getBigContentView().setTextViewText(R.id.textSongName, "Lorem Ipsum Dolor");
setRemoteViews(expandedView, context);
nm.notify(NOTIFICATION_ID_CUSTOM_BIG, nc.setChannelId(id).build());
}
private static void setRemoteViews(RemoteViews remoteViews, Context c) {
// call broadcast when any control of notification is clicked.
Intent playIntent = new Intent(c, PlayBroadcast.class);
PendingIntent playPendingIntent = PendingIntent.getBroadcast(c, 0, playIntent, 0);
// Using RemoteViews to bind custom layouts into Notification
remoteViews.setOnClickPendingIntent(R.id.btnPlay, playPendingIntent);
// call broadcast when any control of notification is clicked.
Intent pauseIntent = new Intent(c, PauseBroadcast.class);
PendingIntent pausePendingIntent = PendingIntent.getBroadcast(c, 0, pauseIntent, 0);
// Using RemoteViews to bind custom layouts into Notification
remoteViews.setOnClickPendingIntent(R.id.btnPause, pausePendingIntent);
}
}
Here is the code of PlayBroadCast.java : (where the broadcast from the play button is received) :
package com.example.user.musicplayer;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
public class PlayBroadcast extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
MediaPlayer mP = PlayerActivity.mediaPlayer;
if(!mP.isPlaying()){
mP.start();
}
}
}
Pardon me if the explanation is not clear, because if i might have the correct words to explain it. I would have googled it. Thanks in advance.
Try this:
expandedLayout.setInt(R.id.notif_button_play, "setImageResource", R.drawable.ic_play)
In my case the view was ImageButton, so I changed the icon through "setImageResource". You can set the function name of your view.
Related
In my app(java) I am getting values from two different crypto Exchange. Then doing some calculation and getting output values. Values are refreshing every second. Now I want to set alert/notification whenever output values is greater than specific value. I want this whenever app is closed or running. How to do that because I am not able to do that when app is closed? Thanks.
You have to use Foreground Service to enable notification even when app is closed .
According to AndroidDevelopers,
Foreground services perform operations that are noticeable to the
user. Each foreground service must show a status bar notification that
has a priority of PRIORITY_LOW or higher. That way, users are actively
aware that your app is performing a task in the foreground and is
consuming system resources.
https://developer.android.com/guide/components/foreground-services
Example of code from Programmer'sWorld, to create foreground services and notification in your Android App
package com.example.myserviceclass;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.os.IBinder;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
public class MyService extends Service {
private Integer alarmHour;
private Integer alarmMinute;
private Ringtone ringtone;
private Timer t = new Timer();
private static final String CHANNEL_ID = “MyNotificationChannelID”;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
alarmHour = intent.getIntExtra(“alarmHour”, 0);
alarmMinute = intent.getIntExtra(“alarmMinute”, 0);
ringtone = RingtoneManager.getRingtone(getApplicationContext(), RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE));
try {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID )
.setContentTitle(“My Alarm clock”)
.setContentText(“Alarm time – ” + alarmHour.toString() + ” : ” + alarmMinute.toString())
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, “My Alarm clock Service”, NotificationManager.IMPORTANCE_DEFAULT);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(notificationChannel);
}
catch (Exception e){
e.printStackTrace();
}
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if (Calendar.getInstance().getTime().getHours() == alarmHour &&
Calendar.getInstance().getTime().getMinutes() == alarmMinute){
ringtone.play();
}
else {
ringtone.stop();
}
}
}, 0, 2000);
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
ringtone.stop();
t.cancel();
super.onDestroy();
}
}
package com.example.myserviceclass;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.widget.TimePicker;
public class MainActivity extends AppCompatActivity {
private TimePicker timePicker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.FOREGROUND_SERVICE}, PackageManager.PERMISSION_GRANTED);
timePicker = findViewById(R.id.timPicker);
final Intent intent = new Intent(this, MyService.class);
ServiceCaller(intent);
timePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
#Override
public void onTimeChanged(TimePicker timePicker, int i, int i1) {
ServiceCaller(intent);
}
});
}
private void ServiceCaller(Intent intent){
stopService(intent);
Integer alarmHour = timePicker.getCurrentHour();
Integer alarmMinute = timePicker.getCurrentMinute();
intent.putExtra(“alarmHour”, alarmHour);
intent.putExtra(“alarmMinute”, alarmMinute);
startService(intent);
}
}
<?xml version=”1.0″ encoding=”utf-8″?>
<manifest xmlns:android=”http://schemas.android.com/apk/res/android”
package=”com.example.myserviceclass”>
<uses-permission android:name=”android.permission.FOREGROUND_SERVICE”/>
<application
android:allowBackup=”true”
android:icon=”#mipmap/ic_launcher”
android:label=”#string/app_name”
android:roundIcon=”#mipmap/ic_launcher_round”
android:supportsRtl=”true”
android:theme=”#style/AppTheme”>
<service android:name=”.MyService”/>
<activity android:name=”.MainActivity”>
<intent-filter>
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>
</application>
</manifest>
You can do with Notification setting.
first go in setting,
then in notification setting ,
on notification for your app.
Thank you
For this purpose, you can create a foreground service running. This way, you'll be able to notify the user even after he has exited out from the App.
Reference : https://developer.android.com/guide/components/foreground-services?authuser=1
I tried to make notifications but there is no notifications when I click the button, nor errors.
I enabled the notification from phone setting.
my code
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class notification_page extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notification_page);
// Button notify = findViewById(R.id.notify);
}
NotificationManager manager;
int id =0;
public void notify(View view) {
NotificationCompat.Builder nBuilder = new NotificationCompat.Builder(this);
nBuilder.setContentTitle("Hello").setContentText("Notificaction!!").setSmallIcon(R.drawable.common_google_signin_btn_icon_dark);
manager= (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(id,nBuilder.build());
id++;
}
public void cancel(View view) {
manager.cancelAll();
}
}
XML button android:onClick="notify"
and there is no errors in the Logcat
First of all you have to create the notification channel:
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel("1000", "channel_name", importance);
channel.setDescription("channel_description");
channel.setSound(null, null);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
Change the NotificationManager to be:
NotificationManagerCompat manager;
then modify your notify() function like this:
public void notify(View view) {
createNotificationChannel(); //don't forget to create the channel
NotificationCompat.Builder nBuilder = new NotificationCompat.Builder(this, "1000"); //channelId should be same as the one created above
nBuilder.setContentTitle("Hello").setContentText("Notificaction!!").setSmallIcon(R.drawable.common_google_signin_btn_icon_dark);
manager = NotificationManagerCompat.from(getApplicationContext());
manager.notify(id, nBuilder.build());
id++;
}
I'm trying to make notification with a countdown timer.
Am I doing wrong?
I try to update information inside notification using a countdown timer.
If the screen doesn't lock it works correctly. But in case of locked, my screen turns on each notification (so each second). So timer working correctly but it's very annoying that each second makes my screen turning on.
package com.example.yanec.schedulekpi;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.CountDownTimer;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.util.Log;
import com.example.yanec.schedulekpi.Activities.MainActivity;
import com.example.yanec.schedulekpi.Fragments.DetailScheduleInfoFragment;
public class ServiceShowNotification extends BroadcastReceiver {
CountDownTimer countDownTimer;
long timeLeft;
NotificationCompat.Builder mBuilder;
NotificationManagerCompat notificationManager;
#Override
public void onReceive(final Context context, final Intent intent) {
Log.d("myLogs", "OnReceive");
timeLeft = intent.getLongExtra(Constants.INTENT_PASS_DATE, 0);
showNotification(intent, context, Parser.toStringFrom(timeLeft));
countDownTimer = new CountDownTimer(timeLeft, Constants.COUNT_DOWN_INTERVAL) {
#Override
public void onTick(long millisUntilFinished) {
timeLeft -= Constants.COUNT_DOWN_INTERVAL;
mBuilder.setContentText(Parser.toStringFrom(timeLeft));
mBuilder.setVisibility(Notification.VISIBILITY_PUBLIC);
notificationManager.notify(Constants.NOTIFICATION_ID, mBuilder.build());
}
#Override
public void onFinish() {
DetailScheduleInfoFragment.isServiceWorking = false;
}
};
countDownTimer.start();
}
private void showNotification(Intent intent, Context context, String time){
Intent intent1 = new Intent(context, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent1, 0);
mBuilder = new NotificationCompat.Builder(context, Constants.CHANNEL_ID)
.setSmallIcon(R.drawable.ic_bar)
.setContentTitle(intent.getStringExtra(Constants.INTENT_PASS_NAME))
.setContentText(time)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
mBuilder.setVisibility(Notification.VISIBILITY_PUBLIC);
notificationManager = NotificationManagerCompat.from(context);
notificationManager.notify(Constants.NOTIFICATION_ID, mBuilder.build());
}
}
If my screen is locked and I'm updating notification, my screen doesn't wake up. But if I wake up the screen by myself (don't unlock just wake up using wakeUp button), it shows me updated info. Thanks.
I have begun trying to develop an android app to use with the new estimote proximity beacons and I was following this guide to show "enter" notification when in range of the beacon. http://developer.estimote.com/android/tutorial/part-2-background-monitoring/
Everything is set correctly such as the UUID and declared the class in the AndroidManifest.xml file but the notification is not working.. Maybe I don't have the code order correct?
This is the BeaconChecker.java class (In the tutorial they call it MyApplication.java):
package com.mcrlogs.pp.test;
/**
* Created by usr on 15/01/2017.
*/
import android.app.Application;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import com.estimote.sdk.Beacon;
import com.estimote.sdk.BeaconManager;
import com.estimote.sdk.Region;
import java.util.List;
import java.util.UUID;
public class BeaconChecker extends Application {
private BeaconManager beaconManager;
public void showNotification(String title, String message) {
Intent notifyIntent = new Intent(this, MainActivity.class);
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivities(this, 0,
new Intent[] { notifyIntent }, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new Notification.Builder(this)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.build();
notification.defaults |= Notification.DEFAULT_SOUND;
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, notification);
}
#Override
public void onCreate() {
super.onCreate();
beaconManager = new BeaconManager(getApplicationContext());
beaconManager.setMonitoringListener(new BeaconManager.MonitoringListener() {
#Override
public void onEnteredRegion(Region region, List<Beacon> list) {
showNotification(
"Your gate closes in 47 minutes.",
"Current security wait time is 15 minutes, "
+ "and it's a 5 minute walk from security to the gate. "
+ "Looks like you've got plenty of time!");
}
#Override
public void onExitedRegion(Region region) {
// could add an "exit" notification too if you want (-:
}
});
beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
#Override
public void onServiceReady() {
beaconManager.startMonitoring(new Region(
"monitored region",
UUID.fromString("B9407F30-F5F8-466E-AFF9-25556B57FE6D"),
null, null));
}
});
}
}
Found the cause, I just needed to add the following to my MainActivity.java class:
#Override
protected void onResume() {
super.onResume();
SystemRequirementsChecker.checkWithDefaultDialogs(this);
}
This is my CreateNotification class. Code has been taken from the android page. http://developer.android.com/guide/topics/ui/notifiers/notifications.html
Code:
package your.notification.manager;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcel;
import android.view.View;
public class CreateNotification extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
int icon = R.drawable.ic_launcher;
CharSequence tickerText = "Hello";
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when);
Context context = getApplicationContext();
CharSequence contentTitle = "My notification";
CharSequence contentText = "Hello World!";
Intent notificationIntent = new Intent(this, NotificationReceiver.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
final int HELLO_ID = 1;
mNotificationManager.notify(HELLO_ID, notification);
}
}
Error:
05-05 12:51:38.687: E/AndroidRuntime(8629): Caused by: java.lang.IllegalArgumentException: contentView required: pkg=com.crumbs.main id=0 notification=Notification(vibrate=null,sound=null,defaults=0x0,flags=0x10)
Your Code is working fine..
Just Clean your project and run again.