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);
}
Related
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
I want to make a widget app that is able to dial a number and user can set the number when he first drag and drop widget to home screen using widget configuration.But when the phone restarts widget uses default number again. I decide to save the entered phonenumber to Shared Preferences to save and load user's phone number but eclipse says that using getSharedPreferences is not allowed in onUpdate.Is there another way to perform it?
What should I do?
my code:
public class Main extends AppWidgetProvider {
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// TODO Auto-generated method stub
super.onUpdate(context, appWidgetManager, appWidgetIds);
for(int i=0 ; i<appWidgetIds.length ; i++)
{
SharedPreferences details = getSharedPreferences("OPERATOR", 0);
int appWidgetId = appWidgetIds[i];
String phNumber = "5554574";
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:"+(phNumber)));
PendingIntent pending = PendingIntent.getActivity(context, 0, intent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.main);
views.setOnClickPendingIntent(R.id.button1, pending);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
}
Use:
SharedPreferences details = context.getSharedPreferences("OPERATOR", 0);
SharedPreferences has to be acquired from the context. onUpdate(...) provides you the context.
Your changed code should look like this:
public class Main extends AppWidgetProvider {
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// TODO Auto-generated method stub
super.onUpdate(context, appWidgetManager, appWidgetIds);
for(int i=0 ; i<appWidgetIds.length ; i++)
{
SharedPreferences details = context.getSharedPreferences("OPERATOR", 0);
int appWidgetId = appWidgetIds[i];
String phNumber = "5554574";
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:"+(phNumber)));
PendingIntent pending = PendingIntent.getActivity(context, 0, intent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.main);
views.setOnClickPendingIntent(R.id.button1, pending);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
}
Please try it.
AppWidgetProvider is not a Context. But you can often create a static method to reach the context of an application, then do this
In Android Manifest file declare following
<application android:name="com.example.MyApplication">
</application>
then write the class
public class MyApplication extends Application{
private static Context context;
public void onCreate(){
super.onCreate();
MyApplication.context = getApplicationContext();
}
public static Context getAppContext() {
return MyApplication.context;
}
}
Then you can use
SharedPreferences details = MyApplication.getAppContext().getSharedPreferences("OPERATOR", 0);
I haven't worked with widgets yet so can't guarantee this solution but hope it work!
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
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
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.