Vibration is gone when running Android app in background - android

I have created an app that gives the user vibration alerts when tilting the phone in a certain direction. It works fine when running the app, however, when closing the window to run the app in background, the vibration stops working. How can I enable it in background?
vibrator.vibrate(VibrationEffect.createWaveform(new long[] {0, 1000}, -1));
I also have
<uses-permission android:name="android.permission.VIBRATE"/>

There are several options. One of them is using a a foreground service.
A foreground service is a service that runs in the background and is given higher priority than a background service, which means it is less likely to be killed by the system when the app is closed.
This is a sample code snippet:
public class VibrationForegroundService extends Service {
private Vibrator vibrator;
#Override
public void onCreate() {
super.onCreate();
vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
startForeground(1, createNotification());
vibrator.vibrate(VibrationEffect.createWaveform(new long[] {0, 1000}, -1));
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
vibrator.cancel();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private Notification createNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "default")
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Vibration Service")
.setContentText("Vibration is running")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setOngoing(true);
return builder.build();
}
}

In addition to #MarcM answer, add "startMyOwnForeground" and it should work with Android 9+
In your fragment:
getActivity().startService(new Intent(getActivity(), VibrationService.class));
VibrationService.java
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import android.os.IBinder;
import android.os.VibrationEffect;
import android.os.Vibrator;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
public class VibrationdService extends Service {
private Vibrator vibrator;
#Override
public void onCreate() {
super.onCreate();
vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
startMyOwnForeground();
else
startForeground(1, new Notification());
}
private void startMyOwnForeground(){
String NOTIFICATION_CHANNEL_ID = "com.example.simpleapp";
String channelName = "My Background Service";
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_NONE);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(chan);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
Notification notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.drawable.ic_vibration)
.setContentTitle("App is running in background")
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(2, notification);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
vibrator.vibrate(VibrationEffect.createWaveform(new long[] {0, 1000}, -1));
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
vibrator.cancel();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private Notification createNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "default")
.setSmallIcon(R.drawable.ic_vibration)
.setContentTitle("Vibration Service")
.setContentText("Vibration is running")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setOngoing(true);
return builder.build();
}
}

Related

Why is deleteIntent(PendingIntent) not called when notification is canceled?

Why is deleteIntent(PendingIntent) not called when notification is canceled?
I am doing this android tutorial on Notifications and in the 'extra challenge', am using deleteIntent.
However it is not invoked at all. Running in the emulator on API 27.
When I swipe the notification to cancel, the cancelNotification() method is not called.
In the docs, I see the watermark 'deprecated' on the page but it's not in the text.
Not sure if it's actually deprecated or if I am using deleteIntent() wrongly.
https://codelabs.developers.google.com/codelabs/android-training-notifications/#6
In the NotifyMe app, there is one use case in which the state of your
buttons does not match the state of the app: when a user dismisses a
notification by swiping it away or clearing the whole notification
drawer. In this case, your app has no way of knowing that the
notification was canceled and that the button state must be changed.
Create another pending intent to let the app know that the user has
dismissed the notification, and toggle the button states accordingly.
Hint: Check out the NotificationCompat.Builder class for a method that
delivers an Intent if the user dismisses the notification.
package com.notifyme;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private static final String PRIMARY_CHANNEL_ID = "primary_notification_channel";
private NotificationManager mNotifyManager;
private static final int NOTIFICATION_ID = 0;
private static final String ACTION_UPDATE_NOTIFICATION =
"com.example.android.notifyme.ACTION_UPDATE_NOTIFICATION";
private static final String ACTION_CANCEL_NOTIFICATION =
"com.example.android.notifyme.ACTION_CANCEL_NOTIFICATION";
private NotificationReceiver mReceiver = new NotificationReceiver();
public class NotificationReceiver extends BroadcastReceiver {
public NotificationReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case ACTION_UPDATE_NOTIFICATION:
updateNotification();;
break;
case ACTION_CANCEL_NOTIFICATION:
cancelNotification();
break;
}
}
}
public void createNotificationChannel() {
mNotifyManager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >=
android.os.Build.VERSION_CODES.O) {
// Create a NotificationChannel
NotificationChannel notificationChannel = new NotificationChannel(PRIMARY_CHANNEL_ID,
"Mascot Notification", NotificationManager
.IMPORTANCE_HIGH);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.enableVibration(true);
notificationChannel.setDescription("Notification from Mascot");
mNotifyManager.createNotificationChannel(notificationChannel);
}
}
private Button button_notify;
private Button button_cancel;
private Button button_update;
public void sendNotification() {
Intent updateIntent = new Intent(ACTION_UPDATE_NOTIFICATION);
PendingIntent updatePendingIntent = PendingIntent.getBroadcast
(this, NOTIFICATION_ID, updateIntent, PendingIntent.FLAG_ONE_SHOT);
Intent cancelIntent = new Intent(ACTION_CANCEL_NOTIFICATION);
PendingIntent cancelPendingIntent = PendingIntent.getBroadcast
(this, NOTIFICATION_ID, cancelIntent, PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder notifyBuilder = getNotificationBuilder();
notifyBuilder.addAction(R.drawable.ic_update, "Update Notification", updatePendingIntent);
notifyBuilder.setDeleteIntent(cancelPendingIntent);
mNotifyManager.notify(NOTIFICATION_ID, notifyBuilder.build());
setNotificationButtonState(false, true, true);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button_notify = findViewById(R.id.notify);
button_notify.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
sendNotification();
}
});
createNotificationChannel();
button_update = findViewById(R.id.update);
button_update.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Update the notification
updateNotification();
}
});
button_cancel = findViewById(R.id.cancel);
button_cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Cancel the notification
cancelNotification();
}
});
registerReceiver(mReceiver,new IntentFilter(ACTION_UPDATE_NOTIFICATION));
setNotificationButtonState(true, false, false);
}
#Override
protected void onDestroy() {
unregisterReceiver(mReceiver);
super.onDestroy();
}
public void updateNotification() {
Bitmap androidImage = BitmapFactory
.decodeResource(getResources(),R.drawable.mascot_1);
NotificationCompat.Builder notifyBuilder = getNotificationBuilder();
notifyBuilder.setStyle(new NotificationCompat.BigPictureStyle()
.bigPicture(androidImage)
.setBigContentTitle("Notification Updated!"));
mNotifyManager.notify(NOTIFICATION_ID, notifyBuilder.build());
setNotificationButtonState(false, false, true);
}
public void cancelNotification() {
mNotifyManager.cancel(NOTIFICATION_ID);
setNotificationButtonState(true, false, false);
}
private NotificationCompat.Builder getNotificationBuilder(){
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent notificationPendingIntent = PendingIntent.getActivity(this,
NOTIFICATION_ID, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notifyBuilder = new NotificationCompat.Builder(this, PRIMARY_CHANNEL_ID)
.setContentTitle("You've been notified!")
.setContentText("This is your notification text.")
.setSmallIcon(R.drawable.ic_android)
.setContentIntent(notificationPendingIntent)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setAutoCancel(true);
return notifyBuilder;
}
void setNotificationButtonState(Boolean isNotifyEnabled,
Boolean isUpdateEnabled,
Boolean isCancelEnabled) {
button_notify.setEnabled(isNotifyEnabled);
button_update.setEnabled(isUpdateEnabled);
button_cancel.setEnabled(isCancelEnabled);
}
}
Update: From CommonsWare's helpful answer below, I corrected the registration of the receiver to use multiple Actions for the same IntentFilter. However it still failed even though I tried all the different flags for the PendingIntent.
When you press the Update button in the notification and then swipe right, the buttons in the Activity do not reset their states because the PendingIntent is not firing.
Here is my updated code.
package com.onedropaflame.notifyme;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private static final String PRIMARY_CHANNEL_ID = "primary_notification_channel";
private NotificationManager mNotifyManager;
private static final int NOTIFICATION_ID = 0;
private static final String ACTION_UPDATE_NOTIFICATION =
"com.example.android.notifyme.ACTION_UPDATE_NOTIFICATION";
private static final String ACTION_CANCEL_NOTIFICATION =
"com.example.android.notifyme.ACTION_CANCEL_NOTIFICATION";
private NotificationReceiver mReceiver = new NotificationReceiver();
public class NotificationReceiver extends BroadcastReceiver {
public NotificationReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case ACTION_UPDATE_NOTIFICATION:
updateNotification();;
break;
case ACTION_CANCEL_NOTIFICATION:
cancelNotification();
break;
}
}
}
public void createNotificationChannel() {
mNotifyManager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >=
android.os.Build.VERSION_CODES.O) {
// Create a NotificationChannel
NotificationChannel notificationChannel = new NotificationChannel(PRIMARY_CHANNEL_ID,
"Mascot Notification", NotificationManager
.IMPORTANCE_HIGH);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.enableVibration(true);
notificationChannel.setDescription("Notification from Mascot");
mNotifyManager.createNotificationChannel(notificationChannel);
}
}
private Button button_notify;
private Button button_cancel;
private Button button_update;
public void sendNotification() {
Intent updateIntent = new Intent(ACTION_UPDATE_NOTIFICATION);
PendingIntent updatePendingIntent = PendingIntent.getBroadcast
(this, NOTIFICATION_ID, updateIntent, PendingIntent.FLAG_ONE_SHOT);
Intent cancelIntent = new Intent(ACTION_CANCEL_NOTIFICATION);
PendingIntent cancelPendingIntent = PendingIntent.getBroadcast
(this, NOTIFICATION_ID, cancelIntent, PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder notifyBuilder = getNotificationBuilder();
notifyBuilder.addAction(R.drawable.ic_update, "Update Notification", updatePendingIntent);
notifyBuilder.setDeleteIntent(cancelPendingIntent);
mNotifyManager.notify(NOTIFICATION_ID, notifyBuilder.build());
setNotificationButtonState(false, true, true);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button_notify = findViewById(R.id.notify);
button_notify.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
sendNotification();
}
});
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_CANCEL_NOTIFICATION);
intentFilter.addAction(ACTION_UPDATE_NOTIFICATION);
createNotificationChannel();
registerReceiver(mReceiver,intentFilter);
button_update = findViewById(R.id.update);
button_update.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Update the notification
updateNotification();
}
});
button_cancel = findViewById(R.id.cancel);
button_cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Cancel the notification
cancelNotification();
}
});
setNotificationButtonState(true, false, false);
}
#Override
protected void onDestroy() {
unregisterReceiver(mReceiver);
super.onDestroy();
}
public void updateNotification() {
Bitmap androidImage = BitmapFactory
.decodeResource(getResources(),R.drawable.mascot_1);
NotificationCompat.Builder notifyBuilder = getNotificationBuilder();
notifyBuilder.setStyle(new NotificationCompat.BigPictureStyle()
.bigPicture(androidImage)
.setBigContentTitle("Notification Updated!"));
mNotifyManager.notify(NOTIFICATION_ID, notifyBuilder.build());
setNotificationButtonState(false, false, true);
}
public void cancelNotification() {
mNotifyManager.cancel(NOTIFICATION_ID);
setNotificationButtonState(true, false, false);
}
private NotificationCompat.Builder getNotificationBuilder(){
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent notificationPendingIntent = PendingIntent.getActivity(this,
NOTIFICATION_ID, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notifyBuilder = new NotificationCompat.Builder(this, PRIMARY_CHANNEL_ID)
.setContentTitle("You've been notified!")
.setContentText("This is your notification text.")
.setSmallIcon(R.drawable.ic_android)
.setContentIntent(notificationPendingIntent)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setAutoCancel(true);
return notifyBuilder;
}
void setNotificationButtonState(Boolean isNotifyEnabled,
Boolean isUpdateEnabled,
Boolean isCancelEnabled) {
button_notify.setEnabled(isNotifyEnabled);
button_update.setEnabled(isUpdateEnabled);
button_cancel.setEnabled(isCancelEnabled);
}
}
It appears as though you are not registering a receiver for ACTION_CANCEL_NOTIFICATION, just ACTION_UPDATE_NOTIFICATION.
Commonsware posted the correct answer about both actions needing to be registered.
However that was not sufficient. I corrected the registration of the receiver to use multiple Actions for the same IntentFilter. However it still failed even though I tried all the different flags for the PendingIntent. When you press the Update button in the notification and then swipe right, the buttons in the Activity do not reset their states because the PendingIntent is not firing.
Solution: I found that I had to set the cancelPendingIntent again during the updateNotification(). I do not know the reason why it is lost.
public void updateNotification() {
Bitmap androidImage = BitmapFactory
.decodeResource(getResources(),R.drawable.mascot_1);
NotificationCompat.Builder notifyBuilder = getNotificationBuilder();
notifyBuilder.setStyle(new NotificationCompat.BigPictureStyle()
.bigPicture(androidImage)
.setBigContentTitle("Notification Updated!"));
// >>>>> SET AGAIN! >>>>>>>>>
Intent cancelIntent = new Intent(ACTION_CANCEL_NOTIFICATION);
PendingIntent cancelPendingIntent = PendingIntent.getBroadcast
(this, NOTIFICATION_ID, cancelIntent, PendingIntent.FLAG_ONE_SHOT);
notifyBuilder.setDeleteIntent(cancelPendingIntent);
// >>>>>>>>>>>>>>
mNotifyManager.notify(NOTIFICATION_ID, notifyBuilder.build());
setNotificationButtonState(false, false, true);
}

Which method should I use instead of setLatestInfo?

I'm a beginner and I'm trying to show some status bar notification on the user.I found out that API23+ does not support the method setLatestInfo, so my compiler finds it as an error. What other method should I use instead of this to turn on notifications?
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.Switch;
import androidx.annotation.RequiresApi;
import static android.app.PendingIntent.getActivity;
import static android.content.Context.NOTIFICATION_SERVICE;
public class Settings extends AppCompatActivity {
Switch simpleswitch1;
Switch simpleswitch2;
private Notification notification;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
simpleswitch1 = (Switch) findViewById(R.id.simpleswitch1);
simpleswitch2 = (Switch) findViewById(R.id.simpleswitch2);
simpleswitch1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Notify("Title", "Message");
}
});
simpleswitch2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
notification.defaults |= Notification.DEFAULT_SOUND;
}});}
private void Notify(String notificationTitle, String notificationMessage) {
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.notification, "New message", System.currentTimeMillis());
Intent notificationIntent = new Intent(Settings.this, Settings.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(Settings.this, notificationTitle, notificationMessage, pendingIntent);
notificationManager.notify(9999, notification);
}
}
setLatestEventInfo is deprecated, was removed in api 23. So if your SDK version is set to api 23+ you'll have this issue and you should use NotificationCompat.Builder instead.
An example :
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
private void Notify(String notificationTitle, String notificationMessage) {
Intent notificationIntent = new Intent(Settings.this, Settings.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification)
.setContentTitle("New message")
.setContentText("My notification")
// Set the intent that will fire when the user taps the notification
.setContentIntent(pendingIntent)
.build();
Notification notification = builder.getNotification();
notificationManager.notify(11 /*An identifier for this notification unique within your application.*/, notification);
}
I suggest to read the official documentation about notification here.

How to keep an app running when screen goes off(latest android)

I have an app (activity). I want it to stay running even if screen goes off, but older solution don't work. As i understand the only solution is to make a service. But is it easy to transform an activity to service?The method with wake lock can't be used any more, as it is deprecated.
Create Foreground Service as below.
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.os.Build;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
public class ForegroundService extends Service {
public static final String CHANNEL_ID = "ForegroundServiceChannel";
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String input = intent.getStringExtra("inputExtra");
createNotificationChannel();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Foreground Service")
.setContentText(input)
.setSmallIcon(R.drawable.ic_stat_name)
.setContentIntent(pendingIntent)
.build();
startForeground(1001, notification);
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Foreground Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
}
Dont forget to declarer the service in manifest.

How to add Pending Intent to this Activity

I'm having an issue with trying to run an activity when a notification is clicked.
How and where create a Pending Intent, which must run my app after i click on notification..? I dont have problems with notification. But my notification after click doesnt work. Please help, thanks ..............................................................................................................................................................................................................................................
package pl.wat.pz.myapplication;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v4.app.NotificationCompat;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
public class MainActivity extends Activity {
private static final String GROUP_UPDATES="group_updates";
private static final String CHANNEL_CONTENT="channel_content";
private static final int NOTIF_ID_CONTENT=1337;
private NotificationManager mgr;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mgr=getSystemService(NotificationManager.class);
if (mgr.getNotificationChannel(CHANNEL_CONTENT)==null) {
initContentChannel();
}
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.actions, menu);
return(super.onCreateOptionsMenu(menu));
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId()==R.id.settings) {
Intent i=new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
i.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
startActivity(i);
}
return super.onOptionsItemSelected(item);
}
public void raiseContent(View view) {
Notification n=new NotificationCompat.Builder(MainActivity.this, CHANNEL_CONTENT)
.setContentTitle(getString(R.string.notif_content_title))
.setContentText(getString(R.string.notify_content_text))
.setSmallIcon(android.R.drawable.stat_sys_warning)
.build();
mgr.notify(NOTIF_ID_CONTENT, n);
}
private void initContentChannel() {
NotificationChannel channel=
new NotificationChannel(CHANNEL_CONTENT,
getString(R.string.channel_name_content),
NotificationManager.IMPORTANCE_LOW);
channel.setGroup(GROUP_UPDATES);
mgr.createNotificationChannel(channel);
}
}
You use of intent to your class to extend of FirebaseMessagingService and your intent code is like to below :
Intent intent = new Intent(context, yourClass.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
final PendingIntent resultPendingIntent =
PendingIntent.getActivity(
context,
requestCode,
intent,
PendingIntent.FLAG_CANCEL_CURRENT
);
// then set to notification
NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle();
bigPictureStyle.setBigContentTitle(title);
bigPictureStyle.setSummaryText(Html.fromHtml(message).toString());
bigPictureStyle.bigPicture(bitmap);
Notification notification;
notification = mBuilder.setSmallIcon(icon).setTicker(title).setWhen(0)
.setAutoCancel(true)
.setContentTitle(title)
.setContentIntent(resultPendingIntent)
.setSound(alarmSound)
.setStyle(bigPictureStyle)
.setWhen(getTimeMilliSec(timeStamp))
.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), icon))
.setContentText(message)
.build();
NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(Config.NOTIFICATION_ID_BIG_IMAGE, notification);

How to stop audio playback when a phone call arrives in Android

hello im new to android and im doing a simple online radio app for my church the poblem is that i need the playback service to stop and restart when the phone gets a call and end it
so far i can stop the service just fine but when it gets started again just crashes so i dont know what im doing wrong
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.content.res.Resources;
import android.os.IBinder;
import android.os.PowerManager.WakeLock;
import android.support.v4.app.NotificationCompat;
import com.spoledge.aacdecoder.MultiPlayer;
public class RadioService extends Service{
WakeLock wakelock;
//TelephonyManager teleManager= null;
//PhoneStateListener listener;
NotificationManager mNotificationManager;
public static MultiPlayer aacPlayer;
public static String radio;
private static Boolean isTuning;
// private TeleListener myListener = null;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
super.onCreate();
setTuning(false);
setRadio(getString(R.string.rhema));
aacPlayer = new MultiPlayer();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId){
setTuning(true);
setTuning(true);
aacPlayer.playAsync(radio);
//CallReceiver.setTuning(true);
Resources r= getResources();
String[] Notify = r.getStringArray(R.array.PlayNotify);
// prepare intent which is triggered if the
// notification is selected
Intent inten = new Intent(this, PlayerActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, inten, 0);
// build notification
// the addAction re-use the same intent to keep the example short
NotificationCompat.Builder n = new NotificationCompat.Builder(this)
.setContentTitle(Notify[0])
.setContentText(Notify[1])
.setSmallIcon(R.drawable.noti_icon)
.setContentIntent(pIntent)
.setAutoCancel(true)
.setOngoing(true)
.setContentIntent(pIntent);
Notification hola = n.build();
startForeground(100, hola);
//startForeground(startId, notification);
return START_STICKY;
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
pause();
//CallReceiver.setTuning(false);
super.onDestroy();
}
public static boolean getTuning() {
return isTuning;
}
public void setTuning(boolean Tuning) {
isTuning = Tuning;
}
public void setRadio(String r){
radio = r;
}
public void PlayNotify(){
Resources r= getResources();
String[] Notify = r.getStringArray(R.array.PlayNotify);
// prepare intent which is triggered if the
// notification is selected
Intent intent = new Intent(this, RadioService.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);
// build notification
// the addAction re-use the same intent to keep the example short
NotificationCompat.Builder n = new NotificationCompat.Builder(this)
.setContentTitle(Notify[0])
.setContentText(Notify[1])
.setSmallIcon(R.drawable.noti_icon)
.setContentIntent(pIntent)
.setAutoCancel(true);
n.setOngoing(true);
n.setContentIntent(pIntent);
//NotificationManager mNotificationManager =(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(100, n.build());
}
public static void play(){
aacPlayer.playAsync(radio);
}
public static void pause(){
aacPlayer.stop();
}
}
and this is the broadcast
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
public class CallReceiver extends BroadcastReceiver{
TelephonyManager telManager;
Context context;
public static boolean Tuning = false;
PlayerActivity mainActivity;
NotificationManager mNotificationManager;
#Override
public void onReceive(Context context, Intent intent) {
mainActivity=new PlayerActivity();
this.context=context;
telManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
telManager.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);
}
private final PhoneStateListener phoneListener = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
try {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING: {
//PAUSE
if(Tuning){
context.stopService(new Intent(context,RadioService.class));
}
break;
}
case TelephonyManager.CALL_STATE_OFFHOOK: {
if(Tuning){
context.stopService(new Intent(context,RadioService.class));
}
break;
}
case TelephonyManager.CALL_STATE_IDLE: {
//PLAY
if(Tuning){
showNotification(context);
context.stopService(new Intent(context,RadioService.class));}
break;
}
default: { }
}
} catch (Exception ex) {
}
}
};
public static void setTuning(boolean r){
Tuning = r;
}
private void showNotification(Context context) {
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
new Intent(context, PlayerActivity.class), 0);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.noti_icon)
.setContentTitle("Rhema Stereo")
.setContentText("Vuelve a Sintonizarnos.");
mBuilder.setContentIntent(contentIntent);
mBuilder.setDefaults(Notification.DEFAULT_SOUND);
mBuilder.setAutoCancel(true);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, mBuilder.build());}
}
the weir thing is that from the activities i can start and stop the service just fine but here i can only stop it. So for now im using a notification to get back to an activity and restart the service
If I may, I would suggest another approach for this problem. You state that:
i need the playback service to stop and restart when the phone gets a
call
However, the issue is more complex. You should also stop playback, for example, when a notification arrives, or if another music player is started by the user. Instead of having to monitor all these posibilities independently, Android provides built-in support for this concept -- it's called the audio focus. In broad terms, it means that only one app can have audio focus at one point in time, and that you should relinquish if it asked to.
This behavior can be obtained by using an OnAudioFocusChangeListener.
Basically, you must:
Request audio focus before starting playback.
Only start playback if you effectively obtain it.
Abandon focus when you stop playback.
Handle audio focus loss (either by lowering volume or stopping playback altogether).
Please check the Managing Audio Focus article in the Android documentation.
you need to add this snippet in your current activity
IntentFilter receiverFilter = new IntentFilter(
Intent.ACTION_HEADSET_PLUG);
BootBroadcast receiver = new BootBroadcast();
registerReceiver(receiver, receiverFilter);
then the same need to register in the receiver manifest.xml
eg:
<receiver
android:name="YOUR_ACTION_STRING.BootCompletedReceiver"
android:enabled="true"
android:exported="false" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Also add this flag inside BootBroadcast class
newIntent .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

Categories

Resources