Instantiate non-activity class on pending intent in android - java

i have a notification in android, and i want to do something like
MyStaticClass.start() when i click in the notification, this class is not an activity, its only to instantiate a needed class.
How can i do it it?
This is my actually code:
String notificationContent = "Hay una nueva version disponible";
String notificationTitle = "Firext";
Bitmap largeIcon = BitmapFactory.decodeResource(FirextApplication.getInstance().getResources(), R.drawable.ic_launcher);
int smalIcon = R.drawable.ic_launcher;
Intent intent = new Intent(FirextApplication.getInstance(), UpdateProcess.class);
intent.setData(Uri.parse("content://" + Calendar.getInstance().getTimeInMillis()));
PendingIntent pendingIntent = PendingIntent.getActivity(FirextApplication.getInstance(), 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK);
NotificationManager notificationManager = (NotificationManager) FirextApplication.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(
FirextApplication.getInstance())
.setWhen(Calendar.getInstance().getTimeInMillis())
.setContentText(notificationContent)
.setContentTitle(notificationTitle)
.setSmallIcon(smalIcon)
.setAutoCancel(true)
.setTicker(notificationTitle)
.setLargeIcon(largeIcon)
.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_SOUND)
.setContentIntent(pendingIntent);
Notification notification = notificationBuilder.build();
notificationManager.notify((int) Calendar.getInstance().getTimeInMillis(), notification);
And the class i need to call
public class UpdateProcess {
private static final String APPLICATION_VND_ANDROID_PACKAGE_ARCHIVE = "application/vnd.android.package-archive";
private static final String NEWVERSION = "NewVersion.apk";
private static final File EX = Environment.getExternalStorageDirectory();
private static volatile UpdateProcess instance = null;
private Activity activity;
private UpdateProcess(Activity activity) {
this.activity = activity;
checkForNewUpdates();
}
public static void startUpdate(Activity activity) {
if (instance == null) {
synchronized (UpdateProcess.class) {
if (instance == null) {
instance = new UpdateProcess(activity);
}
}
} else {
UpdateProcess.instance.activity = activity;
}
}
I only need do a UpdateProcess.startUpdate();
Edit:
This is my new code:
private void showNot() {
String notificationContent = "Hay una nueva version disponible";
String notificationTitle = "Firext";
Bitmap largeIcon = BitmapFactory.decodeResource(FirextApplication.getInstance().getResources(), R.drawable.ic_launcher);
int smalIcon = R.drawable.ic_launcher;
Intent intent = new Intent(FirextApplication.getInstance(), UpdateProcess.class);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
Notification notificationBuilder = new NotificationCompat.Builder(context)
.setWhen(Calendar.getInstance().getTimeInMillis())
.setContentText(notificationContent)
.setContentTitle(notificationTitle)
.setSmallIcon(smalIcon)
.setTicker(notificationTitle)
.setLargeIcon(largeIcon)
.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_SOUND)
//.setContentIntent(pendingIntent)
.addAction(android.R.drawable.arrow_up_float, "Call", pendingIntent).build();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder);
}
public class UpdateProcess extends IntentService {
private static final String APPLICATION_VND_ANDROID_PACKAGE_ARCHIVE = "application/vnd.android.package-archive";
private static final String NEWVERSION = "NewVersion.apk";
private static final File EX = Environment.getExternalStorageDirectory();
private static volatile UpdateProcess instance = null;
private Context context;
private UpdateProcess(Context context) {
super("UpdateProcess");
this.context = context;
checkForNewUpdates();
}
#Override
protected void onHandleIntent(Intent intent) {
startUpdate(getApplicationContext());
}
But when i do click in action nothing happens..i get thi error:
05-10 17:15:22.955 753-7617/? W/ActivityManager﹕ Unable to start service Intent { flg=0x10000000 cmp=com.firext.android/.util.UpdateProcess bnds=[192,346][1080,490] } U=0: not found
Edit 2. Now works, i forget include service in manifest

I need to show a toast message in a method inside UpdateProcess, what i should use?
Your Notification can trigger an Activity, a Service, or a BroadcastReceiver via its PendingIntent. Activity is a Context. Service is a Context. BroadcastReceiver receives a Context as a parameter to onReceive(). Hence, from all three locations, you already have a Context, so use that one.
You might also consider getting rid of the Toast entirely. A Toast is only good for a message that the user does not need, as the user might not see it.
I only need do a UpdateProcess.startUpdate();
It would appear that checkForNewUpdates() will do some significant work.
If that work will take less than ~15 seconds, convert UpdateProcess to UpdateIntentService, extending IntentService, and do your checkForNewUpdates() work in onHandleIntent(). You can use a getService() PendingIntent to trigger the UpdateIntentService to do its work.
If the work is likely to take longer than that, you should consider using the WakefulBroadcastReceiver pattern (or perhaps my WakefulIntentService), to ensure that the device stays awake long enough for your work to complete.

Instead to use getActivity() use getService() in you pending intent. Create an ad-hoc intent service to call UpdateProcess.startUpdate() in onHandleIntent(). In this case you can't use an activity as parameter of course, but maybe you can change the parameter in a Context.

Related

How to show notification with ringing alarm in background?

guys, I am developing an alarm app in which alarm is triggering good and at the right time but the drawback is when the alarm is ringing with an activity then when we press the home button too it is ringing the real problem is when the application is closed by pressing the home button and pressing or swiping close all apps the application getting destroyed I need something like Google does like showing a notification and playing sound even if the application is closed.
So I think someone is having Idea about this issue.
Here is what from Google Clock
Googel Clock image
Because of android Q, I had developed something that when the user is alive at the time of alarm then we just show notification with the help of this.
public class DismissAlarmNotificationController {
public final int NOTIFICATION_ID = 1;
public static final String INTENT_KEY_NOTIFICATION_ID = "notificationId";
public final String CHANNEL_ID = "channel-01";
private NotificationManager notificationManager;
private Context context;
private final int IMPORTANCE = NotificationManager.IMPORTANCE_HIGH;
public DismissAlarmNotificationController(Context context) {
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
this.context = context;
}
public void showNotification() {
Intent fullScreenIntent = new Intent(context, DismissAlarmActivity.class);
PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(context, 0,
fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(
CHANNEL_ID, getChannelName(), IMPORTANCE);
notificationManager.createNotificationChannel(notificationChannel);
}
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_alarm_on_notification)
.setContentTitle(context.getString(R.string.dismiss_alarm_notification_title))
.setContentText(context.getString(R.string.dismiss_alarm_notification_body, getCurrentTime()))
.setAutoCancel(true)
.addAction(getDismissNotificationAction())
.setFullScreenIntent(fullScreenPendingIntent, true);
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
}
public String getChannelName() {
return context.getString(R.string.app_name) + "Channel";
}
public void cancelNotification() {
notificationManager.cancelAll();
}
private NotificationCompat.Action getDismissNotificationAction() {
Intent dismissIntent = new Intent(context, DismissNotificationReceiver.class);
dismissIntent.putExtra(INTENT_KEY_NOTIFICATION_ID, NOTIFICATION_ID);
PendingIntent dismissNotificationPendingIntent = PendingIntent.getBroadcast(context, 0, dismissIntent, PendingIntent.FLAG_CANCEL_CURRENT);
return new NotificationCompat.Action.Builder(
0,
context.getString(R.string.dismiss_alarm_notification_dismiss_button_title),
dismissNotificationPendingIntent)
.build();
}
private String getCurrentTime() {
SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm");
Date currentTime = new Date();
return dateFormat.format(currentTime);
}
}
Thanks in advance.
Give a try to Android's WorkManager!
It lets you run background works even if the app is closed or the phone has been restarted.
Hope it will help!

Run only foreground service when app is closed to reduce memory usage

I am running a foreground service via broadcast receiver on boot completed.
It starts the services as desired and take only a a fraction of the device memory use and when I launch the app it increased the device memory usage as it should but when I close the app it still takes too much of memory even though the app has been closed and only the foreground service is running. What I want is really that it should use the same amount of memory after app has been closed as of it was using before the app was opened.
So, I did some digging through Android Profiler and what I found is that when foreground service starts after the boot it only opens Application.class, BroadcastReceiver.class, Service.class and few other background classes. And as I open the app it opens all the above classes and other activities . But when I close the app it still uses the device memory for graphic supports. I don't know how to stop that memory usage after the app has been closed.
Here are some screenshots of my Android Profiler
Before Launching the App through Foreground Notification Memory used 65MB
remember the foreground notification was started from the broadcast receiver after boot complete.
After Launching the app from Notifications Memory used 146 MB
While surfing through activities Memory used 165 MB
After app has been closed Memory used 140 MB
Now I want to know how to achieve the task of using the previous amount of memory use that was 65MB?
Here are my BroadcastReceiver and Service.class code.
Broadcast Receiver
public class BootCompletedIntentListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())){
Intent serviceIntent = new Intent(context,ClipMonitorService.class);
ContextCompat.startForegroundService(context,serviceIntent);
}
}
}
Service
public class ClipMonitorService extends Service {
private static final String TAG = "ClipboardManager";
private ExecutorService mThreadPool = Executors.newSingleThreadExecutor();
private ClipboardManager mClipboardManager;
private PrefManager prefManager;
#Override
public void onCreate() {
super.onCreate();
prefManager = new PrefManager(this);
}
#Override
public void onDestroy() {
super.onDestroy();
if (mClipboardManager != null) {
mClipboardManager.removePrimaryClipChangedListener(
mOnPrimaryClipChangedListener);
}
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Intent settingIntent = new Intent(this, SettingActivity.class);
PendingIntent pendingSettIntent = PendingIntent.getActivity(this, 0, settingIntent, 0);
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.custom_notification_layout);
remoteViews.setOnClickPendingIntent(R.id.btn_action, pendingSettIntent);
remoteViews.setTextViewText(R.id.notif_subtitle, "1 Clips copied Today");
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContent(remoteViews)
.setVisibility(Notification.VISIBILITY_SECRET)
.setPriority(NotificationCompat.PRIORITY_MIN)
.setContentIntent(pendingIntent)
.setColor(getResources().getColor(R.color.colorPrimary))
.setShowWhen(false)
.build();
startForeground(1, notification);
mClipboardManager =
(ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
mClipboardManager.addPrimaryClipChangedListener(
mOnPrimaryClipChangedListener);
return START_STICKY;
}
private ClipboardManager.OnPrimaryClipChangedListener mOnPrimaryClipChangedListener =
new ClipboardManager.OnPrimaryClipChangedListener() {
#Override
public void onPrimaryClipChanged() {
Log.d(TAG, "onPrimaryClipChangeds");
try {
String textToPaste = mClipboardManager.getPrimaryClip().getItemAt(0).getText().toString();
if (textToPaste.length() > 200) {
if (prefManager.isClipNotifOns()) {
mThreadPool.execute(new MakeNotifRunnable(
textToPaste));
}
}
} catch (Exception ignored) {
}
}
};
private class MakeNotifRunnable implements Runnable {
private final CharSequence mTextToWrite;
public MakeNotifRunnable(CharSequence text) {
mTextToWrite = text;
}
#Override
public void run() {
Intent notifIntent = new Intent(getApplicationContext(), PostNewsActivity.class);
notifIntent.putExtra("post", mTextToWrite);
NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
int notificationId = 2;
String channelId = "channel1";
String channelName = "Clipboard Monitor Notification";
int importance = 0;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
importance = NotificationManager.IMPORTANCE_DEFAULT;
}
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel mChannel = new NotificationChannel(
channelId, channelName, importance);
notificationManager.createNotificationChannel(mChannel);
}
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext(), channelId)
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle("Verify copied content")
.setContentText(mTextToWrite)
.setAutoCancel(true)
.setOnlyAlertOnce(true);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(getApplicationContext());
stackBuilder.addNextIntent(notifIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
notificationManager.notify(notificationId, mBuilder.build());
}
}
}
Help me to reduce memory usage
I'll be thankful for your answer.
P.S: As I am new to android development I may have uploaded too much information with jargons .Pardon me for that.

BroadcastReceiver is not working properly while in others it does

i am making an app that required to inform the user with a notification when a specific date is approaching.
I use a Client class as a 'middle man' between activity and a Service. Once i bind the service, i call a method that interacts with AlarmTask class that uses AlarmManager to set an alarm. And as a last step i send a PendingIntent to start my another class witch is a BroadcastReceiver for my notification.
My problem is that the onReceive() is not called. Code reaches all the way to alarmManager.set() correctly. I read many posts and tried different ways to register my BroadcastReceiver. Any ideas on what might be wrong?
AlarmTask
public class AlarmTask implements Runnable {
private final Calendar date;
private final AlarmManager alarmManager;
private final Context context;
private long mGoalId;
public AlarmTask(Context context, Calendar date, long goalId) {
this.context = context;
this.alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
this.date = date;
mGoalId = goalId;
}
#Override
public void run() {
Log.e("AlarmTask", "run executed with request code: " + mGoalId);
// Request to start the service when the alarm date is upon us
Intent intent = new Intent(context, NotificationReceiver.class);
intent.putExtra(NotificationReceiver.INTENT_NOTIFY, true);
// mGoalId is the unique goal id that is gonna be used for deletion
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, (int)mGoalId, intent, 0);
alarmManager.set(AlarmManager.RTC, date.getTimeInMillis(), pendingIntent);
}
}
NotificationReceiver
public class NotificationReceiver extends BroadcastReceiver {
// Unique id to identify the notification.
private static final int NOTIFICATION = 123;
public static final String INTENT_NOTIFY = "com.test.name.services.INTENT_NOTIFY";
private NotificationManager notificationManager;
#Override
public void onReceive(Context context, Intent intent) {
Log.e("onReceive", "Broadcast fired : " + intent);
CharSequence title = "Alarm!!";
int icon = R.drawable.goal;
CharSequence text = "Your notification time is upon us.";
long time = System.currentTimeMillis();
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setSmallIcon(icon);
builder.setContentTitle(title);
builder.setContentText(text);
builder.setVibrate(new long[] { 0, 200, 100, 200 });
final Notification notification = builder.build();
notificationManager.notify(NOTIFICATION, notification);
}
}
Manifest
<receiver android:name=".broadcasts.NotificationReceiver"></receiver>

Repeating notification sound

Is it possible (and if yes how) to make push notification sound repeat until it's read? I am creating app that notifies user about new event in app, but user needs to read notification as soon as possible. When user "reads" notification it should stop ringing. Here's code:
public class GCMIntentService extends IntentService {
String mes;
HelperGlobals glob;
public GCMIntentService() {
super("GcmIntentService");
}
#SuppressLint("SimpleDateFormat")
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
glob = (HelperGlobals) getApplicationContext();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
// .... Doing work here
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
public void createPush(String title, String msg, Intent intent) {
Uri soundUri = Uri.parse("android.resource://example.project.com/" + R.raw.notification);
Context context = getApplicationContext();
Intent notificationIntent = new Intent(context, DoNothing.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification n = new Notification.Builder(this)
.setContentTitle(title)
.setContentText(msg)
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pIntent)
.setAutoCancel(true).build();
n.defaults |= Notification.DEFAULT_VIBRATE;
//n.defaults |= Notification.DEFAULT_SOUND;
n.sound = soundUri;
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(0, n);
}
}
And BroadcastReceiver:
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("BukuLog", "Receiver");
// Explicitly specify that GcmMessageHandler will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(),
GCMIntentService.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
like this:
Notification note = mBuilder.build();
//here
note.flags = Notification.FLAG_INSISTENT;
mNotificationManager.notify(1, note);
int FLAG_INSISTENT : Bit to be bitwise-ored into the flags field that if set, the audio will be repeated until the notification is cancelled or the notification window is opened.
follow android developer

Android context choice

I don't understand which context I should use in
(mApplicationContext or context parameter from onRecieve method). Please, could you give me some explanation what context parameter I should use and why (I read about memory leaks, documentation for this methods)
final PendingIntent pendingIntent = PendingIntent.getActivity(**mApplicationContext**, <smth>);
Notification.Builder notificationBuilder = new Notification.Builder( **mApplicationContext**).<smth>;
NotificationManager notificationManager = (NotificationManager) **mApplicationContext**.getSystemService(Context.NOTIFICATION_SERVICE);
// Constructor
public DownloaderTask(MainActivity parentActivity) {
super();
mParentActivity = parentActivity;
mApplicationContext = parentActivity.getApplicationContext();
}
mApplicationContext.sendOrderedBroadcast(new Intent(
MainActivity.DATA_REFRESHED_ACTION), null,
new BroadcastReceiver() {
final String failMsg = "Download has failed. Please retry Later.";
final String successMsg = "Download completed successfully.";
#Override
public void onReceive(Context context, Intent intent) {
if (getResultCode() != Activity.RESULT_OK) {
final PendingIntent pendingIntent = PendingIntent
.getActivity(mApplicationContext, <smth>);
RemoteViews mContentView = new RemoteViews(
mApplicationContext.getPackageName(),
R.layout.custom_notification);
if(success){
mContentView.setTextViewText(R.id.text,
successMsg);
} else {
mContentView.setTextViewText(R.id.text, failMsg);
}
Notification.Builder notificationBuilder = new Notification.Builder(
mApplicationContext).<smth>;
notificationBuilder.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) mApplicationContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(MY_NOTIFICATION_ID, notificationBuilder.build());
log("Notification Area Notification sent");
}
}
}, null, 0, null, null);
}
Always use the most specific context that you have. Use "this" in activities, and the context that is provided to you through methods.
Leave the application context to those cases where you can't have access to an activity context.
speaking generally, if you are in an activity, 'this' is your context ( remember to import android.content.Context; ), you can also pass the context to your fragments.
There are other times when it's a good idea to getApplicationContext, like in services launching alarms and such, but you'd do well to think of the activity you are working with as the context and you'll find out about the other exceptions as you go along.
keeping to this pattern, it is always informative when you think you have access to a context but you realize you don't; consider what exactly you are trying to do with that object, and what part of the program it "belongs" to.
So, inferring what constructed this object, another activity did DownloaderTask(this) or DownloaderTask(this.context) or DownloaderTask(getApplicationContext); I'd do it the first of those ways and just form the constructor here with public void DownloaderTask(Context context) =]

Categories

Resources