Sending data to my (homescreen) widget - android

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

Related

Send data from Widget Configuration to viewsFactory 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.

How to set Widget button visibility?

Hi first of all i'm sorry for my bad english. How to set RemoteViews .setViewVisibility? I want to hide widget button when i click on it.
Here is my code. Thanks for help.
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
final int N = appWidgetIds.length;
for (int i = 0; i < N; i++){
int appId = appWidgetIds[i];
widget = new RemoteViews(context.getPackageName(), R.layout.widget_wyglad);
Intent Tv = new Intent(context, client_widget.class);
Tv.setAction(AKCJA);
Tv.putExtra("test", AKCJA);
PendingIntent ptv = PendingIntent.getBroadcast(context, 0, Tv, 0);
widget.setOnClickPendingIntent(R.id.bt_wid_tv, ptv);
appWidgetManager.updateAppWidget(appId, widget);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
if (extras != null){
widget.setViewVisibility(R.id.bt_wid_tv, View.GONE);
}
else {Log.d("ERR", "EXTRAS ELSE");}
super.onReceive(context, intent);
}
}
You have done everything right about making the view hidden. just include this in your code-
In your onReceive method-
if (intent.getAction().equals(AKCJA)) {
widget.setViewVisibility(R.id.bt_wid_tv, View.GONE);
}
Have you tried using INVISIBLE instead of GONE? Gone will remove the view as if it were never there. And invisible will hold the view's place in the layout, but make it invisible.
rv.setViewVisibility(R.id.bt_wid_tv, View. INVISIBLE);
Yeah it finally work,
There's what i change:
int appId = appWidgetIds[i];
change to:
appId = appWidgetIds[i];
next i add static int appId:
public class client_widget extends AppWidgetProvider {
static int appId;
finally add this new AppWidgetManager and update line:
public void onReceive(Context context, Intent intent) {
AppWidgetManager newAppWidgetManager = AppWidgetManager.getInstance(context);
if (intent.getAction().equals(AKCJA)) {
AppWidgetManager nowy = AppWidgetManager.getInstance(context);
widget.setViewVisibility(R.id.bt_wid_tv, View.GONE);
newAppWidgetManager.updateAppWidget(appId, widget);
Thanks #Naddy

How to save and retrieve an android widget id

I have setup a widget like this
ToggleWidget.java
public class ToggleWidget extends AppWidgetProvider {
static RemoteViews remoteViews;
boolean status = false;
static int appWidgetId;
#Override
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++) {
appWidgetId = appWidgetIds[i];
remoteViews = new RemoteViews(context.getPackageName(), R.layout.toggle_widget);
Intent intent = new Intent(context.getApplicationContext(), WakeService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
PendingIntent pendingIntent = PendingIntent.getService(
context.getApplicationContext(), 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.bulb_widget, pendingIntent);
if (WakeService.isAwake) {
remoteViews.setImageViewResource(R.id.bulb_widget, R.drawable.bulb_on);
}
else {
remoteViews.setImageViewResource(R.id.bulb_widget, R.drawable.bulb_off);
}
// Tell the AppWidgetManager to perform an update on the current app widget
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
}
#Override
public void onDeleted(Context context, int[] appWidgetIds) {
// TODO Auto-generated method stub
super.onDeleted(context, appWidgetIds);
}
}
How can i save the ID of every widget i create and delete those that i've deleted with sharedPreferences?
Also from a service i'd like to update the widget like this
private void updateWidget(){
Intent intent = new Intent(this,ToggleWidget.class);
intent.setAction("android.appwidget.action.APPWIDGET_UPDATE");
int[] ids = {ToggleWidget.appWidgetId};
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,ids);
sendBroadcast(intent);
}
How can i retrieve the saved IDs from the service to make the update?
In your Reciever class just override onCreate() method and under that method,
int[] ids = getIntent().getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
Then you will get int array, pls check it, it will work...:)
Take a look at android's Data Storage options. Here is how you could use SharedPreferences...
public class MyService extends Service{
//Class used to store data
private SharedPreferences preferences;
private int[] ids;
private int numIds;
public void retreiveIds(){
preferences = PreferenceManager.getDefaultSharedPreferences(this);
numIds = preferences.getInt("num",0);
ids = new int[numIds];
for(int i=0;i<numIds;i++){
ids[i] = preferences.getInt("ID"+i,0);
}
}
public void saveIds(){
SharedPreferences.Editor ed = preferences.edit();
numIds = ids.length;
//iterate through array and save each id
for(int i=0;i<numIds;i++){
ed.putInt("ID"+i,ids[i]);
}
ed.putInt("num",numIds);
ed.commit();
}
}
There is another way to do it. Code in kotlin:
val thisWidget = ComponentName(context, this.javaClass)
val allWidgetIds: IntArray = appWidgetManager.getAppWidgetIds(thisWidget)
Now you can use these allWidgetIds to update widgets.

Getting a String to AppWidget via GetExtras (or) Shared prefrences

I have an app widged which basically has a textview. I also have
an activity which displays a textview from string created within. Now
i have a button in Activity 1 which onClick will send data (string to
appWidget class) I tried putExtra and getExtra methods and also Shared
preferences method, im little confused to use which first!
Here are some inputs from me for more clarity.
Activity1:
final String addwidget =
((TextView)findViewById(R.id.verse)).getText().toString();
Intent widgetIntent = new Intent(MyScheduledActivity.this,
MainWidget.class);
widgetIntent.putExtra("widgetVerse", addwidget);
AppWidget:
public class MainWidget extends AppWidgetProvider {
RemoteViews views;
public static String verseFromFav;
private Bundle getVerseData;
#Override
public void onReceive(Context context, Intent intent) {
getVerseData = intent.getExtras();
verseFromFav = getVerseData.getString("widgetVerse");
super.onReceive(context, intent);
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
for (int i=0; i<N; i++) {
views = new RemoteViews(context.getPackageName(),R.layout.widget_layout);
if(verseFromFav == null){
verseFromFav = "no verse";
}
views.setTextViewText(R.id.widgetVerse, verseFromFav);
ComponentName thisWidget = new ComponentName( context, MainWidget.class );
AppWidgetManager.getInstance( context ).updateAppWidget( thisWidget, views );
appWidgetManager.updateAppWidget(appWidgetIds, views);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
}
(THE APP WIDGET SHOWS "no verse" WHICH READS NULL)
Can any one help me with a basic idea on how to display the string
here. please. thanks in advance.
onUpdate will ALWAYS be called (sometimes multiple times) so utilize that to fire a utility or controller class and do all the work in that class.
Thus, in your app widget the only thing you might have, all I am demonstrating is updating a string in a TextView, is stuff in the onUpdate() method.
#Override
public void onUpdate( final Context context, final AppWidgetManager appWidgetManager, final int[] appWidgetIds ) {
// Need this here to set the initial state of the app widget
final AppWidgetController _actrlr = new AppWidgetController( context );
_actrlr.updateAppWidgetUI( this );
super.onUpdate( context, appWidgetManager, appWidgetIds );
}
Then in AppWidgetController class you might have something like this...
public final void updateAppWidgetUI( final Context context ) {
final AppWidgetManager _manager = AppWidgetManager.getInstance( context );
final ComponentName _componentName = new ComponentName( context, com.your.namespace.theprovidername.class );
final int[] appWidgetIds = _manager.getAppWidgetIds( _componentName );
for ( final int i : appWidgetIds ) {
final RemoteViews _rv = new RemoteViews( context.getPackageName(), R.layout.appwidget_xml_layout_file );
if( somethingIsTrue ) {
_rv.setTextViewText( R.id.textViewThatYouWantToUpdate, "The text that you wish to display if something is TRUE" );
} else {
_rv.setTextViewText( R.id.textViewThatYouWantToUpdate, "The text that you wish to display if something is FALSE" );
}
_manager.updateAppWidget( i, _rv );
}
}
RemoteView setTextViewText()
http://developer.android.com/reference/android/widget/RemoteViews.html#setTextViewText(int, java.lang.CharSequence)
I would advise you to use sharedpreference for this. It would do you better.
SharedPreferences settings =
getSharedPreferences("MyWigdetPreferences", MODE_WORLD_READABLE);
SharedPreferences.Editor prefEditor = Settings.edit();
prefEditor.putString("widgetVerse", addwidget);
prefEditor.commit();
Then in the mainWidget activity pull it out by..
SharedPreferences settings =
getSharedPreferences("MyWigdetPreferences", MODE_WORLD_READABLE);
String verse = settings.getString("widgetVerse");
That should do it.
EDIT:
Instead of
#Override
public void onReceive(Context context, Intent intent) {
getVerseData = intent.getExtras();
verseFromFav = getVerseData.getString("widgetVerse");
super.onReceive(context, intent);
}
Try
#Override
public void onReceive(Context context, Intent intent) {
getVerseData = getIntent.getExtras();
verseFromFav = getVerseData.getString("widgetVerse");
super.onReceive(context, intent);
}

Force Android widget to update

I respond to a button press on my appwidget in the onreceive method. When the button I pressed, I want to force the widget to call the onupdate method. How do I accomplish this?
Thanks in advance!
Widget can't actually respond to clicks because it's not a separate process running. But it can start service to process your command:
public class TestWidget extends AppWidgetProvider {
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];
// Create an Intent to launch UpdateService
Intent intent = new Intent(context, UpdateService.class);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
// Get the layout for the App Widget and attach an on-click listener to the button
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);
views.setOnClickPendingIntent(R.id.button, pendingIntent);
// Tell the AppWidgetManager to perform an update on the current App Widget
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
public static class UpdateService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//process your click here
return START_NOT_STICKY;
}
}
}
You should also register the new service in your manifest file:
<service android:name="com.xxx.yyy.TestWidget$UpdateService">
You can find another example of UpdateService implementation in Wiktionary sample in SDK
And here's another good approach Clickable widgets in android
This is kinda crude, but it works rather well for me, as I've found no directly-implemented way to force an update.
public class Foo extends AppWidgetManager {
public static Foo Widget = null;
public static Context context;
public static AppWidgetManager AWM;
public static int IDs[];
public void onUpdate(Context context, AppWidgetManager AWM, int IDs[]) {
if (null == context) context = Foo.context;
if (null == AWM) AWM = Foo.AWM;
if (null == IDs) IDs = Foo.IDs;
Foo.Widget = this;
Foo.context = context;
Foo.AWM = AWM;
Foo.IDs = IDs;
.......
}
}
Now, anywhere I want to force the widget to update, it's as simple as:
if (null != Foo.Widget) Foo.Widget.onUpdate(null, null, null);

Categories

Resources