Get appwidget position on home screen? - java

I start an activity when a widget icon is clicked.What i want is to send the position of that widget to that activity.I have tried
Intent intent=new Intent(context, WidgetActivity.class);
Bundle bundle = new Bundle();
bundle.putString("rect", bound);
intent.putExtras(bundle);
//intent.putExtra("rect", bound.toString());
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,intent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.pic1);
views.setOnClickPendingIntent(R.id.wbutton1, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
in my onUpdate procedure.But this crashes the activity.
I have heard that the position is returned using intent.getsourceBounds() .Thats in onReceive ryt?i have tried making bound a global variable.setting its value from onReceive as bound=intent.getsourceBounds(); That didn't work either.
So my question is
1.How do i get the widget position using intent.getsourceBounds() in onUpdate?
2.How can i send it to the activity?
Thank you for your time.
edit:i managed to send string from widget to activity like this:
Intent intent=new Intent(context, WidgetActivity.class);
Bundle bundle = new Bundle();
bundle.putString("pos", "hello");
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(context,0,intent,PendingIntent.FLAG_CANCEL_CURRENT);
edit 2: I found https://stackoverflow.com/a/5324918/1685829 which says it can be done using getSourceBounds().Can anyone explain how i can use it in onUpdate.

You don't need to send it; Android does it for you. getSourceBounds() can only be used from inside the activity. This information is not available inside onUpdate().

Related

RemoteViews to LocalBroadcastManager

LocalBroadcastManager does not receive broadcast intent from RemoteViews PendingIntent.
So if it is true then is there any idea or way out to do communicate in between RemoteViews and LocalBroadcastManager?
I am using RemoteViews for Notification custom view, which run within a foreground service.
And when click on button within RemoteViews, it will call a method within service.
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
contentView = new RemoteViews(getPackageName(), R.layout.custom);
Intent intent1 = new Intent("myintent");
PendingIntent pi = PendingIntent.getBroadcast(this, 1, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
contentView.setOnClickPendingIntent(R.id.button,pi);
But LocalBroadcastManager does not receive this.
Yes i kinda sort out this.
Using another BroadcastReceiver as middle man to receive broadcast for PendingIntent and sendbroadcast through LocalBroadcastManager which can receive by service's LBM

extras(notification text) doesn't get passed

the extras ( a notification text) doesn't get passed to the textView, (the text view appears empty), what's the problem?
here's the related code:
AlarmReceiver extends BroadcastReceiver :
https://textuploader.com/1j851
Notification Activity( that should show the text):
https://textuploader.com/1j85j
my main activity:
https://textuploader.com/1j8tr
please excuse me if I did any stupid mistakes, I'm new to programming
I guess this is your problem here. You pass the wrong value here. You make an object i but you are using intent object.
Intent i = new Intent(context,
NotificationActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.putExtra("message",x);
PendingIntent pendingIntent = PendingIntent.getActivity(context,0,i,PendingIntent.FLAG_UPDATE_CURRENT);
So use like this below.
Intent i = new Intent(context,
NotificationActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK); //i
i.putExtra("message",x); //i
PendingIntent pendingIntent = PendingIntent.getActivity(context,0,i,PendingIntent.FLAG_UPDATE_CURRENT);

Redirect to activity with preserving/creating activity stack

I want to start activity from notification. I want to open an activity, which is successor of some other activities.
Example activities: IntroActivity -> Photos -> SpecificPhoto. What I want to achieve: In case user clicks on notification, I want to open SpecificPhoto activity. Keep in mind, that app can be running (for example PhotosActivity is displayed), or it can be shut down.
I want to preserve back button functionality (move to PhotosActivity on back pressed).
On notification click, I need to launch IntroActivity, because user needs to login here in case he is not.
I tried following (using constants in activities, code):
On PhotosActivity onCreate:
redirectToActivity();
RedirectToActivity method:
private void redirectToActivity() {
Intent intent = getIntent();
int activityCode = intent.getIntExtra("code", 0);
switch (activityCode) {
case SpecificPhotoActivity.CODE:
startActivity(new Intent(this, SpecificPhotoActivity.class));
break;
default:
return;
}
}
By applying this approach, I can traverse the whole activity stack and go to the activity I want. However, this approach is not working in every case. Sometimes, the activity_code is not set (don't know why) and therefore we end in the first activity.
Is there any more professional approach to solve this issue? I believe this must be solved somehow in many apps.
What you want is called TaskStackBuilder.
Here's how you should construct the intent, that would navigate to SpecificPhotoActivity:
Intent action = new Intent(context, SpecificPhotoActivity.class);
PendingIntent pendingIntent = TaskStackBuilder.create(context)
.addNextIntentWithParentStack(action)
.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
In order to correctly specify stack of activities, you should provide android:parentActivityName inside manifest file:
<application ...>
<activity android:name=".SpecificPhotoActivity"
android:parentActivityName=".PhotosActivity"/>
</application>
With this parameter you have specified, that the parent of SpecificPhotoActivity is PhotoActivity, thus TaskStackBuilder would understand where to navigate as soon as back button is clicked inside SpecificPhotoActivity.
Construction of the notification should be as follows:
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle(...)
.setContentText(...)
.setSmallIcon(...)
.setContentIntent(pendingIntent)
.build();
manager.notify(NOTIFICATION_ID, notification);
Now notification click would open SpecificPhotoActivity. A click on back button would navigate to PhotosActivity.
What's left is authorization handling. I suppose you are able to apprehend whether user is authorized or no during the construction of the notification. Hence, following approach should work:
PendingIntent pendingIntent = null;
if (authorized) {
Intent action = new Intent(context, SpecificPhotoActivity.class);
pendingIntent = TaskStackBuilder.create(context)
.addNextIntentWithParentStack(action)
.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
} else {
Intent action = new Intent(context, IntroActivity.class);
action.putExtra("photos_flow", true);
pendingIntent = PendingIntent.getActivity(context, 0, action, 0);
}
Now, inside IntroActivity after successful authorization:
void onAuthorized() {
if(getIntent().getBooleanExtra("photos_flow", false)) {
// most possibly you should pass some id into SpecificPhotoActivity's intent
Intent[] intents = new Intent[]{new Intent(this, PhotosActivity.class), new Intent(this, SpecificPhotoActivity.class)};
startActivities(intents);
finish();
}
}

How to make a button in a notification 'do something'

I am trying to make a simple stopwatch app that will display the time in a notification and give you a couple buttons that will allow you to start and stop the stopwatch.
How do I add a button to a notification? And how do I 'point' that button to a certain function?
Heres a picture of what I was thinking:
actionIntent = new Intent(this, MainActivity.class);
actionPendingIntent = PendingIntent.getService(this, 0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT);
timerNotification.addAction(android.R.drawable.ic_media_pause, "Start", actionPendingIntent);
This is what I currently have. Where in the intent would I put the function I want to execute?
Add Action to the notification and assign a pendingintent
If you want to custom your notification layout,you can use setContent() function with a RemoteViews of your custom layout.
Remote View mRemoteView = new RemoteViews(getPackageName(), R.layout.notification_general);
Notification.Builder mBuilder = new Notification.Builder(context);
mBuilder.setSmallIcon(R.mipmap.ic_battery)
.setContent(mRemoteView)
.setContentIntent(notificationPendingIntent);
mNotificationManager.notify(1, mBuilder.build());
To handle an notification button onClick event, you need to use separate PendingIntents(made from Intents with differecnt actions) for every button. Later in onReceive() you just check action of incoming Intent & execute different code depending on that. Remember to assign your Listener on manifest.
Intent generalIntent = new Intent(context, GeneralReceiver.class);
generalIntent.putExtra(REQUEST_CODE, ACTION_GENERAL);
PendingIntent generalPendingIntent =
PendingIntent.getBroadcast(context, 1, generalIntent, 0);
mRemoteView.setOnClickPendingIntent(R.id.btnNotificationGeneral, generalPendingIntent);
public static class GeneralReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Your code here
}
}

Android widget intents

I have a widget class and a service class updating the widget.
I have added in the widget class in onUpdate() the following code:
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.countdownwidget);
Intent Intent1 = new Intent(Intent.ACTION_MAIN);
Intent1.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent pendingIntent1 = PendingIntent.getActivity(context, 0, Intent1, 0);
views.setOnClickPendingIntent(R.id.button1, pendingIntent);
Intent Intent2 = new Intent(Intent.ACTION_MAIN);
Intent2.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent pendingIntent2 = PendingIntent.getActivity(context, 0, Intent2, 0);
views.setOnClickPendingIntent(R.id.button2, pendingIntent2);
And I have also added the following code in the widget service in the onStart()
Intent Intent1 = new Intent(Intent.ACTION_MAIN);
Intent1.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent pendingIntent1 = PendingIntent.getActivity(getApplicationContext(), 0, Intent1, 0);
remoteView.setOnClickPendingIntent(R.id.button1, pendingIntent1);
Intent Intent2 = new Intent(Intent.ACTION_MAIN);
Intent2.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent pendingIntent2 = PendingIntent.getActivity(getApplicationContext(), 0, Intent2, 0);
remoteView.setOnClickPendingIntent(R.id.button2, pendingIntent1);
The problem I am having is that once the implicit intent registers the app to launch on button1, the button2 is identical to button1. How can i make the 2 intents behave differently? i.e register and launch different apps.Its working with one button, but the other button launches the same thing of the first button.I have have been looking to get this to work for the last week, reading things all over but with no result.
I would appreciate your help.
Thanks.
The problem I am having is that once the implicit intent registers the app to launch on button1, the button2
is identical to button1.
Well, of course. All four of your Intents are identical: ACTION_MAIN, CATEGORY_LAUNCHER, with nothing else specified. I am surprised this Intent even works.
So, the first step to having the buttons do different things is to actually have different Intents.
Also, please do not use getApplicationContext(). Just use this, as a Service is a Context.

Categories