Send data from Widget Configuration to viewsFactory Android - android

Upon adding a new widget a configuration activity popups which inflates a listview of names from database and when i select the name from the config activity it pass the position to Appwidget provider
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
final CharSequence recipeId = IngredientConfiguration.loadTitlePref(context, appWidgetId);
String recipeIdInt = recipeId.toString();
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.ingredient_widget);
Intent intent = new Intent(context, ListViewService.class);
remoteViews.setRemoteAdapter(R.id.widget_listview, intent);
remoteViews.setEmptyView(R.id.widget_listview, R.id.empty_view);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
i created the remoteviewservice factory which inflates listview from database with cursor with position 0.
i want to get the info from config activity and use that value in remoteviewfactory and inflate the listview with unique value

Just add your parameters to adapter intent. Check out a simple example.
Intent intent = new Intent(context, ExampleRemoteService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
intent.putExtra("group", group);
intent.putExtra("week", week);
intent.putExtra("day", day);
remoteViews.setRemoteAdapter(R.id.example, intent);
In ExampleRemoteService in method onGetViewFactory you can get this intent and transfer to ExampleViewsFactory.
#Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return (new ExampleViewsFactory(this.getApplicationContext(),
intent));
}
In ExampleViewsFactory take all intent's data and in OnCreate just load your list depends on this parameters.
private String group;
private int widgetId;
private int week;
private int day;
private List<ExampleModel> data = new ArrayList<>();
public ExampleViewsFactory(Context context, Intent adapter) {
this.group = adapter.getStringExtra("group");
this.day = adapter.getIntExtra("day", 0);
this.week = adapter.getIntExtra("week", 0);
this.widgetId = adapter.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
}
#Override
public void onCreate() {
this.data = exampleRepository.getDataByWeekAndDay(group, week, day);
}
Now you need only to make a remoteviews for all items.

Related

Same widgets with different ListView data

I have a simple AppWidget that has ListView.
The widget have simple config Activity, where you select which set of data you want to display. That info (int id) is stored into SharedPreferences and later get from SP in RemoteViewsFactory.
All is working perfectly, until I add another Widget to the screen. The new one doesn't load different data if selected, but rather takes the one from previous Widget.
With little debugging I think that my onUpdate method is't being called, but I cannot find the problem here.
WidgetConfig.java
public class IngredientsWidgetConfigureActivity extends Activity implements RecipesAdapter.RecipesAdapterOnClickHandler {
int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
RecipesAdapter mAdapter;
public IngredientsWidgetConfigureActivity(){
super();
}
//save recipeId into SharedPrefs
static void saveSelectedRecipe (Context context, int appWidgetId, int selectedRecipe){
SharedPreferences.Editor prefs = context.getSharedPreferences(AppConstants.PREFS_NAME, 0).edit();
prefs.putInt(AppConstants.PREF_PREFIX_KEY + appWidgetId, selectedRecipe);
prefs.apply();
}
#Override
protected void onCreate(#Nullable Bundle icicle) {
super.onCreate(icicle);
setResult(RESULT_CANCELED);
setContentView(R.layout.ingredients_widget_configure);
//setup RecyclerView
...
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null){
mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
}
if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID){
finish();
return;
}
}
#Override
public void onClick(Recipe recipe) {
final Context context = IngredientsWidgetConfigureActivity.this;
// When the button is clicked, store the recipe Id
int selectedRecipe = recipe.id;
saveSelectedRecipe(context, mAppWidgetId, selectedRecipe);
// It is the responsibility of the configuration activity to update the app widget
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
IngredientsWidget.updateAppWidget(context, appWidgetManager, mAppWidgetId);
// Make sure we pass back the original appWidgetId
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);
finish();
}
WidgetProvider
....
static void updateAppWidget(final Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.ingredients_widget_layout);
Intent intent = new Intent(context, WidgetRemoteViewsService.class);
intent.putExtra(AppConstants.APP_WIDGET_ID_KEY, appWidgetId);
views.setRemoteAdapter(R.id.widget_list_view, intent);
//TODO: recipes are not changing in different widgets
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views);
}
#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);
}
}
And finally my
RemoteViewsFactory.java
public WidgetRemoteViewsFactory (Context context, Intent intent){
mContext = context;
appWidgetId = intent.getIntExtra(AppConstants.APP_WIDGET_ID_KEY, 1);
}
#Override
public void onCreate() {
}
#Override
public void onDataSetChanged() {
final long identityToken = Binder.clearCallingIdentity();
//get id from SharedPref
RecipeDatabase mDb = RecipeDatabase.getInstance(mContext);
SharedPreferences prefs = mContext.getSharedPreferences(AppConstants.PREFS_NAME, 0);
recipeId = prefs.getInt(AppConstants.PREF_PREFIX_KEY + appWidgetId, 9999);
recipe = mDb.recipeDAO().loadRecipe(recipeId);
Binder.restoreCallingIdentity(identityToken);
}
#Override
public void onDestroy() {
}
#Override
public int getCount() {
if (recipe == null) {
return 0;
} else {
return recipe.ingredients.size();
}
}
#Override
public RemoteViews getViewAt(int position) {
if (position > recipe.ingredients.size()){
return null;
}
RemoteViews remoteViews = new RemoteViews(mContext.getPackageName(), R.layout.widget_list_item);
remoteViews.setTextViewText(R.id.widget_text, recipe.ingredients.get(position).getIngredient());
return remoteViews;
}
#Override
public RemoteViews getLoadingView() {
return null;
}
#Override
public int getViewTypeCount() {
return 1;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public boolean hasStableIds() {
return true;
}
}
Solved...
I had to put new data into the Intent in updateAppWidget so the Factory loads new instance instead of reusing new one.
So I am sending new random value data with every widget, so it updates properly.
updateAppWidget snippet:
//send intent and data to Adapter
Intent intent = new Intent(context, WidgetRemoteViewsService.class);
intent.putExtra(AppConstants.APP_WIDGET_ID_KEY, appWidgetId);
//set random data to initialize new Factory
Random rnd = new Random();
intent.setData(Uri.fromParts("content", String.valueOf(rnd.nextInt()), null));
views.setRemoteAdapter(R.id.widget_list_view, intent);
Thanks to #TheFedex87

AppWidgets transform into Google Calendar and Clock widgets after reboot

I have no idea why this is happening. I'm making widgets which show the best currency rate for the currencies that the user chooses. I've noticed after a reboot, they sometimes turn into a clock and a calendar widget. Here's my code. I assume it could be something with my Intents or OnReceive() but I'm not sure what.
public class LightRowWidget extends RowWidget {
List<CurrencyObject> currencyObjects = new ArrayList<>();
public LightRowWidget() {
super(R.layout.widget_row_layout, R.color.white, Constants.FULL_OPACITY, R.color.black);
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
if (appWidgetIds != null && appWidgetIds.length > 0) {
for (int appWidgetId : appWidgetIds) {
// Create currencyObjects. They're used to assign the correct value
// to the correct texView
CurrencyObject currObj1 = new CurrencyObject(
R.id.currency1, R.id.currency1_buy, R.id.currency1_sell);
currencyObjects.add(currObj1);
CurrencyObject currObj2 = new CurrencyObject(R.id.currency2, R.id.currency2_buy, R.id.currency2_sell);
currencyObjects.add(currObj2);
// Register an onClickListener to Update the current widget on a click
Intent clickIntent = new Intent(context, LightRowWidget.class);
clickIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
onUpdate(context, appWidgetManager, appWidgetId, currencyObjects, clickIntent);
}
//start an intent that will schedule the alarm for the next update
Intent startIntent = new Intent(context, LightRowWidget.class);
scheduleNextUpdate(context, startIntent, appWidgetIds);
}
and Here is my RowWidget class with the relevant code.
public abstract class RowWidget extends AppWidgetProvider implements WidgetInterface{
public RowWidget(int layout, int background_color, int background_opacity, int text_color){
super();
this.layout = layout;
this.background_color=background_color;
this.background_opacity=background_opacity;
this.text_color=text_color;
}
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int appWidgetId, List<CurrencyObject> currencyObjects, Intent clickIntent) {
theAppWidgetManager = appWidgetManager;
//Get the current name of class
String currentClass = this.getClass().getName();
switch(currentClass){
case("foobar"):
configure_class=Constants.FOUR_ROW_CONFIGURE;
break;
case("foo"):
configure_class=Constants.ROW_APP_WIDGET_LIGHT_CONFIGURE;
break;
case("bar"):
configure_class=Constants.ROW_APP_WIDGET_DARK_CONFIGURE;
break;
case("barfoo"):
configure_class=Constants.TWO_ROW_CONFIGURE;
break;
}
// There may be multiple widgets active, so update all of them
// Get the preferred Currencies
Set<String> preferredCurrencies = AppWidgetConfigure.loadCurrencyPref(context,appWidgetId, configure_class);
// Inflate the layout
RemoteViews view = new RemoteViews(context.getPackageName(), layout);
// if the preferred Currencies have been declared already
if(preferredCurrencies!= null){
// Set the currencies for each object
for(String currency: preferredCurrencies){
if(currencyCount<currencyObjects.size()){
currencyObjects.get(currencyCount).setCurrencyType(currency);
currencyCount+=1;
}
}
}
else{
for(CurrencyObject curObj:currencyObjects){
curObj.setCurrencyType("RUB");
}
}
// Open up the Currency fragment on the click of the widget
Intent configIntent = new Intent(context, MainActivity.class);
configIntent.putExtra("LaunchCurrency", true);
configIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent configPendingIntent = PendingIntent.getActivity(context, 0, configIntent, 0);
view.setOnClickPendingIntent(R.id.row_widget_layout, configPendingIntent);
// Update the widget whenever refresh button clicked
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
view.setOnClickPendingIntent(R.id.refresh, pendingIntent);
makeRequest(context, theDate, view, currencyObjects, appWidgetId);
currencyCount = 0;
}
//Handle receiving the intent
#Override
public void onReceive(Context context, Intent intent){
if (intent.getAction().equals(ACTION_APPWIDGET_UPDATE)) {
AppWidgetManager manager = AppWidgetManager.getInstance(context);
// Get id's
int[] allWidgetIds = intent
.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
onUpdate(context, manager, allWidgetIds);
}
else{
super.onReceive(context, intent);
}
}
EDIT: Widgets transform to a lot of different widgets that are already on my screen.

notifyappwidgetviewdatachanged not working on a listview on my widget

I tried lots of solutions but after weeks i have not been able to solve this issue: why "notifyappwidgetviewdatachanged" doesn't work? how can i update a listview placed on my widget? Where am i wrong?
Here are my classes.
Widget Provider:
public class Widget_Provider extends AppWidgetProvider
{
public static final String ACTION_MOSTRAORARI = "fACTION_TOAST";
public static final String EXTRA_STRING = "EXTRA_STRING";
#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)
{
RemoteViews views = updateWidgetListView(context, appWidgetId);
final Intent onItemClick = new Intent(context, Widget_Provider.class);
onItemClick.setAction(ACTION_MOSTRAORARI);
onItemClick.setData(Uri.parse(onItemClick.toUri(Intent.URI_INTENT_SCHEME)));
final PendingIntent onClickPendingIntent = PendingIntent.getBroadcast(context, 0, onItemClick, PendingIntent.FLAG_UPDATE_CURRENT);
views.setPendingIntentTemplate(R.id.myStopList, onClickPendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
public RemoteViews updateWidgetListView(Context context, int appWidgetId)
{
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
Intent svcIntent = new Intent(context, Widget_Service.class);
svcIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
svcIntent.setData(Uri.parse(svcIntent.toUri(Intent.URI_INTENT_SCHEME)));
remoteViews.setRemoteAdapter(R.id.myStopList, svcIntent);
return remoteViews;
}
#Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(ACTION_MOSTRAORARI)) {
if (MainUtils.isNewtworkAvailable(context))
{
String item = intent.getExtras().getString(EXTRA_STRING);
Intent intentOrari = new Intent(context, Diag_MostraOrari.class);
intentOrari.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intentOrari);
}
}
super.onReceive(context, intent);
}
#Override
public void onDeleted(Context context, int[] appWidgetIds) {}
#Override
public void onEnabled(Context context) {}
#Override
public void onDisabled(Context context) {}
}
Widget Service:
public class Widget_Service extends RemoteViewsService
{
#Override
public RemoteViewsFactory onGetViewFactory(Intent intent)
{
Map<String, ArrayList<String>> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
/* ---
* Here i fetch data from a local db and store it on "map"
*/ ---
return (new Widget_ListProvider(this.getApplicationContext(), intent, map));
}
}
ListProvider:
public class Widget_ListProvider implements RemoteViewsFactory
{
private Map<String, ArrayList<String>> map = new HashMap<>();
private ArrayList<ListItem_Widget> listItemList = new ArrayList<>();
private Context context = null;
private int appWidgetId;
public Widget_ListProvider(Context context, Intent intent, Map<String, ArrayList<String>> map)
{
this.map = map;
this.context = context;
appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
populateListItem();
}
//This function populate the arraylist "listItemList" by the data stored on "map"
private void populateListItem() { [...] }
#Override
public int getCount() {
return listItemList.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public RemoteViews getViewAt(int position)
{
final RemoteViews remoteView = new RemoteViews(context.getPackageName(), R.layout.listitem_widget);
ListItem_Widget listItem = listItemList.get(position);
remoteView.setTextViewText(R.id.heading, listItem.heading);
remoteView.setTextViewText(R.id.content, listItem.content);
final Intent fillInIntent = new Intent();
fillInIntent.setAction(Widget.ACTION_MOSTRAORARI);
final Bundle bundle = new Bundle();
bundle.putString(Widget.EXTRA_STRING, listItem.heading);
fillInIntent.putExtras(bundle);
remoteView.setOnClickFillInIntent(R.id.listrow, fillInIntent);
return remoteView;
}
#Override
public RemoteViews getLoadingView() {
return null;
}
#Override
public int getViewTypeCount() {
return 1;
}
#Override
public boolean hasStableIds() {
return true;
}
#Override
public void onCreate() {}
#Override
public void onDataSetChanged() {}
#Override
public void onDestroy() {}
}
The xml of my listview custom item contains just two textviews: "heading" and "content".
Where am i wrong? why when i call "notifyappwidgetviewdatachanged" from another activity nothing happens?
[EDIT]
That's the activity where i need to update my widget.
public class Diag_Line extends AppCompatActivity
{
//[...]
#Override
protected void onCreate(Bundle savedInstanceState)
{
//[...]
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getApplicationContext());
ComponentName thisAppWidget = new ComponentName(getApplicationContext().getPackageName(), Widget.class.getName());
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.myStopList);
//"myStopList" is the id of my listview inside the widget xml.
//[...]
}
}
Well, the problem is a quite obvious: In your RemoteViewsFactory you have an empty method onDataSetChanged(). But when you're triggering notifyAppWidgetViewDataChanged(), you're getting callback in onDataSetChanged(). For better understanding check this pic.
If Diag_Line is a Configuration Activity just make something like this:
appWidgetManager.updateAppWidget(appWidgetIds, views); // views is a RemoteViews that you need to build
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.myStopList);
Also check official documentation here
UPDATE
Some hints for you. If you're working with widget, make all fetching data and fillings RemoteViews on background (IntentService is a nice approach). So just make IntentService and make logic for widget here. Don't forget to make him foreground (only for Android O), if you're triggering your updates by broadcasts. Also you can check library that makes all for you.
In order for notifyAppWidgetViewDataChanged() to work properly
we need to retreive the data in onDataSetChanged() method of RemoteViewSourceFactory
like this:
override fun onDataSetChanged() {
listOfArticles = newsDatabaseRepo.getSynchronouslySavedNews() as ArrayList<Articles>
}
as suggested in here
And have a method to refresh the widget if a change occured:
private fun refreshWidget() {
val appWidgetManager =
AppWidgetManager.getInstance(applicationContext)
val thisAppWidget = ComponentName(
applicationContext.packageName,
MyAppWidgetProvider::class.java.name
)
val appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget)
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.stack_view)
}
After calling the above method and once I come out of my App I am able to notice the changes in My Widget
So in order to check if onDataSetChanged is called after notifyAppWidgetViewDataChanged()
I kept a debug point and onDataSetChanged() was called and the list was updated as suggested in here here
Had a similar problem updating my widget, it was calling onDataSetChanged but not refreshing the layout. So in my case I had to set updateAppWidget to null before updating with remoteviews like this:
appWidgetManager.updateAppWidget(appWidgetId, null);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
Looks like there is some sort of caching happening here.

How to automatically update widget in home screen

I have completed one task application in android.And now i create one widget for this application.In my widget i have display list of task for today,which is working correctly.My problem is when i go to my application and add some task in today and then back to the home screen the widget having only old data instead of new data and no modification...please any one help me....
My RemoteFactory class:
public class TaskItemStatus implements RemoteViewsService.RemoteViewsFactory {
Context context;
int appWidgetId;
String statusRemainingTask="false";
String[] items;
private final String TAG = "CalendarViewSample:"
+ this.getClass().getName();
public TaskItemStatus(Context context, Intent intent) {
this.context = context;
appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
getData();
}
#SuppressLint("SimpleDateFormat")
private void getData() {
List<String> listTask=new ArrayList<String>();
Taskdatabase objTaskDb = new Taskdatabase(this.context);
objTaskDb.Open();
Calendar calendarToday = Calendar.getInstance();
SimpleDateFormat simpledateFormat = new SimpleDateFormat("dd-MM-yyyy");
String dateToday = simpledateFormat.format(calendarToday.getTime());
listTask.addAll(objTaskDb.fetchTodayRemainTask(dateToday, statusRemainingTask));
Log.i(TAG,"ListTask:"+listTask.toString());
items=new String[listTask.size()];
items=listTask.toArray(items);
}
#Override
public int getCount() {
return (items.length);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public RemoteViews getLoadingView() {
return null;
}
#Override
public RemoteViews getViewAt(int position) {
RemoteViews row = new RemoteViews(context.getPackageName(),
R.layout.widgetrow);
row.setTextViewText(android.R.id.text1, items[position]);
Intent i = new Intent();
//Bundle extras = new Bundle();
//extras.putString(WidgetTaskSchedular.EXTRA_WORD, items[position]);
//i.putExtras(extras);
row.setOnClickFillInIntent(android.R.id.text1, i);
return (row);
}
#Override
public int getViewTypeCount() {
return 1;
}
#Override
public boolean hasStableIds() {
return (true);
}
#Override
public void onCreate() {
}
#Override
public void onDataSetChanged() {
}
#Override
public void onDestroy() {
}
}
WidgetProvider:
public class WidgetTaskSchedular extends AppWidgetProvider {
static int ID;
static final int[] sameid=new int[1];
public static String EXTRA_WORD=
"com.capsone.testing.calendar.WORD";
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if(intent.getAction().equals("update_widget"))
{
Log.i(TAG,"AppWidgetIds:"+ID);
for(int i=0;i<1;i++)
{
sameid[i]=ID;
Log.i(TAG,"SameId:"+sameid[i]);
onUpdate(context, AppWidgetManager.getInstance(context),sameid);
}
}
}
#SuppressWarnings("deprecation")
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
ID=appWidgetIds[i];
for (int i=0; i<appWidgetIds.length; i++) {
Log.i("Widget","WidgetId:"+appWidgetIds.length);
Intent intentWidgetService=new Intent(context, WidgetService.class);
intentWidgetService.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
intentWidgetService.setData(Uri.parse(intentWidgetService.toUri(Intent.URI_INTENT_SCHEME)));
RemoteViews remoteView=new RemoteViews(context.getPackageName(),
R.layout.widgetlayout);
remoteView.setRemoteAdapter(appWidgetIds[i], R.id.listWidget,
intentWidgetService);
Intent clickIntent=new Intent(context, ActionBarActivity.class);
PendingIntent clickPendingIntent=PendingIntent
.getActivity(context, 0,
clickIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
remoteView.setPendingIntentTemplate(R.id.listWidget, clickPendingIntent);
ComponentName component=new ComponentName(context,WidgetTaskSchedular.class);
appWidgetManager.updateAppWidget(component, remoteView);
}
}
}
AppWidgetProvider class:
ComponentName component = new ComponentName(context, WidgetTaskSchedular.class);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds[i], R.id.listWidget);
appWidgetManager.updateAppWidget(component, remoteView);
RemoteView class:
#Override
public void onDataSetChanged() {
// Just copy and paste you getdata() coding here
}
One way to achieve this is when you save the new task in your application just send a broadcast with a custom intent to indicate the change in the underlying database.
Add a receiver to this broadcast in your WidgetTaskSchedular class and in on receive method call the onUpdate method to re-populate data in the widget. Somewhat like this:
public void onReceive(Context context, Intent intent) {
System.out.println("On receive function");
if (intent.getAction().equals("com.android.myapp.myBroadcast")) {
System.out.println("There is an update from app ");
//re populate data or in onUpdate
onUpdate(context, AppWidgetManager.getInstance(context), IDs);
}
super.onReceive(context, intent);
}
PS:Save Ids as a static field or something.I took in the IDs in a static array of integers which I populatedin the onUpdate method,you can also try replacing that part with the following code:
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.widget);
// Update - here like for example as below
remoteViews.setTextViewText(R.id.yourTextID, "My updated text");
// Trigger widget layout update
AppWidgetManager.getInstance(context).updateAppWidget(
new ComponentName(context, Widget.class), remoteViews);

Sending data to my (homescreen) widget

I am having some trouble sending data(strings) from my activity to my appWidgetProvide class.
I have a method called updateWidget. This gets called by the widget configure activity when the widget first gets placed in the home screen .This method is also called by the onReceive method when it receives data from one of my activities when the user enters data into that activity.
Here is my problem : the widget get placed in the home screen with all the data in the right place. But when my activity sends data the onReceive (using intents and extras) the data does not come through.I just get a empty string on the extras.getString .
I have used intents to send data between activities before , do I need to do something different when I send data to a widget provide class? Or am I just being stupid and missing something obvious ?
I have attached (what I think are the) relevant bits of code. Let me know if you need any clarification or any more of the code.
Thanks for taking the time to read this and for any help that you can give,
Cheers Rakshak
the onListItemClick in the widget configure class.
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Cursor note = mDbHelper.fetchNote(id);
startManagingCursor(note);
String title = note.getString(note.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE));
String text = note.getString(note.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY));
loadData(title);
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK,resultValue);
finish();
}
void loadData(String title) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
SingleNote.updateWidget(this, appWidgetManager, mAppWidgetId, title);
}
The intent that sends data to the onReceive (this is in one of my activity classes)
private void updateWidget() {
Intent i = new Intent(this, SingleNote.class);
i.setAction(SingleNote.UPDATE_ACTION);
Toast.makeText(getApplicationContext(),mTitleText.getText()+"from the activity",
Toast.LENGTH_SHORT).show();//This works just fine
i.putExtra("title", mTitleText.getText());
sendBroadcast(i);
}
My widget provide class
public class SingleNote extends AppWidgetProvider {
public static String UPDATE_ACTION = "ActionUpdateSinglenoteWidget";
private static NotesDbAdapter mDbHelper;
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
// Perform this loop procedure for each App Widget that belongs to this provider
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
// Tell the AppWidgetManager to perform an update on the current app widget
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.singlenote_widget);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Bundle extras = intent.getExtras();
String title1 = extras.getString("title");//this value does not come through
Toast.makeText(context, title1,Toast.LENGTH_LONG).show();//this gives an empty space
if (action != null && action.equals(UPDATE_ACTION)) {
final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
ComponentName name = new ComponentName(context, SingleNote.class);
int[] appWidgetId = AppWidgetManager.getInstance(context).getAppWidgetIds(name);
final int N = appWidgetId.length;
if (N < 1)
{
return ;
}
else {
int id = appWidgetId[N-1];
updateWidget(context, appWidgetManager, id ,title1);
}
}
else {
super.onReceive(context, intent);
}
}
static void updateWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId, String title){
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.singlenote_widget);
views.setTextViewText(R.id.single_note_title, title);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
I suggest to try replacing i.putExtra("title", mTitleText.getText()); in updateWidget() with i.putExtra("title", mTitleText.getText().toString());
String title1 = extras.getString("title");
expects string, and mTitleText.getText() returns Editable - this is likely a mismatch

Categories

Resources