Android: Run method in separate class from a home screen widget - java

I have a method in a plain class file (not an activity) that I run from my main activity, and I also want to run it from my home screen widget.
The button in the widget works perfectly as long as the app is open in the background. If I close the app from recent tasks the button stops working.
I think I need to start the app with the button click as well, but I don't want it to open the main activity, just run the method. How can I do this?
Here is my code for the widget:
public class PanicWidget extends AppWidgetProvider {
public static final String CLICK_PANIC = "PANIC";
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.panic_widget);
Intent intent = new Intent(context, PanicWidget.class);
intent.setAction(CLICK_PANIC);
PendingIntent actionPendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
remoteViews.setOnClickPendingIntent(R.id.panicbutton, actionPendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
}
#Override
public void onReceive(Context context, Intent intent){
super.onReceive(context, intent);
if (CLICK_PANIC.equals(intent.getAction())){
Methods.countdown();
}
}
}

Related

How Do I getText().toString() a TextView Using RemoteViews?

I'm developing a widget for the first time, and remoteviews is a bit confusing compared to building an app.
I understand this part...
RemoteViews views = new Remoteviews(context.getPackageName(), R.layout.my_widget_layout);
views.setTextViewText(R.id.myTV, "Hello World");
Now the next is a bit complex for me. I want the button that I have on the widget to pass the TextView text and display it on a toast.
Here's what I started...
Intent myIntent = new Intent(context, myReceiver.class);
PendingIntent myPendingIntent = PendingIntent.getBroadcast(context, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.myButton, myPendingIntent);
My Class (This is where I need help!)
public static class myReceiver extends BroadcastReceiver{
Override
public void onReceive(Context context, Intent intent){
Toast.makeText(context, (HELP! I need to getText().toString() from the R.id.myTV), Toast.LENGTH_SHORT).show();
}
}
Thanks! Much appreciated!
You can add the text you want to display to the intent via putStringExtra method and then extract the extra string like this:
#Override
public void onReceive(Context context, Intent intent) {
AppWidgetManager mgr = AppWidgetManager.getInstance(context);
if (intent.getAction().equals(check-your-desired-action-here)) {
String textThatYouWantToDisplay = intent.getStringExtra("name-of-the-desired-item");
Toast.makeText(context,textThatYouWantToDisplay , Toast.LENGTH_SHORT).show();
}
super.onReceive(context, intent);
}
for more info:
this sample widget app from google
Build an app widget android document
Intent getStringExtra method

How to call a method in the Mainactivity by clicking a widget using Android studio?

I am a beginer, so be kind. I have an app with four buttons. If I run the app and click a single button, data is sent to specific device (one of four) using Bluetooth. I also have a widget that needs to call a method for data sending for the first device, so simulating a click of the first button i.e. calling a method in the Mainactivity class with a parameter 1.
Thank you for your help.
So currently from a widget I can start the Mainactivity, opening an app, but I would like to run a specific method instead.
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
for (int i = 0; i < appWidgetIds.length; i++) {
int appWidgetId = appWidgetIds[i];
Intent intent = new Intent(context, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.io_t3widget);
views.setOnClickPendingIntent(R.id.appwidget_text, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}

onAppWidgetOptionsChanged() called on screen awake. How to prevent this?

I have a calendar widget and I'm updating it myself everyday at 12:01AM as well when the size is changed so I don't have a need for automatic update. I also set the updatePeriodMillis to 0. The problem I'm having is that the App Widget calls onAppWidgetOptionsChanged():
Every time the screen unlocks
Every time you're brought home
It wouldn't be an issue for me, but the problem is you can see for a split second the App Widget updating. Anyone know of any way I can prevent that from happening?
For reference here is part of my WidgetProvider class
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action != null) {
if (action.equals(ACTION_REFRESH) || action.equals(ACTION_NEXT) || action.equals(ACTION_PREVIOUS)) {
context.sendBroadcast(new Intent(action));
}
}
Bundle extra = intent.getExtras();
if (extra != null && extra.containsKey(KEY_APP_WIDGET_ID)) {
updateAppWidget(context, AppWidgetManager.getInstance(context), extra.getInt(KEY_APP_WIDGET_ID));
}
super.onReceive(context, intent);
}
#Override
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
int width = Util.dp2px(newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH));
Intent broadcastIntent = new Intent(ACTION_REFRESH);
broadcastIntent.putExtra(KEY_SIZE_CHANGE, width);
context.sendBroadcast(broadcastIntent);
updateAppWidget(context, appWidgetManager, appWidgetId);
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
}
private static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
Intent intent = new Intent(context, WidgetService.class);
views.setRemoteAdapter(R.id.widget_calendar_container, intent);
// Buttons on widget click handlers
views.setOnClickPendingIntent(R.id.widget_refresh, getPendingSelfIntent(context, ACTION_REFRESH, appWidgetId));
views.setOnClickPendingIntent(R.id.widget_next, getPendingSelfIntent(context, ACTION_NEXT, appWidgetId));
views.setOnClickPendingIntent(R.id.widget_previous, getPendingSelfIntent(context, ACTION_PREVIOUS, appWidgetId));
// Widget Container click handler
Intent homeIntent = new Intent(Intent.ACTION_MAIN);
homeIntent.addCategory(Intent.CATEGORY_LAUNCHER);
homeIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
homeIntent.setComponent(new ComponentName(context.getPackageName(), Home.class.getName()));
PendingIntent homePendingIntent = PendingIntent.getActivity(context, 0, homeIntent, 0);
views.setPendingIntentTemplate(R.id.widget_calendar_container, homePendingIntent);
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_calendar_container);
}
I prefer another answer, but this is what I got so far.
#Override
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
int width = Util.dp2px(newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH));
if (width != WidgetRemoteViewsFactory.width) {
Intent broadcastIntent = new Intent(ACTION_REFRESH);
broadcastIntent.putExtra(KEY_SIZE_CHANGE, width);
LocalBroadcastManager.getInstance(context).sendBroadcast(broadcastIntent);
updateAppWidget(context, appWidgetManager, appWidgetId);
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
}
}
I made the field I am interested in width static on WidgetRemoteViewsFactory and I am only broadcasting when that field changes. I can't seem to prevent onAppWidgetOptionsChanged() from being called because AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED is being broadcasted and received every time the screen is awaken.
Android Documentation says
Called in response to the AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED broadcast when this widget has been layed out at a new size. -
AppWidgetProvider#onAppWidgetOptionsChanged
But that action is being broadcasted every time the screen awakens.
If anyone has a better solution, please feel free to post it. There has to be a better solution or this is a bug on Android's side.

Android widget talk to service and service talk to widget

I have an Android app whose service is started when app starts and when app is killed, service is also destroyed.
I have a home screen widget starting alongside with app. It has 3 imageviews - "Play","Next","Previous".
On press of any of these imageview in widget, they need to talk to service and service talks to library etc.
When service has an answer, it responds to widget with status OK or NO. Based on the response, I need to update the imageviews.
When the app is killed, I need to gray out my widget fully. In this situation, when I click on the greyed out widget, I need to start the app. Could anyone help me please
how I could achieve this.
Here is my widget code -
public class MyWidgetProvider extends AppWidgetProvider {
private Intent serviceIntent;
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
RemoteViews remoteViews;
ComponentName componentName;
remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
componentName = new ComponentName(context, ControlScreenWidgetProvider.class);
remoteViews.setOnClickPendingIntent(R.id.PLAY,getPendingSelfIntent(context, "PLAY",componentName));
remoteViews.setOnClickPendingIntent(R.id.NEXT,getPendingSelfIntent(context, "NEXT",componentName));
remoteViews.setOnClickPendingIntent(R.id.PREVIOUS,getPendingSelfIntent(context, "PREVIOUS",componentName));
appWidgetManager.updateAppWidget(componentName, remoteViews);
}
#Override
public void onReceive(Context context, Intent intent)
{
super.onReceive(context, intent);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews remoteViews;
ComponentName componentName;
remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
componentName = new ComponentName(context, MyWidgetProvider.class);
if ("PLAY".equals(intent.getAction())) {
remoteViews.setOnClickPendingIntent(R.id.PLAY,getPendingSelfIntent(context, "PLAY",componentName));
// Dont know what to do here
}
else if ("NEXT".equals(intent.getAction())) {
remoteViews.setOnClickPendingIntent(R.id.lock_door,getPendingSelfIntent(context, "NEXT",componentName));
// Dont know what to do here
}
else if ("PREVIOUS".equals(intent.getAction())) {
remoteViews.setOnClickPendingIntent(R.id.lock_door,getPendingSelfIntent(context, "PREVIOUS",componentName));
// Dont know what to do here
}
appWidgetManager.updateAppWidget(componentName, remoteViews);
}
protected PendingIntent getPendingSelfIntent(Context context, String action, ComponentName componentName) {
Intent intent = new Intent(context, MyWidgetProvider.class);
intent.setAction(action);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, componentName);
return PendingIntent.getService(context, 0, intent, 0);
}
}

Onclick Event for Android Widget

I've read about 10 posts now about onclick events and Widgets and I understand they are implemented differently. However, despite the success other people are having I seem to be finding it impossible to get it to work. I'm using Android Studio 2.2 and have created a simple test app. I have a button called button. I want a toast to display when I press the button.
I've copied the code as suggested in the other posts. Can someone take a look and see if I am doing anything wrong?
public class NewAppWidget extends AppWidgetProvider {
private static final String MyOnClick = "myOnClickTag";
protected PendingIntent getPendingSelfIntent(Context context, String action) {
Intent intent = new Intent(context, getClass());
intent.setAction(action);
return PendingIntent.getBroadcast(context, 0, intent, 0);
}
void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
CharSequence widgetText = context.getString(R.string.appwidget_text);
// Construct the RemoteViews object
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);
views.setOnClickPendingIntent(R.id.button, getPendingSelfIntent(context, MyOnClick));
views.setTextViewText(R.id.appwidget_text, widgetText);
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views);
}
//RemoteViews.setOnClickPendingIntent(R.id.button, getPendingSelfIntent(context, MyOnClick));
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
#Override
public void onEnabled(Context context) {
// Enter relevant functionality for when the first widget is created
}
#Override
public void onDisabled(Context context) {
// Enter relevant functionality for when the last widget is disabled
}
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);//add this line
if (MyOnClick.equals(intent.getAction())){
//your onClick action is here
//display in short period of time
Toast.makeText(context, "msg msgasdasd", Toast.LENGTH_SHORT).show();
}
};
}
OK - really weird. Restarted the android emulator and it started working.
Mmmmm.
Cheers

Categories

Resources