Can't Update Notifications text after Forerground service init; Context issue - java

I have a simple NanoHTTPD server running as a foreground service.
I am facing issues in updating the notifications with new content when a new request to a server comes in.
The foreground service starts up and the notification shows. No issue there. But can't update them later.
File structure
- Mainactivity
- NanoServer (server implementaion)
- NanoService (foreground service class)
- NotificationProvider (separate class to handle notifications)
NanoServer.java
public Context context = getContext();
public NotificationProvider notificationProvider;
public NanoServer(int port) {
super(8089);
}
#Override
public Response serve(String uri, Method method,
Map<String, String> header, Map<String, String> parameters,
Map<String, String> files) {
String answer = "";
String msg;
// doesnt work with the context. something wrong here I guess????
notificationProvider = new NotificationProvider();
notificationProvider.setNotification(context, "Title", uri, 0);
FileInputStream fis = null;
try {
fis = new FileInputStream(uri);
Log.w(TAG, uri + " found");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return newChunkedResponse(Status.OK, "audio/mpeg", fis);
}
public Context getContext() {
return context;
}
NanoService.java
String TAG = "NANOSERVICE";
public Context context = this;
public Handler handler = null;
public static Runnable runnable = null;
PowerManager powerManager;
PowerManager.WakeLock wakeLock;
WifiManager.WifiLock wifiLock;
private NanoServer nanoServer;
public NotificationProvider notificationProvider;
public NanoService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Start the httpd.
try {
nanoServer = new NanoServer(8089);
nanoServer.start();
Log.d(TAG, "Service with server started");
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(this, "Service failed to start.", Toast.LENGTH_LONG).show();
}
// Keep the CPU awake (but not the screen).
powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
wakeLock.acquire();
// Keep the WIFI turned on.
WifiManager wm = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
wifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, TAG);
wifiLock.acquire();
notificationProvider = new NotificationProvider();
notificationProvider.setNotification(this, "Title", "Message", 0);
// had to extend notificationprovider with notification
startForeground(1, notificationProvider);
Log.d(TAG, "Foreground service running");
return Service.START_STICKY;
}
#Override
public void onDestroy() {
stopForeground(true);
wakeLock.release();
wifiLock.release();
nanoServer.stop();
}
NotificationProvider.java
public class NotificationProvider extends Notification {
String TAG = "NOTIFICATIONPROVIDER";
public NotificationProvider() {
}
public void setNotification(Context context, String notificationTitle, String notificationMessage, int notificationRequestCode){
NotificationCompat.Builder builder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle(notificationTitle)
.setContentText(notificationMessage)
.setTicker("My service")
.setColor(101)
.setWhen(System.currentTimeMillis())
.setOngoing(true)
.setPriority(NotificationCompat.PRIORITY_MAX);
Intent intent = new Intent(context, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(context, notificationRequestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(0, builder.build());
Log.d(TAG, "Got new Notification");
}
}

I think the easiest solution will be using the same builder method for updating the notification.
Use this updated NotificationProvider.
Change new NotificationProvider() to NotificationProvider.getInstance() in NanoService (or anywhere else).
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.iroid.videoeditor.R;
import com.iroid.videoeditor.main.MainActivity;
public class NotificationProvider extends Notification {
private static NotificationProvider sInstance;
private NotificationCompat.Builder mBuilder;
private String TAG = "NOTIFICATIONPROVIDER";
public static NotificationProvider getInstance() {
if (sInstance == null)
sInstance = new NotificationProvider();
return sInstance;
}
// Prevent creating new instances from outside
private NotificationProvider() {
}
public void setNotification(Context context, String notificationTitle, String
notificationMessage, int notificationRequestCode) {
NotificationManager manager = (NotificationManager) context.getSystemService(Context
.NOTIFICATION_SERVICE);
if (mBuilder == null) {
// Notification doesn't exists. Need to create one.
mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle(notificationTitle)
.setContentText(notificationMessage)
.setTicker("My service")
.setColor(101)
.setWhen(System.currentTimeMillis())
.setOngoing(true)
.setPriority(NotificationCompat.PRIORITY_MAX);
Intent intent = new Intent(context, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(context,
notificationRequestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(contentIntent);
manager.notify(0, mBuilder.build());
Log.d(TAG, "Got new Notification");
} else {
// Notification exists. Simply update
}
}
}

The problem is most likely to be with your Notification ID, which must be unique within your application if you later want to update it.
manager.notify(0, builder.build());
Change it to a non-zero constant
private static final int NOTE_ID = 2794; //chosen arbitrarily
manager.notify(NOTE_ID, builder.build());
However you should also not hold (leak) a context, instead get the app context (or service context) when you use it.
To be able to get an Application Context at any time, implement an application class (and register it in the manifest)
public class MyApplication extends Application {
public static Context appContext() {
return this;
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="...">
<!-- The name here should match whatever you called your application class -->
<application android:name=".MyApplication"
...>
...
</application>
</manifest>

Related

ProtocolException in MediaPlayer streaming Service (MediaHTTPConnection: readAt 20709376 / 32768 => java.net.ProtocolException)

I've made an Android app that main feature is to play audio stream from my server. But for some reason music stops playing after about 20 minutes and the app is throwing ProtocolException (logs from app on Android Studio logcat image).
Android Studio logcat
This error is even more weird because it occurs only on some devices. Error occurs on multiple Xiaomi devices (all with Android 10) and Samsung Galaxy S9 (also with Android 10) but on Samsung Galaxy S10 (Android 10) and Huawai tablet that error doesn't occur and music is being played as long as user does not stop it.
This is my PlayerService class code that is responsible for running MediaPlayer as a service:
public class PlayerService extends Service {
private static final String CHANNEL_ID = "PlayerServiceChannel";
private static final int SERVICE_ID = 1;
private MediaPlayer player;
private Notification notification;
private JsonObjectHandler jsonObjectHandler;
private int streamIndex = 9999;
private Messenger messenger;
private PendingIntent pendingIntent;
private NotificationManager notificationManager;
private PendingIntent closeApp;
private WifiManager.WifiLock wifiLock;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
JSONObject jsonObject = new JSONObject(Objects.requireNonNull(intent.getStringExtra("JsonInfo")));
jsonObjectHandler = new JsonObjectHandler(jsonObject);
} catch (JSONException e) {
jsonObjectHandler = null;
}
return START_REDELIVER_INTENT;
}
#Override
public void onCreate() {
super.onCreate();
wifiLock = ((WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE))
.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "playerServiceWiFiLock");
HandlerThread thread = new HandlerThread("ServiceStartArgument", Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
Looper mServiceLooper = thread.getLooper();
ServiceHandler mServiceHandler = new ServiceHandler(mServiceLooper);
messenger = new Messenger(mServiceHandler);
PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
case TelephonyManager.CALL_STATE_OFFHOOK:
stopForeground(true);
stopSelf();
break;
case TelephonyManager.CALL_STATE_IDLE:
break;
}
super.onCallStateChanged(state, incomingNumber);
}
};
TelephonyManager mgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
if (mgr != null) {
mgr.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
createNotificationChannel();
Intent notificationIntent = new Intent(this, LoginActivity.class);
pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
stopSelf();
unregisterReceiver(this);
System.exit(0);
}
};
IntentFilter intentFilter = new IntentFilter("android.intent.CLOSE_APP");
registerReceiver(broadcastReceiver, intentFilter);
Intent intentClose = new Intent("android.intent.CLOSE_APP");
closeApp = PendingIntent.getBroadcast(this, 0, intentClose, 0);
updateNotification(streamIndex);
startForeground(SERVICE_ID, notification);
}
private NotificationCompat.Builder createNotification(int streamIndex) {
String defaultValue;
if (jsonObjectHandler == null || streamIndex == 9999) {
defaultValue = "";
} else {
defaultValue =
jsonObjectHandler.getPlaylistButtons().get(streamIndex).getButtonName();
}
return new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ikonastream48)
.setContentIntent(pendingIntent)
.setContentTitle(getString(R.string.app_name))
.setContentText(defaultValue)
.setDefaults(0)
.setSound(null)
.addAction(R.drawable.ic_close_black, getString(R.string.close), closeApp);
}
private void updateNotification(int streamIndex) {
notification = createNotification(streamIndex).build();
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert notificationManager != null;
notificationManager.notify(SERVICE_ID, notification);
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID, "Example Service Channel", NotificationManager.IMPORTANCE_DEFAULT);
serviceChannel.setSound(null, null);
notificationManager = getSystemService(NotificationManager.class);
if (notificationManager != null) {
notificationManager.createNotificationChannel(serviceChannel);
}
}
}
private void stopServicePlayer() {
if (player != null) {
player.stop();
player.reset();
player.release();
player = null;
}
stopForeground(true);
}
#Override
public void onDestroy() {
super.onDestroy();
stopServicePlayer();
if (wifiLock.isHeld()) wifiLock.release();
}
private void sendMessageBroadcast(Intent intent) {
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
if (streamIndex != 9999) {
Intent intent1 = new Intent("streamIndex");
intent1.putExtra("INDEX", streamIndex);
sendMessageBroadcast(intent1);
}
return messenger.getBinder();
}
private final class ServiceHandler extends Handler {
ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 0) {
player = new MediaPlayer();
player.setOnErrorListener((mp, what, extra) -> false);
player.setAudioAttributes(new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributes.USAGE_MEDIA)
.build());
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
streamIndex = msg.arg1;
updateNotification(streamIndex);
try {
player.setOnPreparedListener(mediaPlayer -> {
mediaPlayer.start();
Intent intent = new Intent("streamIndex");
intent.putExtra("INDEX", streamIndex);
sendMessageBroadcast(intent);
});
player.setDataSource(jsonObjectHandler
.getPlaylistButtons()
.get(streamIndex)
.getButtonStreamAddress());
} catch (IOException e) {
e.printStackTrace();
}
player.prepareAsync();
if (!wifiLock.isHeld()) wifiLock.acquire();
} else if (msg.what == 1) {
Intent intent2 = new Intent("streamIndex");
intent2.putExtra("INDEX", streamIndex);
sendMessageBroadcast(intent2);
}
}
}
}
Thank you for all responses in advance!
P.S. The code was written few years ago (at the beginning of my programming journey), so I'm aware that it looks bad and need to be rewritten in better way.
Disable caches and retry :
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "audio/mp3");
headers.put("Accept-Ranges", "bytes");
headers.put("Status", "206");
headers.put("Cache-control", "no-cache");
Uri uri = Uri.parse(yourContentUrl);
player.setDataSource(getApplicationContext(), uri, headers);
The problem was on the server side. When the stream was switched from CBR to the VBR in the Lame encoder, the problem stop occurring.

How to use Broadcast receiver in non-static service class

Hello I created Broadcast Receiver in the Service class to receive application notifications but it doesn't receive any intents from Notification. When I make the broadcast receiver static, the problem is solved but at this time I cannot access the elements of the non-static upper class. I have to solve this without making it static.
My Code:
public class BackgroundService extends Service {
private final int TASK_DELAY = 0;
private final int TASK_PERIOD = 5 * 1000;
int NOTIFICATION_ID = 1;
private Context context;
private NotificationCompat.Builder builder;
private NotificationManager notificationManager;
private static Timer timer;
private PendingIntent test;
private int runRate;
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//User pressed a notifiacition button
Log.w(TAG, "onReceive: Recived" );
}
// constructor
public MyReceiver(){
}
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
public static Timer getTimer() {
return timer;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public void onCreate() {
Toast.makeText(this, "Service has been started!", Toast.LENGTH_SHORT).show();
context = getApplicationContext();
timer = new Timer();
runRate = 0;
builder = new NotificationCompat.Builder(context)
.setSmallIcon(android.R.drawable.ic_dialog_alert)
.setContentTitle("KolBoost")
.setContentText("Arkaplan servisi etkinleştirildi!")
.setAutoCancel(false)
.setPriority(NotificationCompat.PRIORITY_HIGH);
MyReceiver myReceiver = new MyReceiver();
IntentFilter filter = new IntentFilter();
Intent close = new Intent(getBaseContext(), BackgroundService.class);
close.setAction("CLOSE_SERVICE");
PendingIntent closeServiceIntent = PendingIntent.getBroadcast(getBaseContext(), 0, close, 0);
Intent i2 = new Intent(getBaseContext(), BackgroundService.class);
i2.setAction("BOOST_MEMORY");
PendingIntent boostIntent = PendingIntent.getBroadcast(getBaseContext(), 0, i2, 0);
Intent launch = new Intent(getBaseContext(),BackgroundService.class);
launch.setAction("OPEN_MANAGER");
PendingIntent contentIntent = PendingIntent.getBroadcast(getBaseContext(), 0, launch, 0);
builder.setContentIntent(contentIntent);
builder.addAction(0, "Clear Memory", boostIntent);
builder.addAction(0, "Exit", closeServiceIntent);
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(getBaseContext(), MainActivity.class);
test = PendingIntent.getActivity(getBaseContext(), NOTIFICATION_ID, notificationIntent, PendingIntent.FLAG_NO_CREATE);
//I'm adding actions to intentFilter.
filter.addAction(close.getAction());
filter.addAction(i2.getAction());
filter.addAction(launch.getAction());
//Registering Receiver with intentFilter
registerReceiver(myReceiver,filter);
super.onCreate();
}
#Override
public void onDestroy() {
timer.cancel();
notificationManager.cancelAll();
Log.d(TAG, "onDestroy: Destroyed");
super.onDestroy();
}
}

Can not connect button click action Intent in Main activity to a Pending Intent in Service class to get action in notification using .getAction()

I am trying to connect following MainActivity.java's buttonclick intents to a pendingIntent in my RathuMakara.java Service class. I tried to use CONSTANTS, but I was not successful. I want to add buttons to notification to control the music. So that I know, I should use pending intents, that's why I am trying to connect button click action in MainActivity.java to a pendingIntent in my RathuMakara.java Service class.
This is MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button buttonStart;
private Button buttonStop;
public static final String CHANNEL_ID = "exampleServiceChannel";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonStart = (Button) findViewById(R.id.buttonStart);
buttonStop = (Button)findViewById(R.id.buttonSop);
buttonStart.setOnClickListener(this);
buttonStop.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(v == buttonStart){
startService(new Intent(this, RathuMakara.class));
buttonStart.setEnabled(false);
buttonStop.setEnabled(true);
Toast.makeText(getApplicationContext(),"Lets's Go... Collecting the Awesomeness",Toast.LENGTH_LONG).show();
}
else if (v == buttonStop){
stopService(new Intent(this, RathuMakara.class));
Toast.makeText(getApplicationContext(),"Playing Stopped",Toast.LENGTH_LONG).show();
buttonStop.setEnabled(false);
buttonStart.setEnabled(true);
}
}
}
This is RathuMakara.java
public class RathuMakara extends Service {
public static Object action;
private MediaPlayer rathu;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Override
public int onStartCommand(Intent intent,int flags , int startID){
String url ="http://206.189.34.189:8000/rathumakara.mp3";
MediaPlayer rathu = new MediaPlayer();
rathu.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
rathu.setDataSource(url);
rathu.prepare();
rathu.start();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Bitmap icon = BitmapFactory.decodeResource(getResources(),
R.drawable.logo);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Rathu Makara FM")
.setContentText("දැන් අහන්නේ")
.setSmallIcon(R.drawable.logo)
.setLargeIcon(icon)
.setOngoing(true)
// .addAction(android.R.drawable.ic_media_play, "Play", )
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
}
catch (IOException e){
e.printStackTrace();
}catch (IllegalArgumentException e){
e.printStackTrace();
}catch (SecurityException e){
e.printStackTrace();
}catch (IllegalStateException e){
e.printStackTrace();
}
return START_NOT_STICKY;
}
#Override
public void onDestroy(){
rathu.stop();
}
}
This is Rathu.java where I created the Notification channel
package com.example.yomal.rathumakarafm;
import android.app.Application;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.os.Build;
public class Rathu extends Application {
public static final String CHANNEL_ID = "exampleServiceChannel";
#Override
public void onCreate() {
super.onCreate();
createNotificationChannel();
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Example Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
}
Please Help Me.Thank you
Set the notification content
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle(textTitle)
.setContentText(textContent)
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
and add action buttons
Intent snoozeIntent = new Intent(this, MyBroadcastReceiver.class);
snoozeIntent.setAction(ACTION_SNOOZE);
snoozeIntent.putExtra(EXTRA_NOTIFICATION_ID, 0);
PendingIntent snoozePendingIntent =
PendingIntent.getBroadcast(this, 0, snoozeIntent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.addAction(R.drawable.ic_snooze, getString(R.string.snooze),
snoozePendingIntent);

How can I restart the timer, after it was cancelled?

I've got this service, which starts a timer, whenever said service also starts. The idea is that, if the user manually turns on the screen (i.e. the app. enters in the "counter" BroadcastReceiver), the timer gets cancelled. Otherwise, if the timer finishes by itself, the service will automatically stop (via onDestroy, of course).
My problem comes when I want to restart the service, WITHOUT killing the app. first. If I simply input a new number of seconds and start the service, I get the following error: java.lang.IllegalStateException: Timer was canceled
How can I get rid of said problem?
MainService:
public class MainService extends Service {
static String BROADCAST_ACTION = "com.example.vladpintea.friendsbeforecents.displayevent";
Handler handler = new Handler();
Intent intentForStars;
String usedTimer;
long interval;
TimerTask myTask = new TimerTask() { public void run() { stopSelf(); } };
Timer myTimer = new Timer();
#Override
public void onCreate() {
Toast.makeText(MainService.this, "Service, Created", Toast.LENGTH_SHORT).show();
intentForStars = new Intent(BROADCAST_ACTION);
registerReceiver(counter, new IntentFilter(Intent.ACTION_SCREEN_ON));
}
private BroadcastReceiver counter = new BroadcastReceiver() {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onReceive(Context context, Intent intent) {
myTimer.cancel();
NotificationManager notify_manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Intent intent_main_activity = new Intent(context, MainActivity.class);
PendingIntent pending_intent_main_activity = PendingIntent.getActivity(context, 0,
intent_main_activity, 0);
Notification notification_popup = new Notification.Builder(context)
.setContentTitle("Friends Before Cents")
.setContentText("Oh, no! You've Lost. Try Again?")
.setSmallIcon(R.mipmap.ic_sentiment_very_dissatisfied_white_48dp)
.setContentIntent(pending_intent_main_activity)
.setAutoCancel(true)
.build();
notify_manager.notify(0, notification_popup);
Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, 30000);
}
};
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(MainService.this, "Service, Started", Toast.LENGTH_SHORT).show();
try { usedTimer = intent.getStringExtra("timer"); } catch (NullPointerException ignored) {}
try { interval = Long.parseLong(usedTimer); } catch (NumberFormatException ignored) {}
myTimer.schedule(myTask, interval * 1000);
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1000);
return super.onStartCommand(intent, flags, startId);
}
private Runnable sendUpdatesToUI = new Runnable() {
public void run() { handler.postDelayed(this, 1000); }
};
public void addStars() { sendBroadcast(intentForStars); }
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onDestroy() {
unregisterReceiver(counter);
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK
| PowerManager.ACQUIRE_CAUSES_WAKEUP
| PowerManager.ON_AFTER_RELEASE, "MyWakeLock");
wakeLock.acquire();
Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, 30000);
NotificationManager notify_manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Intent intent_main_activity = new Intent(this.getApplicationContext(), MainActivity.class);
PendingIntent pending_intent_main_activity = PendingIntent.getActivity(this, 0,
intent_main_activity, 0);
Notification notification_popup = new Notification.Builder(this)
.setContentTitle("Friends Before Cents")
.setContentText("Congrats! You've Won Some Coins.")
.setSmallIcon(R.mipmap.ic_sentiment_very_satisfied_white_48dp)
.setContentIntent(pending_intent_main_activity)
.setAutoCancel(true)
.build();
notify_manager.notify(0, notification_popup);
addStars();
}
#Override
public IBinder onBind(Intent intent) { return null; }
You can not, the Doc reference states that once cancelled you need to create a new instance...
the Doc:
Note that calling this method from within the run method of a
repeating timer task absolutely guarantees that the timer task will
not run again.
So basically after cancel you need a new one...

Notification class does not work properly

I created a simple service and now I am making a notification for this. I am writing a class for notification. After writing all code, three lines are underlined with red color one is this function getSystemService(ns); at line 14, second is this one getApplicationContext(); on line 20 and the third one is again same function as first one but on line 31 in cancelNotification() function. here is my complete code
package com.zafar.batterynotify;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
public class Notify {
private static final int NOTIFICATION_ID = 1;
public void initNotification() {
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
int icon = R.drawable.ic_launcher;
CharSequence tickerText = "Service Started";
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when);
notification.flags = Notification.FLAG_ONGOING_EVENT;
Context context = getApplicationContext();
CharSequence contentTitle = "Ongoing service";
CharSequence contentText = "This is service is ongoing";
Intent notificationIntent = new Intent(context, BatteryNotify.class);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, notification);
}
public void cancelNotification() {
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
mNotificationManager.cancel(NOTIFICATION_ID);
}
}
Edit Updated code
My service class
package com.zafar.batterynotify;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class BatteryService extends Service {
Notify notification = new Notify();
String ns = Context.NOTIFICATION_SERVICE;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
notification.initNotification(Context.NOTIFICATION_SERVICE);
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
public void onDestroy() {
super.onDestroy();
notification.cancelNotification(Context.NOTIFICATION_SERVICE);
Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show();
}
}
Notify class
package com.zafar.batterynotify;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
public class Notify {
private static final int NOTIFICATION_ID = 1;
public void initNotification(Context actContext) {
//String ns = Context.NOTIFICATION_SERVICE;
//Context context = actContext.getApplicationContext();
NotificationManager mNotificationManager = actContext.getSystemService(ns);
int icon = R.drawable.ic_launcher;
CharSequence tickerText = "Service Started";
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when);
notification.flags = Notification.FLAG_ONGOING_EVENT;
Context context = actContext.getApplicationContext();
CharSequence contentTitle = "Ongoing service";
CharSequence contentText = "This is service is ongoing";
Intent notificationIntent = new Intent(context, BatteryNotify.class);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, notification);
}
public void cancelNotification(Context actContext) {
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = actContext.getSystemService(ns);
mNotificationManager.cancel(NOTIFICATION_ID);
}
}
don't try to use getApplicationContext(), instead create MyApplication class, inherited from the Application, then inside that class do the following:
public class MyApplication extends Application {
private static MyApplication instance;
#Override
public void onCreate() {
super.onCreate();
instance = this;
.........
}
public static Context getContext() {
return instance;
}
After that, you may use MyApplication.getContext() anywhere if you need a context and don't have an Activity lying around.
Pass your context from calling Activity or service to your class and use it:
public void initNotification(Context actContext) {
//...
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = actContext.getSystemService(ns);
//...
}
public void cancelNotification(Context actContext) {
//...
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = actContext.getSystemService(ns);
//...
}

Categories