I am working on a simple Service application which increments a counter ever 1 second and shows notification after every 10 seconds. I have used thread so, when I close my app service runs in the background.
Problem- Everything is working fine but when I immediately press back button after starting the counter on button click. My App crashes. Can somebody tell me what is the problem? Thanks!
public class MyService extends Service {
private static final int NOTIFICATION_ID = 5453;
String s;
boolean flag=true;
int cooo;
int m;
int n=0;
private void triggerNotification(final int text){ //Notification Triggering Function
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.ic_action_noti);
Intent intent = new Intent(this, ServiceActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(ServiceActivity.class); // Creates a virtual stack so that when back key is pressed main activity will be displayed
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT
);
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
CharSequence tickerText="Current Counter Value :"+text;
Notification notification = new Notification.Builder(this)
.setLargeIcon(bm)
.setSmallIcon(R.drawable.ic_action_noti) // Setting Notification Icon
.setContentTitle(getString(R.string.notification)) // Setting Title of Notification
.setAutoCancel(true) // Makes this notification automatically dismissed when the user touches it
.setPriority(Notification.PRIORITY_MAX) // Setting priority to Max
.setContentIntent(pendingIntent)
.setContentText(tickerText)
.setLights(0xFF0000FF, 100,3000)
.setSound(soundUri)
.build();
notification.defaults |= Notification.DEFAULT_VIBRATE;
notification.defaults |= Notification.DEFAULT_SOUND;
NotificationManager notificationManager = //Notification Manager
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(NOTIFICATION_ID, notification);
// Log.d(TAG, "Notification sent successfully.");
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
} //Default function of service class
public int onStartCommand(Intent intent, int flags, int startID){ //Function recieving intent from startService
cooo=intent.getIntExtra("cont", 0);
s=Integer.toString(cooo);
Thread thread=new Thread(new Runnable() {
#Override
public void run() { //Thread Initialized
while(flag){
try{ Log.d("The counter value is:", s + " ");
m=Integer.parseInt(s);
m++;
n++;
s=Integer.toString(m);
if(n%10==0){
Log.d("Notification Triggered", "Congrats!");
triggerNotification(m);
}
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread.start(); //Thread Started
return super.onStartCommand(intent,flags,startID); //sending intent again
}
public void onDestroy(){ //function call on stop button pressed
super.onDestroy();
flag=false;
Log.d("Notification Triggered","on stop Button");
triggerNotification(m);
//Toast.makeText(getApplicationContext(),"stopped",Toast.LENGTH_LONG).show();
}
}
Error Log-
04-06 23:06:11.450 16940-16940/headfirst.com.serviceapplication
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start service
headfirst.com.serviceapplication.MyService#427724e8 with null:
java.lang.NullPointerException
at
android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2850)
at android.app.ActivityThread.access$2000(ActivityThread.java:159)
at
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1419)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5419)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at
headfirst.com.serviceapplication.MyService.onStartCommand(MyService.java:72)
at
android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2833)
at android.app.ActivityThread.access$2000(ActivityThread.java:159)
at
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1419)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5419)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
at dalvik.system.NativeStart.main(Native Method)
Related
any body knows why this error occur, Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION on getMediaProjection() even i call getMediaProjection() method after calling startforeground() method..!
Stack Trace is :
Process: com.al1.screenrecorder, PID: 24641
java.lang.RuntimeException: Unable to start service com.al1.screenrecorder.service.DisplayRecorderService#9ef2101 with Intent { cmp=com.al1.screenrecorder/.service.DisplayRecorderService (has extras) }: java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4661)
at android.app.ActivityThread.access$2900(ActivityThread.java:292)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2246)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8147)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
Caused by: java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
at android.os.Parcel.createException(Parcel.java:2071)
at android.os.Parcel.readException(Parcel.java:2039)
at android.os.Parcel.readException(Parcel.java:1987)
at android.media.projection.IMediaProjection$Stub$Proxy.start(IMediaProjection.java:231)
at android.media.projection.MediaProjection.<init>(MediaProjection.java:75)
at android.media.projection.MediaProjectionManager.getMediaProjection(MediaProjectionManager.java:104)
at com.al1.screenrecorder.service.DisplayRecorderService.createMediaProjection(DisplayRecorderService.java:118)
at com.al1.screenrecorder.service.DisplayRecorderService.onStartCommand(DisplayRecorderService.java:107)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4641)
at android.app.ActivityThread.access$2900(ActivityThread.java:292)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2246)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8147)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
Caused by: android.os.RemoteException: Remote stack trace:
at com.android.server.media.projection.MediaProjectionManagerService$MediaProjection.start(MediaProjectionManagerService.java:498)
at android.media.projection.IMediaProjection$Stub.onTransact(IMediaProjection.java:135)
at android.os.Binder.execTransactInternal(Binder.java:1028)
at android.os.Binder.execTransact(Binder.java:1001)
strong text
private void startForeground() {
Intent activityIntent = new Intent(this, MainActivity.class);
activityIntent.setAction("stop");
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String channelId = "001";
String channelName = "myChannel";
NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_NONE);
channel.setLightColor(Color.BLUE);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (manager != null) {
manager.createNotificationChannel(channel);
Notification notification = new Notification.
Builder(getApplicationContext(), channelId)
.setOngoing(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setCategory(Notification.CATEGORY_SERVICE)
.setContentTitle(getString(R.string.ClickToCancel))
.setContentIntent(contentIntent)
.build();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startForeground(0, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION);
} else {
startForeground(0, notification);
}
}
} else {
startForeground(0, new Notification());
}
}
and onStartCommand is :
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service onStartCommand() is called");
startForeground();
mResultCode = intent.getIntExtra("code", -1);
mResultData = intent.getParcelableExtra("data");
mScreenWidth = intent.getIntExtra("width", 720);
mScreenHeight = intent.getIntExtra("height", 1280);
mScreenDensity = intent.getIntExtra("density", 1);
isVideoSd = intent.getBooleanExtra("quality", true);
isAudio = intent.getBooleanExtra("audio", true);
mMediaProjection = createMediaProjection();
mMediaRecorder = createMediaRecorder();
mVirtualDisplay = createVirtualDisplay();
mMediaRecorder.start();
return Service.START_STICKY;
}
and exception is in this method on getMediaProjection:
private MediaProjection createMediaProjection() {
Log.i(TAG, "Create MediaProjection");
return ((MediaProjectionManager) Objects.requireNonNull(getSystemService(Context.MEDIA_PROJECTION_SERVICE))).
getMediaProjection(mResultCode, mResultData);
}
Add android:foregroundServiceType="mediaProjection" to the <service> element in the manifest for your service.
You have to start a foreground service bit before you create media projection.
If you have already a service, there will be a delay to start the service most times even if you start service before you initialize media projection. Start projection after a slight delay after you start the service. I think this will do the trick.
code sample:
startService(new Intent(AppController.getInstance(),
ScreenCaptureService.class));
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
MediaProjectionManager projectionManager = (MediaProjectionManager)
context.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
if (isServiceActive(context, ScreenCaptureService.class)){
mMediaProjection =
projectionManager.getMediaProjection(resultCode, data);
processAndSaveScreenshotFromDevice(context);
}
}
}, 200);
Please make sure you have granted the required FOREGROUND_SERVICE permissions. If your targetSdkVersion = 28 using foreground services must request the FOREGROUND_SERVICE permission.
So add FOREGROUND_SERVICE permission to your manifest file without which it throws SecurityException.
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
You can read more about this migration notes: https://developer.android.com/about/versions/pie/android-9.0-migration#tya
Hope this will help you.....
Wrapping getMediaProjection(mResultCode, mResultData) inside a Handler().postDelayed() solved the problem for me.
override fun onServiceConnected(className: ComponentName, service: IBinder) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
val binder = service as MediaProjectionService.LocalBinder
mediaProjectionService = binder.getService()
// delay needed because getMediaProjection() throws an error if it's called too soon
Handler().postDelayed({
mediaProjection = mediaProjectionManager.getMediaProjection(activityResultCode, activityData)
startStreaming()
serviceBound = true
}, 1000)
}
The problem with OP's code was that he used
startForeground(0, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION);
Docs explicitly say:
Params: id – The identifier for this notification as per NotificationManager.notify(int, Notification); must not be 0.
Try this: https://stackoverflow.com/a/68343645/5182769. The key is you must create notification channel in onStartCommand firstly.
After adding the foreground permission <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />, you need to create a service class.So in a new Java file have this:
public class BackgroundService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
createNotificationChannel();
Intent intent1 = new Intent(this, ClassWithError.class);
Intent intent2 = new Intent(this, AnotherClassWithError.class);
PendingIntent pendingIntent1 = PendingIntent.getActivity(this, 0, intent1, 0);
PendingIntent pendingIntent2 = PendingIntent.getActivity(this, 0, intent2, 0);
Notification notification1 = new NotificationCompat.Builder(this, "ScreenRecorder")
.setContentTitle("yNote studios")
.setContentText("Filming...")
.setContentIntent(pendingIntent1).build();
Notification notification2 = new NotificationCompat.Builder(this, "ScreenRecorder")
.setContentTitle("yNote studios")
.setContentText("Filming...")
.setContentIntent(pendingIntent1).build();
startForeground(1, notification1);
startForeground(2, notification2);
return super.onStartCommand(intent, flags, startId);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
NotificationChannel channel = new NotificationChannel("ScreenRecorder", "Foreground notification",
NotificationManager.IMPORTANCE_DEFAULT);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
}
#Override
public void onDestroy() {
stopForeground(true);
stopSelf();
super.onDestroy();
}
}
Then back in the manifest, add the service segment with the name section as the above service class. It should be within the application segment.
<service
android:name=".Services.BackgroundService"
android:enabled="true"
android:exported="true"
android:stopWithTask="true"
android:foregroundServiceType="mediaProjection" />
After setting it up like that, you can access this background service whenever you need it (in the onCreate method) as follows:
Intent intent = new Intent(this, BackgroundService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent);
} else {
startService(intent);
}
But be sure to manage it. It may be the cause of several exceptions in other functions within your project. Things like media recorders will crush when invoked while this service is running. For this, use the onDestroy method to close the service.
everyone! I'm working on my project - MusicApp and I want to know how to update foreground service? I read the posts but I got an error:
2019-04-13 21:11:31.351 19279-19279/com.example.musicapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.musicapp, PID: 19279
java.lang.NullPointerException: class name is null
at android.content.ComponentName.<init>(ComponentName.java:116)
at android.app.Service.startForeground(Service.java:695)
at com.example.musicapp.MusicForegroundService.startForeground(MusicForegroundService.java:119)
at com.example.musicapp.activities.MainActivity$14.playSong(MainActivity.java:586)
at com.example.musicapp.MusicService.playSong(MusicService.java:93)
at com.example.musicapp.activities.MainActivity$3.onItemClickListener(MainActivity.java:315)
at com.example.musicapp.adapters.SongsRecyclerViewAdapter$SongsViewHolder$1.onClick(SongsRecyclerViewAdapter.java:83)
at android.view.View.performClick(View.java:7339)
at android.view.View.performClickInternal(View.java:7305)
at android.view.View.access$3200(View.java:846)
at android.view.View$PerformClick.run(View.java:27788)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7073)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)
I have got the next code in my MainActivity class:
mForegroundService = new MusicForegroundService(MainActivity.this);
if (!isForegroundServiceRunning(MusicForegroundService.class)) {
// first time, create the foreground service
mForegroundService.startForeground();
mForegroundService.updateForegroundNotification(mCurrentSong.getTitle(), mCurrentSong.getArtist());
} else {
mForegroundService.updateForegroundNotification(
mCurrentSong.getTitle(),
mCurrentSong.getArtist());
}
My Music Foreground Service:
public class MusicForegroundService extends Service {
private static final int NOTIFICATION_ID = 1;
private static final String CHANNEL_ID = "channel_id_01";
private Context mContext;
private NotificationManager mNotificationManager;
private Notification mNotification;
private RemoteViews mRemoteViews;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
public MusicForegroundService(Context context) {
mContext = context;
}
public void startForeground() {
mNotificationManager =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
// create the notification channel
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(
CHANNEL_ID,
"Music foreground service",
NotificationManager.IMPORTANCE_LOW);
notificationChannel.enableVibration(false);
notificationChannel.enableLights(false);
if (mNotificationManager != null) {
mNotificationManager.createNotificationChannel(notificationChannel);
}
}
Intent notificationIntent = new Intent();
PendingIntent notificationPendingIntent = PendingIntent.getActivity(
mContext,
MUSIC_SERVICE_REQUEST_CODE,
notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
mRemoteViews =
new RemoteViews(mContext.getPackageName(), R.layout.partial_music_notification);
NotificationCompat.Builder builder = new NotificationCompat.Builder(
mContext,
CHANNEL_ID);
builder.setAutoCancel(false)
.setCustomContentView(mRemoteViews)
.setTicker(mContext.getString(R.string.app_name))
.setContentIntent(notificationPendingIntent)
.setSmallIcon(R.drawable.ic_stat_notify_music);
mNotification = builder.build();
startForeground(NOTIFICATION_ID, mNotification);
}
// update text
public void updateForegroundNotification(String title, String artist) {
mRemoteViews.setTextViewText(R.id.text_title_notification, title);
mRemoteViews.setTextViewText(R.id.text_info_notification, artist);
mNotificationManager.notify(NOTIFICATION_ID, mNotification);
}
}
Can anybody help me in my case? I don't know why I got the error. At the first I tried to start the foreground service and then I wanted to add text(update).
Hi i use this post Background process timer on android for the timeer in background process
my timer code in main activity is
int repeatTime = 5;
AlarmManager processTimer = (AlarmManager)getSystemService(ALARM_SERVICE);
Intent intent = new Intent(this, processTimerReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
processTimer.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),repeatTime*1000, pendingIntent);
and my code in class processTimerReceiver is:
public class processTimerReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
MainActivity m = new MainActivity();
m.get_start_info();
}
}
i want to call method get_start_info() in main activity but app crashed
full my main activity is :
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.activity_main);
int repeatTime = 5;
AlarmManager processTimer = (AlarmManager)getSystemService(ALARM_SERVICE);
Intent intent = new Intent(this, processTimerReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
processTimer.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),repeatTime*1000, pendingIntent);
get_start_info();
}
public void get_start_info() {
JsonArrayRequest movieReq = new JsonArrayRequest("www.example.com",
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
try {
JSONObject obj = response.getJSONObject(0);
// any
sendNotification();
//any
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
AppController.getInstance().addToRequestQueue(movieReq);
}
public void sendNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(android.R.drawable.ic_dialog_email);
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Intent intent = new Intent(MainActivity.this, azegar_mail_list.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
//mp.start();
builder.setContentIntent(pendingIntent);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
builder.setContentTitle("آزگار");
builder.setContentText("نامه جدید برای شما ارسال شده است");
builder.setAutoCancel(true);
builder.setSound(soundUri);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Will display the notification in the notification bar
notificationManager.notify(1, builder.build());
}
}
my error is :
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start receiver com.azegar.www.azegar.processTimerReceiver: java.lang.NullPointerException
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2539)
at android.app.ActivityThread.access$1500(ActivityThread.java:167)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1432)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:153)
at android.app.ActivityThread.main(ActivityThread.java:5341)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:929)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at android.content.ContextWrapper.getResources(ContextWrapper.java:89)
at android.view.ContextThemeWrapper.getResources(ContextThemeWrapper.java:78)
at android.support.v7.app.AppCompatActivity.getResources(AppCompatActivity.java:551)
at android.content.Context.getString(Context.java:327)
at com.azegar.www.azegar.MainActivity.get_start_info(MainActivity.java:438)
at com.azegar.www.azegar.processTimerReceiver.onReceive(processTimerReceiver.java:12)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2532)
at android.app.ActivityThread.access$1500(ActivityThread.java:167)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1432)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:153)
at android.app.ActivityThread.main(ActivityThread.java:5341)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:929)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)
at dalvik.system.NativeStart.main(Native Method)
First of all, if you are calling get_start_info() outside of the MainActivity, then move get_start_info() and sendNotification out of MainActivity.
You are getting a NullPointerException because you are trying to use MainActivity's context to build a notification inside sendNotification and that context is null because you are instantiating MainActivity with the new keyword (You should not instantiate a new activity with the new keyword). Instead, pass the BroadcastReceiver's context as a parameter to sendNotification and use it to build the notification.
Parts of the code which uses Context:
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
Intent intent = new Intent(MainActivity.this, azegar_mail_list.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
Here, instead of using this, you should use the Context passed as a parameter.
I have a button on my activity that starts a notification and then also starts a Countdown Timer with an Async Task. The purpose of the code is to convert the millisUntilFinished to readable time and send it to my GUI in the second activityI get this fatal exception:
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: com.idkbro.pashchallenge, PID: 25702
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:318)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:200)
at android.os.Handler.<init>(Handler.java:114)
at android.os.CountDownTimer$1.<init>(CountDownTimer.java:114)
at android.os.CountDownTimer.<init>(CountDownTimer.java:114)
at com.idkbro.pashchallenge.MainActivity$1CDTTask$1.<init>(MainActivity.java:0)
at com.idkbro.pashchallenge.MainActivity$1CDTTask.doInBackground(MainActivity.java:250)
at com.idkbro.pashchallenge.MainActivity$1CDTTask.doInBackground(MainActivity.java:196)
at android.os.AsyncTask$2.call(AsyncTask.java:304)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
Here they said the error could be because of trying to update the GUI in the asynctask, but this isnt in my case because í send variable to the activity using an intent service. I think the problem could be how i "set up" my asynctask
The MainActivity class when the accept button is(P.S: so sorry about the code if its a but messy :( ):
public void agreeButton (View v){
Intent intent = new Intent(MainActivity.this, CountdownPage.class);
startActivity(intent);
NotificationCompat.Builder notificationBuiler = new NotificationCompat.Builder(this)
.setContentTitle("Pash Challenge")
.setContentText("You have so many minutes left")//TODO make notification display countdown
.setTicker("Alert new message")
.setSmallIcon(R.drawable.pashicon);//Code to display notification
Intent moreInfoIntent = new Intent(MainActivity.this, MoreInfoNotification.class);
notificationManager =(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notificationID,notificationBuiler.build());
// Used to stack tasks across activites so we go to the proper place when back is clicked
TaskStackBuilder tStackBuilder = TaskStackBuilder.create(this);
// Add all parents of this activity to the stack
tStackBuilder.addParentStack(MoreInfoNotification.class);
// Add our new Intent to the stack
tStackBuilder.addNextIntent(moreInfoIntent);
// Define an Intent and an action to perform with it by another application
// FLAG_UPDATE_CURRENT : If the intent exists keep it but update it if needed
PendingIntent pendingIntent = tStackBuilder.getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT);
// Defines the Intent to fire when the notification is clicked
notificationBuiler.setContentIntent(pendingIntent);
isNotificationActive =true;
class CDTTask extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
Calendar calendar = Calendar.getInstance();
Long preTime = calendar.getTimeInMillis();
calendar.add(Calendar.DATE, 2);// set milliseconds for 2 days
Long postTime = calendar.getTimeInMillis();
Long delay = postTime - preTime;
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
manager.set(AlarmManager.RTC_WAKEUP, postTime, null);
CountDownTimer timer = new CountDownTimer(delay, 1) {
#Override
public void onTick(final long millisUntilFinished) {
runOnUiThread(new Runnable() {
#Override
public void run() {
//SendAndCovert milliseconds to CoundownPage
SAndCDays(millisUntilFinished);
SAndCHours(millisUntilFinished);
SAndCMinutes(millisUntilFinished);
SAndCSeconds(millisUntilFinished);
}//End run
});//End runOnUiThread
}//End onTick
#Override
public void onFinish() {
}//End OnFinish
void SAndCDays(Long milli){ //Code to convert milliseconds to days and send it to CountdownPage.java
Long millis = (milli / (1000*60*60*24));
String days = ""+millis;
Intent numIntent = new Intent(getApplicationContext(), CountdownPage.class);
numIntent.putExtra("days", days);
startActivity(numIntent);
}//End SAndCDays
void SAndCMinutes(Long milli){ //Code to convert milliseconds to minutes and send it to CountdownPage.java
long millis = ((milli / (1000 * 60)) % 60);
String minutes = ""+millis;
Intent numIntent = new Intent(getApplicationContext(), CountdownPage.class);
numIntent.putExtra("minutes", minutes);
startActivity(numIntent);
}//End SAndCMinutes
//Code to convert milliseconds to hours and send it to CountdownPage.java
void SAndCHours(Long milli){
long millis = (milli/ (1000 * 60 * 60)) % 24;
String hours = ""+millis;
Intent numIntent = new Intent(getApplicationContext(), CountdownPage.class);
numIntent.putExtra("hours", hours);
startActivity(numIntent);
}//End SAndCHours
//Code to convert milliseconds to seconds and send it to CountdownPage.java
void SAndCSeconds(Long milli){
long millis = (milli/ 1000) % 60;
String seconds = ""+millis;
Intent numIntent = new Intent(getApplicationContext(), CountdownPage.class);
numIntent.putExtra("seconds", seconds);
startActivity(numIntent);
} //End SAndCSeconds
};
timer.start();
return null;
}//End doInBackground
}
CDTTask object = new CDTTask();
object.execute();//Code to start Countdown Async task
} // End agreeButton
Here is my Alert Receiver class if its of any help:
public class AlertReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
createNotification(context, "Times Up", " x Seconds has past","alert");// TODO change to CDT Time
}//End onReceive
public void createNotification(Context context, String msg,
String txtMsg,String msgAlert) {
PendingIntent notificIntent = PendingIntent.getActivity(context, 0,
new Intent(context, MainActivity.class), 0);
// Builds a notification
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.pashicon)
.setContentTitle(msg)
.setTicker(msgAlert)
.setContentText(txtMsg);
mBuilder.setContentIntent(notificIntent);
mBuilder.setDefaults(NotificationCompat.DEFAULT_SOUND);
mBuilder.setAutoCancel(true);
}//End createNotification
}//End AlertReceiver.class
And how i receive and display the coveted times from the service:
#Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.activity_challenge_page);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
TextView txtTimerDay=(TextView)findViewById(R.id.txtTimerDay);
TextView txtTimerMinute=(TextView)findViewById(R.id.txtTimerMinute);
TextView txtTimerHour=(TextView)findViewById(R.id.txtTimerHour);
TextView txtTimerSecond=(TextView)findViewById(R.id.txtTimerSecond);
txtTimerDay.setText(getIntent().getStringExtra("days"));
txtTimerMinute.setText(getIntent().getStringExtra("minutes"));
txtTimerHour.setText(getIntent().getStringExtra("hours"));
txtTimerSecond.setText(getIntent().getStringExtra("seconds"));
}
I have an app that uses AlarmManager broadcast receiver, and start notification.
Everything was good until (I don't know until, I just observed it).
When I start alarm in certain time, everything works good, but notification repeats several times. I used Integer i = 0; and "Message of Notification" + i++
If there are several alarms, repeats only first.
When notification returns for the second time, there is log.
What is that?
09-28 13:55:55.598 16489-16489/? D/dalvikvm﹕ Late-enabling CheckJNI
09-28 13:55:55.668 16489-16489/com.example.nes.app E/Trace﹕ error opening trace file: No such file or directory (2)
09-28 13:55:55.668 16489-16489/com.example.nes.app D/ActivityThread﹕ setTargetHeapUtilization:0.25
09-28 13:55:55.668 16489-16489/com.example.nes.app D/ActivityThread﹕ setTargetHeapIdealFree:8388608
09-28 13:55:55.668 16489-16489/com.example.nes.app D/ActivityThread﹕ setTargetHeapConcurrentStart:2097152
receiver
public class MyReceiver extends BroadcastReceiver {
public MyReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
Intent service1 = new Intent(context, MyAlarmService.class);
context.startService(service1);
}
}
alarmManager.class
public class MyAlarmService extends Service {
NotificationManager mManager;
SharedPreferences sPref;
String eventCode = "EV_KEY";
int i = 0;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
}
#SuppressWarnings("static-access")
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
mManager = (NotificationManager) this.getApplicationContext().getSystemService(this.getApplicationContext().NOTIFICATION_SERVICE);
Intent intent1 = new Intent(this.getApplicationContext(),onResume.class);
Notification notification = new Notification(R.mipmap.ic_launcher, getResources().getString(R.string.timeToSmoke), System.currentTimeMillis());
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.flags |= Notification.DEFAULT_VIBRATE ;
notification.defaults|= Notification.DEFAULT_SOUND;
notification.flags |= Notification.FLAG_ONLY_ALERT_ONCE;
intent1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
i++;
PendingIntent pendingNotificationIntent = PendingIntent.getActivity(this.getApplicationContext(), 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
notification.setLatestEventInfo(this.getApplicationContext(), getResources().getString(R.string.time), "Text"+String.valueOf(i), pendingNotificationIntent);
Random r = new Random();
int id = r.nextInt(10000 - 50) + 50;
mManager.notify(id, notification);
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
and how do I call Alarm Manager
void StartAlarm(int day, int hour, int minutes) {
calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_MONTH, day);
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minutes);
calendar.set(Calendar.SECOND, 0);
Random r = new Random();
int rcode = r.nextInt(10000 - 50) + 50;
rcodeAlarm.add(String.valueOf(rcode));
Intent myIntent = new Intent(Time.this, MyReceiver.class);
pendingIntent = PendingIntent.getBroadcast(Time.this, rcode, myIntent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
timeAlarm.add(String.valueOf(calendar.getTimeInMillis()));
}
Solved. I just cut all the code from Alarm Manager.class to Broadcast recever.
But the quastion still open. Why first variant gives such error?