I've pretty much given up on dynamic remoteviews, but I still have about 20 remoteViews with 3-4 method calls on each in my onUpdate method. Now the problem is, can I have an iterator on RemoteViews subView id for a loop?
EDIT
Ok, here's the code, I tried using bookmarkcounter as a iterator since the R class generates R.id.widget* * as a incrementing number (by one). But it doesn't work.
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
Cursor cursor;
String SORT_BY_COLUMN = Constants.SORT_BY_COLUMN;
String SORT_ORDER = Constants.SORT_ORDER;
int bookmarkIdCounter = R.id.widget_bookmark_1;
Bitmap bitmap;
HashMap<Integer, String> urls = new HashMap<Integer, String>();
ComponentName thisWidget = new ComponentName(context, WidgetProvider.class);
RemoteViews updateViews = new RemoteViews(
context.getPackageName(), R.layout.widget_main);
RemoteViews bookmarks = new RemoteViews(
context.getPackageName(), R.layout.widget_bookmarks);;
cursor = context.getContentResolver().query(
Browser.BOOKMARKS_URI, Constants.projection, Constants.selection,
null, SORT_BY_COLUMN + " " + SORT_ORDER);
if(cursor.moveToFirst()) {
ByteArrayInputStream blobImage;
do{
blobImage = new ByteArrayInputStream(
cursor.getBlob(cursor.getColumnIndex(BookmarkColumns.FAVICON)));
bitmap = BitmapFactory.decodeStream(blobImage);
bitmap = Bitmap.createScaledBitmap(
bitmap, Constants.FAVICON_SIZE, Constants.FAVICON_SIZE, false);
bookmarks.setImageViewBitmap(bookmarkIdCounter, bitmap);
bookmarks.setInt(bookmarkIdCounter, "setBackgroundColor", Color.WHITE);
urls.put(bookmarkIdCounter,
cursor.getString(
cursor.getColumnIndex(BookmarkColumns.URL)));
bookmarkIdCounter++;
} while (cursor.moveToNext() && (bookmarkIdCounter < 2));
}
updateViews.addView(R.id.widget_main_container, bookmarks);
cursor.deactivate();
appWidgetManager.updateAppWidget(thisWidget, updateViews);
}
RemoteViews is not a View nor does it contain Views.
It is a way to "describe" a View and have it created in some other process. Basically it's just a set of actions that must be performed to build a View.
As there are no Views inside it there is no way to retrieve/iterate a list of subViews.
Related
the android widget content when device rotated are suddenly gone.
do I have to repopulate them when device is rotated? but the widget dont have onconfiguration change to listen to.
also I used alarmmanager with service to populate the widget for new app (adding to viewflipper) to display every 1 minute.
widget code:
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
try{
// create intent service per APP id
for(int i = 0; i < appWidgetIds.length; i++)
{
Log.e("onUpdate -- Widget_2_6", "onUpdate -- Widget_2_6: widget ID: " + appWidgetIds[i]);
// check if alarms not created, create 1
if(!GlobalStorage.tempStorage.containsKey(Widget_2_6.class.toString() + appWidgetIds[i]))
{
createAlarmService(context, appWidgetIds[i]);
// put to hash for alarms created
GlobalStorage.tempStorage.put(Widget_2_6.class.toString() + appWidgetIds[i], 0);
//CustomAndroidTools.popToast(Widget_2_6.class.toString() + appWidgetIds[i], context);
}
}
}
catch(Exception e)
{
Log.e("onUpdate -- Widget_2_6", "onUpdate -- Widget_2_6: error: " + e.toString());
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
private void createAlarmService(Context context, int id)
{
if(alarm == null)
{
createAlarm(context);
}
// each new alarm will repeat in increasing half minute: so first is 1 min next is 1 min and 30 sec ...
alarm.setRepeating(AlarmManager.RTC, 0, (1000 * (60 + (GlobalStorage.tempStorage.size() * 30))), createPendingIntent(context, id));
Log.e("createAlarmService -- Widget_2_6", "createAlarmService -- Widget_2_6, creating alarm for widget id: " + id);
}
service code:
if(CustomAndroidTools.checkDeviceIsInteractive(context))
{
new Thread(new Runnable() {
public void run() {
try{
ArrayList<AppInfo> appInfos = init(context, _class, widgetID);
buildUpdate(context, _class, widgetID, appInfos);
// update the limit offset here instead so that to ensure no exception came from building the UI of the widget
updateLimitOffset(_class, widgetID);
}
catch(Exception e)
{
Log.e("Thread -- onStartCommand -- WidgetUpdateService", "Thread -- onStartCommand -- WidgetUpdateService: error: " + e.toString());
}
}
}).start();
}
private ArrayList<AppInfo> init(Context context, Class<?> _class, int widgetID)
{
ArrayList<AppInfo> appInfos = new ArrayList<AppInfo>();
try{
appListManager alm = new appListManager(context);
int skip = 0;
//int limit = 10;
if(GlobalStorage.tempStorage.containsKey(_class.toString() + widgetID))
{
skip = GlobalStorage.tempStorage.get(_class.toString() + widgetID);
}
if(skip == 0) // first initialize
{
///TODO: for testing, get the first 5 used by banner
appInfos.add(alm.getAppById(30));
appInfos.add(alm.getAppById(16));
appInfos.add(alm.getAppById(13));
appInfos.add(alm.getAppById(12));
appInfos.add(alm.getAppById(6));
}
//appInfos = alm.getAllAppsUnderTheCategory(-1, skip, limit);
}
catch(Exception e)
{
Log.e("init -- WidgetUpdateService", "init -- WidgetUpdateService: error: " + e.toString());
}
return appInfos;
}
private void updateLimitOffset(Class<?> _class, int widgetID){
int skip = 0;
int limit = 10;
if(GlobalStorage.tempStorage.containsKey(_class.toString() + widgetID))
{
skip = GlobalStorage.tempStorage.get(_class.toString() + widgetID);
}
if(skip != 0)
{
limit = 5;
}
GlobalStorage.tempStorage.put(_class.toString() + widgetID, skip + limit); // update offset limit here
}
private void buildUpdate(Context context, Class<?> _class, int widgetID, ArrayList<AppInfo> appInfos) throws Exception
{
RemoteViews views = null;
appListManager alm = new appListManager(context);
try{
if(_class.equals(Widget_1_6.class) || _class.equals(Widget_1_6_2.class))
{
views = new RemoteViews(getPackageName(), R.layout.widget_1_6);
}
else if(_class.equals(Widget_2_6.class) || _class.equals(Widget_2_6_2.class))
{
views = new RemoteViews(getPackageName(), R.layout.widget_2_6);
}
if(alm.getTotalApps(-1) < 1)
{
views.setViewVisibility(R.id.app, View.GONE);
views.setViewVisibility(R.id.sorryText, View.VISIBLE);
views.setViewVisibility(R.id.loadingText, View.GONE);
}
else
{
views.setViewVisibility(R.id.app, View.VISIBLE);
views.setViewVisibility(R.id.sorryText, View.GONE);
views.setViewVisibility(R.id.loadingText, View.GONE);
if(appInfos != null)
{
for(int i = 0; i < appInfos.size(); i++)
{
views.addView(R.id.appInfo, inflateLayout(appInfos.get(i), context, _class, widgetID));
}
}
Intent refreshWidgetIncrement = new Intent(context, WidgetControlService.class);
refreshWidgetIncrement.putExtra(WidgetControlService.INCREMENT, true);
refreshWidgetIncrement.putExtra(WidgetControlService.DECREMENT, false);
refreshWidgetIncrement.putExtra(WidgetControlService.CLASS, _class);
refreshWidgetIncrement.putExtra(WidgetControlService.WIDGET_ID, widgetID);
refreshWidgetIncrement.setData(Uri.withAppendedPath(Uri.parse("BFR://widget/id/#togetituniqie" + WidgetControlService.class.toString()), UUID.randomUUID().toString()));
PendingIntent pIntentIncrement = PendingIntent.getService(context, 0, refreshWidgetIncrement, PendingIntent.FLAG_CANCEL_CURRENT);
views.setOnClickPendingIntent(R.id.arrowRight, pIntentIncrement);
Intent refreshWidgetDecrement = new Intent(context, WidgetControlService.class);
refreshWidgetDecrement.putExtra(WidgetControlService.DECREMENT, true);
refreshWidgetDecrement.putExtra(WidgetControlService.INCREMENT, false);
refreshWidgetDecrement.putExtra(WidgetControlService.CLASS, _class);
refreshWidgetDecrement.putExtra(WidgetControlService.WIDGET_ID, widgetID);
refreshWidgetDecrement.setData(Uri.withAppendedPath(Uri.parse("BFR://widget/id/#togetituniqie" + WidgetControlService.class.toString()), UUID.randomUUID().toString()));
PendingIntent pIntentDecrement = PendingIntent.getService(context, 0, refreshWidgetDecrement, PendingIntent.FLAG_CANCEL_CURRENT);
views.setOnClickPendingIntent(R.id.arrowLeft, pIntentDecrement);
}
AppWidgetManager manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(widgetID, views);
}
catch(Exception e)
{
Log.e("buildUpdate -- WidgetUpdateService", "buildUpdate -- WidgetUpdateService: error: " + e.toString());
}
}
private RemoteViews inflateLayout(AppInfo appInfo, Context context, Class<?> _class, int widgetID) throws IOException
{
RemoteViews view = null;
if(_class.equals(Widget_1_6.class) || _class.equals(Widget_1_6_2.class))
{
view = new RemoteViews(getPackageName(), R.layout.widget_1_6_body_fragment);
view = inflateWidget1_6(view, appInfo, context, _class, widgetID);
}
else if(_class.equals(Widget_2_6.class) || _class.equals(Widget_2_6_2.class))
{
view = new RemoteViews(getPackageName(), R.layout.widget_2_6_body_fragment);
view = inflateWidget2_6(view, appInfo, context, _class, widgetID);
}
return view;
}
private RemoteViews inflateWidget1_6(RemoteViews view, AppInfo appInfo, Context context, Class<?> _class, int widgetID) throws IOException
{
view.setTextViewText(R.id.appTitle, appInfo.title);
view.setTextViewText(R.id.appDesc, appInfo.shortDesc);
File file = new File(Constants.saveImageLocation + appInfo.iconLoc);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;
Bitmap bitmap = null;
if(file.exists()) // if exists in local
{
bitmap = BitmapFactory.decodeFile(Constants.saveImageLocation + appInfo.iconLoc, options);
}
else if (CustomAndroidTools.isImageFoundInAssets(appInfo.iconLoc, context))
{
bitmap = CustomAndroidTools.getImageFromAssets(appInfo.iconLoc, context);
}
else
{
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.broken, options);
}
view.setImageViewBitmap(R.id.appIcon, bitmap);
view.setOnClickPendingIntent(R.id.appIcon, null);
view.setOnClickPendingIntent(R.id.appDetail, null);
Intent openApp = new Intent(context, AppDetailViewActivity.class);
openApp.putExtra(AppDetailViewActivity.LAST_SELECTED_APP, appInfo);
Log.e("current App", "current App: name: " + appInfo.title + ", category index: " + appInfo.category + ". For Widget type: " + _class.toString() + ", id: " + widgetID);
openApp.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
openApp.setData(Uri.withAppendedPath(Uri.parse("BFR://widget/id/#togetituniqie" + new ComponentName(context, _class)), UUID.randomUUID().toString()));
PendingIntent pIntent = PendingIntent.getActivity(context, 0, openApp, 0);
view.setOnClickPendingIntent(R.id.appIcon, pIntent);
view.setOnClickPendingIntent(R.id.appDetail, pIntent);
return view;
}
private RemoteViews inflateWidget2_6(RemoteViews view, AppInfo appInfo, Context context, Class<?> _class, int widgetID) throws IOException
{
File file = new File(Constants.saveImageLocation + appInfo.bannerLoc);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;
Bitmap bitmap = null;
if(file.exists()) // if exists in local
{
bitmap = BitmapFactory.decodeFile(Constants.saveImageLocation + appInfo.bannerLoc, options);
}
else if (CustomAndroidTools.isImageFoundInAssets(appInfo.bannerLoc, context))
{
bitmap = CustomAndroidTools.getImageFromAssets(appInfo.bannerLoc, context);
}
else
{
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.broken, options);
}
view.setImageViewBitmap(R.id.appBanner, bitmap);
view.setOnClickPendingIntent(R.id.appBanner, null);
Intent openApp = new Intent(context, AppDetailViewActivity.class);
openApp.putExtra(AppDetailViewActivity.LAST_SELECTED_APP, appInfo);
Log.e("current App", "current App: name: " + appInfo.title + ", category index: " + appInfo.category + ". For Widget type: " + _class.toString() + ", id: " + widgetID);
openApp.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
openApp.setData(Uri.withAppendedPath(Uri.parse("BFR://widget/id/#togetituniqie" + new ComponentName(context, _class)), UUID.randomUUID().toString()));
PendingIntent pIntent = PendingIntent.getActivity(context, 0, openApp, 0);
view.setOnClickPendingIntent(R.id.appBanner, pIntent);
return view;
}
is there anything i missed?
Ok. got it working, the problem is with the RemoteView's behavior.(NOTE: RemoteView will send the latest changes to views needing a refresh/update)
so what I did was instead of using manager.updateAppWidget(widgetID, views); on all occasion.
I used a flag to know when to use updateAppWidget or partiallyUpdateAppWidget.
below is the modified code under the buildUpdate function from above listing, replacing manager.updateAppWidget(widgetID, views); into:
if(!GlobalStorage.tempStorage.containsKey(_class.toString() + widgetID) || GlobalStorage.tempStorage.get(_class.toString() + widgetID) == 0)
{
Log.e("buildUpdate -- WidgetUpdateService", "buildUpdate -- WidgetUpdateService: either not in collection or is 0: do full update");
manager.updateAppWidget(widgetID, views);
}
else
{
Log.e("buildUpdate -- WidgetUpdateService", "buildUpdate -- WidgetUpdateService: is not 0: do partial update");
manager.partiallyUpdateAppWidget(widgetID, views);
}
with the modified logic, when the view is needing for a refresh/update (which we cannot control most of the time like orientation change). it will not override the whole view and just the partial view.
I have a problem to make a customizable AppWidget : I don't know how to do... I tried to update appearance regularly with this function :
public static void updateApparence(Context context)
{
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
for(int i = 0 ; i < widgetLayoutIds.length ; i++)
{
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, appWidgetProvidersClass[i]));
RemoteViews views = new RemoteViews(context.getPackageName(), widgetLayoutIds[i]);
views.setInt(R.id.widget_background, "setBackgroundColor", prefs.getInt(SettingsApparence.BACKGROUND_COLOR, 0xFFFFFFFF));
views.setInt(R.id.matiere, "setTextColor", prefs.getInt(SettingsApparence.COULEUR_MATIERE, 0xFF666666));
views.setInt(R.id.horaires, "setTextColor", prefs.getInt(SettingsApparence.COULEUR_HORAIRES, 0xFF888888));
views.setInt(R.id.salle, "setTextColor", prefs.getInt(SettingsApparence.COULEUR_SALLE, 0xFF888888));
Bitmap bm = BitmapFactory.decodeFile(context.getFilesDir() + PATH_CLE);
if(bm == null)
{
bm = BitmapFactory.decodeResource(context.getResources(), R.drawable.settings_icon);
bm = changeImageColor(bm, prefs.getInt(SettingsApparence.COULEUR_CLE, 0xFF000000));
}
views.setBitmap(R.id.settings, "setImageBitmap", bm);
bm = BitmapFactory.decodeFile(context.getFilesDir() + PATH_CALENDRIER);
if(bm == null)
{
bm = BitmapFactory.decodeResource(context.getResources(), R.drawable.calendrier_icon);
bm = changeImageColor(bm, prefs.getInt(SettingsApparence.COULEUR_CALENDRIER, 0xFF000000));
}
views.setBitmap(R.id.emploi_du_temps, "setImageBitmap", bm);
appWidgetManager.updateAppWidget(appWidgetIds, views);
}
}
But sometimes, the original appearance (in R.layout.widget, in appWidgetProvidersClass[]) reappear...
How can I do that ?
My assumption is that I just do not fully understand widgets yet. Hopefully one of you guru's can see where my logic/thinking is flawed.
Ultimately what happens with my widget is that it eventually becomes unresponsive at very random intervals (usually > 5 hours).
My investigation so far has led me to believe that it's potentially a result of the OS running low on memory and my widget being recreated?
If that's the case, I would have thought that the OnUpdate() method would handle this but potentially I'm wrong here.
I have read pretty much every thread on here regarding widget unresponsiveness. The only one that showed promise for me was this one:
Android Homescreen Widget becomes Unresponsive
but I'm not using a service and not sure I need to.
The goal of the widget is to first check if the user has created a profile. This is done by checking for the existence of a local db along with a user record. If neither of these exist, the widget should display a "Get Started" image (which it does successfully).
Once the user taps on this image, they are launched into a profile creation wizard. Once the profile is created, the widget is updated from the app to display an image along with some caloric intake information.
There are three clickable items on the widget. The image and the two textviews. Each respectively launching a different activity in my app.
Here is the widget class:
public class bbi_widget extends AppWidgetProvider {
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
}
private static String week6Path = "";
public static RemoteViews getWidgetRemoteViews(Context context) {
Intent calorieCrushIntent = new Intent(context, calorie_crush.class);
Intent dashBoardIntent = new Intent(context, DashboardActivity.class);
PendingIntent calorieCrushPendingIntent = PendingIntent.getActivity(
context, 0, calorieCrushIntent, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent dashboardPendingIntent = PendingIntent.getActivity(
context, 0, dashBoardIntent, PendingIntent.FLAG_UPDATE_CURRENT);
RemoteViews appWidgetViews = new RemoteViews(context.getPackageName(),
R.layout.initial_widget_layout);
appWidgetViews.setOnClickPendingIntent(R.id.surp_def_widgettextView, calorieCrushPendingIntent);
appWidgetViews.setOnClickPendingIntent(R.id.calTextView, calorieCrushPendingIntent);
appWidgetViews.setOnClickPendingIntent(R.id.widget_after_picture, dashboardPendingIntent);
return appWidgetViews;
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
BBIDatabase db = new BBIDatabase(context);
db.openToRead();
boolean doesTableExist = db.doesTableExist(BBIDatabase.BBI_USER_TABLE);
db.close();
boolean doesUserExist = false;
if (doesTableExist){
db.openToRead();
doesUserExist = db.doesUserExist();
db.close();
}
if (!doesTableExist || !doesUserExist){
Intent getStartedIntent = new Intent(context, GettingStartedWizardActivity.class);
PendingIntent getStartedPendingIntent = PendingIntent.getActivity(
context, 0, getStartedIntent, PendingIntent.FLAG_UPDATE_CURRENT);
for (int index = 0; index < appWidgetIds.length; index++) {
int appWidgetId = appWidgetIds[index];
RemoteViews appWidgetViews = getWidgetRemoteViews(context);
appWidgetViews.setOnClickPendingIntent(R.id.widget_after_picture, getStartedPendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, appWidgetViews);
}
} else {
db.openToRead();
String curPath = db.GetSixWeekPath();
Bitmap sixWeekBmp = null;
if (week6Path != curPath && curPath != null && week6Path != null) {
week6Path = db.GetSixWeekPath();
sixWeekBmp = BitmapFactory.decodeFile(week6Path);
}
db.close();
db.openToRead();
int totalCalsToday = db.GetTodaysCalorieIntakeForWidget();
int bmrWithAct = db.GetBMRPlusActivity();
int additionalCalsCrushed = db.GetTodaysCaloriesBurnedForWidget();
int surp = totalCalsToday - (bmrWithAct + additionalCalsCrushed);
if (surp < 0)
surp = 0;
int def = totalCalsToday - (bmrWithAct + additionalCalsCrushed);
if (def > 0)
def = 0;
db.close();
for (int index = 0; index < appWidgetIds.length; index++) {
int appWidgetId = appWidgetIds[index];
RemoteViews appWidgetViews = getWidgetRemoteViews(context);
appWidgetViews.setViewVisibility(R.id.calTextView, View.VISIBLE);
appWidgetViews.setViewVisibility(R.id.surp_def_widgettextView, View.VISIBLE);
appWidgetViews.setTextViewText(R.id.calTextView, "Calorie intake: " + String.valueOf(totalCalsToday));
if (surp > 0) {
appWidgetViews.setTextViewText(R.id.surp_def_widgettextView, "SURPLUS " + String.valueOf(surp));
appWidgetViews.setTextColor(R.id.surp_def_widgettextView, context.getResources().getColor(R.color.surplus_ball_color));
} else {
appWidgetViews.setTextViewText(R.id.surp_def_widgettextView, "DEFICIT " + String.valueOf(def));
appWidgetViews.setTextColor(R.id.surp_def_widgettextView, context.getResources().getColor(R.color.calorie_crush_ball));
}
appWidgetViews.setImageViewBitmap(R.id.widget_after_picture, sixWeekBmp);
Intent calorieCrushIntent = new Intent(context, calorie_crush.class);
Intent dashBoardIntent = new Intent(context, DashboardActivity.class);
PendingIntent calorieCrushPendingIntent = PendingIntent.getActivity(
context, 0, calorieCrushIntent, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent dashboardPendingIntent = PendingIntent.getActivity(
context, 0, dashBoardIntent, PendingIntent.FLAG_UPDATE_CURRENT);
appWidgetViews.setOnClickPendingIntent(R.id.surp_def_widgettextView, calorieCrushPendingIntent);
appWidgetViews.setOnClickPendingIntent(R.id.calTextView, calorieCrushPendingIntent);
appWidgetViews.setOnClickPendingIntent(R.id.widget_after_picture, dashboardPendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, appWidgetViews);
}
}
}
}
From my app, I do update these values in the widget using remoteViews.
Here is the helper class in my app:
public class WidgetHelper {
public static void UpdateCalorieIntake(int newValue, Context context) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.initial_widget_layout);
ComponentName thisWidget = new ComponentName(context, bbi_widget.class);
remoteViews.setTextViewText(R.id.calTextView, "Calories in " + String.valueOf(newValue));
appWidgetManager.updateAppWidget(thisWidget, remoteViews);
}
public static void UpdateWidgetSurplus(int newValue, Context context) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.initial_widget_layout);
ComponentName thisWidget = new ComponentName(context, bbi_widget.class);
if (newValue > 0) {
remoteViews.setTextViewText(R.id.surp_def_widgettextView, "Caloric Surplus " + String.valueOf(newValue));
remoteViews.setTextColor(R.id.surp_def_widgettextView, context.getResources().getColor(R.color.surplus_ball_color));
} else {
remoteViews.setTextViewText(R.id.surp_def_widgettextView, "Caloric Deficit " + String.valueOf(newValue));
remoteViews.setTextColor(R.id.surp_def_widgettextView, context.getResources().getColor(R.color.calorie_crush_ball));
}
appWidgetManager.updateAppWidget(thisWidget, remoteViews);
}
private static String week6Path = "";
public static void UpdateAll(Context context) {
BBIDatabase db = new BBIDatabase(context);
db.openToRead();
String curPath = db.GetSixWeekPath();
Bitmap sixWeekBmp = null;
if (week6Path != curPath && curPath != null && week6Path != null) {
week6Path = db.GetSixWeekPath();
sixWeekBmp = BitmapFactory.decodeFile(week6Path);
}
db.close();
db.openToRead();
int totalCalsToday = db.GetTodaysCalorieIntakeForWidget();
int bmrWithAct = db.GetBMRPlusActivity();
int additionalCalsCrushed = db.GetTodaysCaloriesBurnedForWidget();
int surp = totalCalsToday - (bmrWithAct + additionalCalsCrushed);
if (surp < 0)
surp = 0;
int def = totalCalsToday - (bmrWithAct + additionalCalsCrushed);
if (def > 0)
def = 0;
db.close();
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews appWidgetViews = new RemoteViews(context.getPackageName(), R.layout.initial_widget_layout);
ComponentName thisWidget = new ComponentName(context, bbi_widget.class);
appWidgetViews.setTextViewText(R.id.calTextView, "Calorie intake: " + String.valueOf(totalCalsToday));
if (surp > 0) {
appWidgetViews.setTextViewText(R.id.surp_def_widgettextView, "Caloric surplus " + String.valueOf(surp));
appWidgetViews.setTextColor(R.id.surp_def_widgettextView, context.getResources().getColor(R.color.surplus_ball_color));
} else {
appWidgetViews.setTextViewText(R.id.surp_def_widgettextView, "Caloric deficit " + String.valueOf(def));
appWidgetViews.setTextColor(R.id.surp_def_widgettextView, context.getResources().getColor(R.color.calorie_crush_ball));
}
appWidgetViews.setImageViewBitmap(R.id.widget_after_picture, sixWeekBmp);
Intent calorieCrushIntent = new Intent(context, calorie_crush.class);
Intent dashBoardIntent = new Intent(context, DashboardActivity.class);
PendingIntent calorieCrushPendingIntent = PendingIntent.getActivity(
context, 0, calorieCrushIntent, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent dashboardPendingIntent = PendingIntent.getActivity(
context, 0, dashBoardIntent, PendingIntent.FLAG_UPDATE_CURRENT);
appWidgetViews.setOnClickPendingIntent(R.id.surp_def_widgettextView, calorieCrushPendingIntent);
appWidgetViews.setOnClickPendingIntent(R.id.calTextView, calorieCrushPendingIntent);
appWidgetViews.setOnClickPendingIntent(R.id.widget_after_picture, dashboardPendingIntent);
appWidgetManager.updateAppWidget(thisWidget, appWidgetViews);
}
}
Provider infor:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="294dp"
android:minHeight="294dp"
android:previewImage="#drawable/bbi_icon"
android:initialLayout="#layout/initial_widget_layout"
>
</appwidget-provider>
I am creating a widget that will show some datas for the user from a database. One of the datas depends on a parameter that can be set in my settings activity. I save this parameter with sharedpreferences so I can use it anywhere in my code.
In an activity I could use getApplicationContext, but here where I tell the widget what to do, it doesnt work. What should I use instead of getApplicationContext?
UPDATED
public class plWidget extends AppWidgetProvider{
SharedPreferences sharedPreferences;
String loadedWeightType;
#Override
public void onDeleted(Context context, int[] appWidgetIds) {
// TODO Auto-generated method stub
super.onDeleted(context, appWidgetIds);
Toast.makeText(context, "deleted", 2500).show();
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// TODO Auto-generated method stub
super.onUpdate(context, appWidgetManager, appWidgetIds);
String Wcal="0",Wfat="0",Wprot="0",Wcarb="0",Wsport="0";
final int N = appWidgetIds.length;
for (int i = 0;i<N;i++)
{
int awID = appWidgetIds[i];
updateAppWidget(context, appWidgetManager, appWidgetIds[i]);
GlobalVars.setSulyType(loadedWeightType);
Log.i("SULYYYY", GlobalVars.getSulyType());
long now = System.currentTimeMillis();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Date resultdate = new Date(now);
Log.i("ASAS", sdf.format(resultdate));
hornot database = new hornot(context);
database.open();
int ccc = database.checkDataExists(sdf.format(resultdate), sdf.format(resultdate));
if (ccc==0){
Log.i("nulla", "0");
Log.i("nulla", GlobalVars.getSulyType());
Wcal="0";
Wfat="0";
Wprot="0";
Wcarb="0";
}
else{
database.getDateFromAndToFromDatePicker(sdf.format(resultdate), sdf.format(resultdate));
Wcal = GlobalVars.getSums();
database.FATgetDateFromAndToFromDatePicker(sdf.format(resultdate), sdf.format(resultdate));
Wfat = GlobalVars.getSums();
database.PROTEINgetDateFromAndToFromDatePicker(sdf.format(resultdate), sdf.format(resultdate));
Wprot = GlobalVars.getSums();
database.CARBSgetDateFromAndToFromDatePicker(sdf.format(resultdate), sdf.format(resultdate));
Wcarb = GlobalVars.getSums();
}
int ddd = database.checkDataExistsSports(sdf.format(resultdate), sdf.format(resultdate));
if (ddd==0){
Wsport="0";
}
else{
if (loadedWeightType.equals("kilogramm"))
{
database.SportgetDateFromAndToFromDatePicker(sdf.format(resultdate), sdf.format(resultdate));
// Wsport = GlobalVars.getSums();
Wsport= "kilogramm";
}
else if (loadedWeightType.equals("pound"))
{
database.SportgetDateFromAndToFromDatePicker(sdf.format(resultdate), sdf.format(resultdate));
Wsport="pound";
}
}
RemoteViews v = new RemoteViews(context.getPackageName(), R.layout.widget);
v.setTextViewText(R.id.tvwidgetUpdate, Wcal+Wfat+Wprot+Wcarb+Wsport);
appWidgetManager.updateAppWidget(awID, v);
database.close();
}
}
public void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
SharedPreferences prefs = context.getSharedPreferences(plWidget.class + Integer.toString(appWidgetId),
Context.MODE_WORLD_READABLE);
loadedWeightType= prefs.getString("weighttype", "kilogramm");
}
}
Thanks in advance!
UPDATE
As usual I do the load funciton:
public void LoadWeightType(){
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
loadedWeightType= sharedPreferences.getString("weighttype", "kilogramm");
}
With this in a normal activity, I can load the weighttype. I guess that updateAppWidget function should somehow substitue this function.
public static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
SharedPreferences prefs = context.getSharedPreferences(MyConfigActivity.NAME + Integer.toString(appWidgetId), Context.MODE_WORLD_READABLE);
I call updateAppWidget from onUpdate for each instance of my widget, passing in the parameters. The passed in Context has getSharedPreferences defined, and I specify which set of preferences to get based on the name of the configuration activity and the id of the widget. Here's the sdk reference for the getSharedPreferences function: http://developer.android.com/reference/android/content/Context.html#getSharedPreferences%28java.lang.String,%20int%29
In my drawable-hdpi folder i have 4 image files (.png) to serve as the background of awidget. By default android:background="#drawable/goldgreenbg" is set for the LinearLayout. I created a preferences screen to let the user change the background.
How to do that? I would like to use this code for it:
if (listpref.equals("color1"))
{
Toast.makeText(EditPreferences.this, "Black" + listpref, Toast.LENGTH_LONG).show();
}
else if (listpref.equals("color2"))
{
Toast.makeText(EditPreferences.this, "Brown" + listpref, Toast.LENGTH_LONG).show();
}
Update:
Where shall i put this code to?
MainActivity.java: for the activity
UpdateService.java: for the widget
EditPreferences.java: for the preferences
Main.xml includes the listview and widgetlayout is id of it.
setContentView(R.layout.main);
preferences = PreferenceManager.getDefaultSharedPreferences(this);
String listpref = preferences.getString("listPref", "n/a");
LinearLayout ll = (LinearLayout) findViewById(R.id.widgetlayout);
if (listpref.equals("color1"))
{
Toast.makeText(MainActivity.this, "Black" + listpref, Toast.LENGTH_LONG).show();
ll.setBackgroundDrawable(getResources().getDrawable(R.drawable.blackbg));
}
else if (listpref.equals("color2"))
{
Toast.makeText(MainActivity.this, "Brown" + listpref, Toast.LENGTH_LONG).show();
ll.setBackgroundDrawable(getResources().getDrawable(R.drawable.brownbg));
}
Assuming you allready have the LinearLayout on your screen (using setContentView), you can change the background quite easily like so:
yourLinearLayout.setBackgroundDrawable(getResources().getDrawable(R.drawable.blackbg));
(and get that layout using findViewById() ofcourse )
I found the solution.
EditPreferences.java:
final Preference listpref = getPreferenceScreen().findPreference("listPref");
listpref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
{
public boolean onPreferenceChange(Preference p, Object newValue)
{
String color = (String) newValue;
if (color.equals("color1"))
{
RemoteViews updateViews = new RemoteViews(EditPreferences.this.getPackageName(), R.layout.main);
updateViews.setTextColor(R.id.widget_textview, Color.rgb(208, 202, 202));
updateViews.setTextColor(R.id.widget_textview2, Color.WHITE);
updateViews.setTextColor(R.id.widget_textview3, Color.rgb(176, 175, 175));
// updateViews.setImageViewBitmap(R.id.ImageView01, ((BitmapDrawable)EditPreferences.this.getResources().getDrawable(R.drawable.forestbg)).getBitmap());
updateViews.setImageViewResource(R.id.ImageView01, R.drawable.blacktrans);
ComponentName thisWidget = new ComponentName(EditPreferences.this, HelloWidget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(EditPreferences.this);
manager.updateAppWidget(thisWidget, updateViews);
}
else if (color.equals("color2"))
{
RemoteViews updateViews = new RemoteViews(EditPreferences.this.getPackageName(), R.layout.main);
updateViews.setTextColor(R.id.widget_textview, Color.rgb(23, 81, 11));
updateViews.setTextColor(R.id.widget_textview2, Color.rgb(232, 232, 107));
updateViews.setTextColor(R.id.widget_textview3, Color.rgb(23, 81, 11));
updateViews.setImageViewBitmap(R.id.ImageView01, ((BitmapDrawable)EditPreferences.this.getResources().getDrawable(R.drawable.goldgreenbg)).getBitmap());
// updateViews.setImageViewResource(R.id.ImageView01, R.drawable.goldgreenbgf);
ComponentName thisWidget = new ComponentName(EditPreferences.this, HelloWidget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(EditPreferences.this);
manager.updateAppWidget(thisWidget, updateViews);
}
return true;
}
});
public void onStart(Intent intent, int startId) {
getPrefs();
}
private void getPrefs() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
ListPreference = prefs.getString("listPref", "nr1");
}
This way it is working perfectly.