Widget custom icon Android - android

I would like to make a custom image for a widget, i tried
views.setImageViewResource(R.id.red_button, R.drawable.button_default);
and
Bitmap icon = BitmapFactory.decodeResource(context.getResources(),
R.drawable.button_default);
views.setImageViewBitmap(R.id.red_button, icon);
but it says problem loading widget all the time, no matter what I try, am I missing something? can someone point me to the right documantion/what to do?
Edit:
full xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/holo_green_dark"
android:orientation="vertical"
android:padding="#dimen/widget_margin">
<ImageButton
android:id="#+id/red_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Button"
app:srcCompat="#drawable/button_default" />
</LinearLayout>
code:
public class NewAppWidget extends AppWidgetProvider {
static 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);
Intent intent = new Intent(context, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.red_button, pi);
views.setTextViewText(R.id.red_button, widgetText);
Bitmap icon = BitmapFactory.decodeResource(context.getResources(),
R.drawable.button_default);
views.setImageViewBitmap(R.id.red_button, icon);
//views.setImageViewResource(R.id.red_button, R.drawable.button_default);
// 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);
}
}
#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
}
}
Thanks!

The error message ("problem loading widget") is not caused by any problems with displaying the drawable, it is showing because of this line in your code:
views.setTextViewText(R.id.red_button, widgetText);
You can only use setTextViewText(int, CharSequence) with resource ids for Views extending from TextView (according to the docs, it's equivalent to TextView.setText(CharSequence) ).
The resource id R.id.red_button belongs to an ImageButton which extends from ImageView not from TextView, that's why you get the error message.
So if you want to show some text you need to add a Textview to your app widget's layout.

Related

Widget refresh from inside application

Good Day! I want to add text from inside application to widget, i have a main activity and it has list view and lots of text contents and it has a button to add the text to widget via shared preference, it's works fine when i close the widget and recreate it only, otherwise it's not automatically refresh.if anyone know; how to solve this please help me. here i attached the widget code below.
public class WidgetMaster extends AppWidgetProvider {
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
Intent intentHome = new Intent(context, MainActivity.class);
PendingIntent pendingIntentHome = PendingIntent.getActivity(context, 0, intentHome, 0);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_master);
views.setOnClickPendingIntent(R.id.wid_home, pendingIntentHome);
final SharedPreferences sharedPreferencestoWi = context.getSharedPreferences(String.valueOf(R.string.addTextToWidgetPref), MODE_PRIVATE);
String forWidget = sharedPreferencestoWi.getString("textToWidget", "");
String dum = "add from reading";
if(forWidget.equals("")){
views.setTextViewText(R.id.dum_appwidget_text, dum);
appWidgetManager.updateAppWidget(appWidgetId, views);
} else {
views.setTextViewText(R.id.appwidget_text, forWidget);
views.setViewVisibility(R.id.appwidget_text, 0);
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);
}
}
#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
}
}
How do you update the widget from mainActivity?
In the widget configuration file you can specify a fixed update interval. The smallest update interval is 1800000 milliseconds (30 minutes).
But its better to update widget programmatically, to do this You should send a broadCast to update widget and use a
method like alarmManager or Handler for a repeating task for example you can use the following broadCast to update widget form mainActivity:
Intent intent = new Intent(this, WidgetMaster.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
int[] ids = AppWidgetManager.getInstance(getApplication())
.getAppWidgetIds(new ComponentName(getApplication(),WidgetMaster.class));
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
sendBroadcast(intent);

Do not create widget

Hello this is simple question
i create widget and test this is my simple code :
#Override
public void onReceive(Context context, Intent intent) {
ComponentName thisAppWidget = new ComponentName(context, MyWidget.class);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int ids[] = appWidgetManager.getAppWidgetIds(thisAppWidget);
Log.d(" widget ids : " + Arrays.toString(ids) );
setResultCode(0);
}
But i have got red square on home screen .. ?
My widget provider configuration :
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="80dp"
android:minHeight="80dp"
android:previewImage="#drawable/example_appwidget_preview"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen|keyguard"
>
</appwidget-provider>
But i have got red square on home screen .. ?
This could be the preview image you have set in widget provider xml.
When the widget is added in home screen, the onUpdate() method will be called, where you can set the remote layout for the widget like this.
public class CustomAppWidgetProvider extends AppWidgetProvider{
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
for (int i = 0; i < N; i++) {
int appWidgetId = appWidgetIds[i];
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget_layout);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
}
You can also set a pending intent to an activity/service to be invoked when the whole widget or an child item in the widget is clicked
Intent intent = new Intent(context, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context,0,intent,0);
remoteViews.setOnClickPendingIntent(R.id.imageView1,pendingIntent);
So, here in the widget layout there is a textview , and when the user click on the textview the MainActivity will be launched.
You have to set an layout file to your appwidget-provider:
android:initialLayout="#layout/widget_view"
In this layout file you have to put Buttons, Images, TextViews etc. whatever you need.

better way to start a service from a home screen app widget

I have the following code in my sample app. I'm starting a service from an app widget when a button is clicked. The service's job is to play a short audio clip that depends on which button was clicked.
The app widget contains two buttons (PREV and NEXT). On click events are handled in onUpdate().
From different guides that I've found online I can start the service in two ways:
by creating a broadcast in onUpdate() method and handle it later in onReceive() method of the extended AppWidgetProvider class (as in the sample code for PREV button).
or by calling startService() via a PendingIntent in onUpdate() (as NEXT button).
Which of both is better practice or more commonly used? Thank you
<!-- widget_player.xml -->
<LinearLayout
android:id="#+id/player_controls"
android:layout_width="match_parent"
android:layout_height="30dp"
android:orientation="horizontal" >
<ImageButton
android:id="#+id/btn_player_prev"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:src="#android:drawable/ic_media_previous" />
<ImageButton
android:id="#+id/btn_player_next"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:src="#android:drawable/ic_media_next" />
</LinearLayout>
WidgetPlayer class
public class WidgetPlayer extends AppWidgetProvider {
public static String ACTION_WIDGET_PREV = "action.WIDGET_PREV";
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
final int nPlayerWidgets = appWidgetIds.length;
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_player);
for (int i = 0; i < nPlayerWidgets; i++) {
int appWidgetId = appWidgetIds[i];
updateWidgetPlayer(context, appWidgetManager);
Intent intent;
PendingIntent actionPendingIntent;
// PREV button
intent = new Intent(context, WidgetPlayer.class);
intent.setAction(ACTION_WIDGET_PREV);
actionPendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
remoteViews.setOnClickPendingIntent(R.id.btn_player_prev, actionPendingIntent);
// NEXT button (not using a broadcast)
intent = new Intent(context, PlayerService.class);
intent.setAction(PlayerService.ACTION_NEXT);
actionPendingIntent = PendingIntent.getService(context, 0, intent, 0);
remoteViews.setOnClickPendingIntent(R.id.btn_player_next, actionPendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
}
#Override
public void onReceive(Context context, Intent intent) {
AppWidgetManager manager = AppWidgetManager.getInstance(context.getApplicationContext());
if (intent.getAction().equals(ACTION_WIDGET_PREV)) {
Intent iPrev = new Intent(PlayerService.ACTION_PREV);
iPrev.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetMetaPlayerIds);
context.startService(iPrev);
updateWidgetPlayer(context, manager);
}
// handle more actions here
else {
super.onReceive(context, intent);
}
}
}
The NEXT button code looks more concise so it is better choice if it does what you want. With the PREVIOUS code you have the extra step of receiving the broadcast which appears unnecessary.
You can pass along the id's in the intent to the service if you need those.

Can't update Button's text in a Widget

How do I access items of a homescreen Widget, so I can make changes to them like setting a Button's text? In my AppWidgetProvider's onReceive() method I'm trying to set the text of a Button, which is in my homescreen widget:
#Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(MainActivity.ACTION_CHANGE_BUTTONSTATE))
{
String state = intent.getExtras().getString("state");
Log.d("HomescreenWidget", "received broadcast for button state");
RemoteViews views = new RemoteViews(context.getPackageName(),
R.id.widgetButton);
views.setTextViewText(R.id.widgetButton, state);
ComponentName cn = new ComponentName(context,
HomescreenWidget.class);
AppWidgetManager.getInstance(context).updateAppWidget(cn, views);
}
super.onReceive(context, intent);
}
My Widget's layout.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/RelativeLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/widget_margin" >
<Button
android:id="#+id/playButton_Widget"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:minWidth="80dp"
android:text="#string/playButton" />
</RelativeLayout>
I'm receiving the Broadcast, but then my Widget shows following text: "Problem loading widget".
EDIT
I found following message at the catlog:
W/AppWidgetHostView(135): updateAppWidget couldn't find any view, using error view
W/AppWidgetHostView(135): android.widget.RemoteViews$ActionException: can't find view: 0x7f0a0004
0x7f0a0004 is my Widget's Button. What could be the reason, that it can't be found?
To Access your view via appwidget provider you can use this remote views
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
views.setTextViewText(R.id.widgetname, newName);
or via service :
public class UpdateWidgetService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onStart(Intent intent, int startId) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this
.getApplicationContext());
int[] allWidgetIds = intent
.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
for (int widgetId : allWidgetIds) {
RemoteViews remoteViews = new RemoteViews(this
.getApplicationContext().getPackageName(),
R.layout.widget_layout);
remoteViews.setTextViewText(R.id.update,
"Random: " + String.valueOf(number));
appWidgetManager.updateAppWidget(widgetId, remoteViews);
}
stopSelf();
super.onStart(intent, startId);
}
}
and don't forget to add the service to the manifest
<service android:name=".UpdateWidgetService"></service>
and then in the onUpdate (in your App Widget Provider class)
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
ComponentName thisWidget = new ComponentName(context,
MyWidgetProvider.class);
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
Intent intent = new Intent(context.getApplicationContext(),
UpdateWidgetService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);
context.startService(intent);
}
I hope this can help :)
I've just found the solution. The whole time I was passing the wrong ID for the Button. widgetButton did not exist in the Widget's layout. It was a button from my main Activity
import android.widget.RemoteViews;
//grab the layout, then set the text of the Button called R.id.Counter:
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.my_layout);
remoteViews.setTextViewText(R.id.Counter, "Set button text here");

Widget ImageButton listener not allways called

I have a simple Widget (Android 2.1) containing just a LinearLayout, itself containing an ImageButton.
The ImageButton has a on-click listener.
The problem is: If I put several of this same widget on my home screen, some are working (listener called when button pressed), and some are not! I cannot see any pattern in which are working and which are not.
Here is the widget layout:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#null">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/ImageButton01"
android:src="#drawable/widget_running"
android:background="#null">
</ImageButton>
And here is the widget provider code:
public class GPAppWidgetProvider extends AppWidgetProvider {
private String mTag = getClass().getSimpleName();
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
Log.e(mTag, "onUpdate ");
// Perform this loop procedure for each App Widget that belongs to this
// provider
for (int i = 0; i < N; i++) {
Log.e(mTag, "widget onUpdate one loop");
int appWidgetId = appWidgetIds[i];
// Create an Intent
Intent intent = new Intent(context, GPService.class).setAction(ACTION_WIDGET_TOGGLE_PAUSE);
intent.putExtra("widgetId", appWidgetId);
PendingIntent pauseIntent = PendingIntent.getService(context, 0, intent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.gp_appwidget);
views.setOnClickPendingIntent(R.id.ImageButton01, pauseIntent);
// widget update
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
}
I had the same problem.
Don't forget to set a different "requestCode" when you call "getService" :
public static PendingIntent getService (Context context, int requestCode, Intent intent, int flags)
And make sure your "appWidgetId" is different for each widget.

Categories

Resources