Sharedpreferences does not work with appWidgetProvider (getApplicationContext is undefined) - android

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

Related

Receiving more shared preferences than should exist when creating new widget

I am constructing widgets which give you the best currency rate for the values you choose. On the homePage, when I click on widgets and select the widget I want to create, the WidgetConfigure Application should launch.
However, it crashes before the configure page even launches and I get this error:
java.lang.RuntimeException:java.lang.IndexOutOfBoundsException: Index: 2, Size: 2. This is the code it refers to:
// Set the currencies for each object
for(String currency: preferredCurrencies){
currencyObjects.get(currencyCount).setCurrencyType(currency);
currencyCount+=1;
}
The code is in one of my widget methods responsible for updating it.
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int appWidgetId, List<CurrencyObject> currencyObjects, Intent clickIntent) {
theAppWidgetManager = appWidgetManager;
// There may be multiple widgets active, so update all of them
// Get the preferred Currencies
Set<String> preferredCurrencies = AppWidgetConfigure.loadCurrencyPref(context,appWidgetId);
// 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){
currencyObjects.get(currencyCount).setCurrencyType(currency);
currencyCount+=1;
}*
}
else{
for(CurrencyObject curObj:currencyObjects){
curObj.setCurrencyType("EUR");
}
}
currencyCount = 0;
}
In my widget configure class I have these methods, where I set the preferredCurrencies:
private static final String PREFS_NAME = "change.Widgets";
private static final String PREF_PREFIX_KEY = "appwidget_";
int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
private List<String> currencies = new ArrayList<>();
private int checkCounter;
private Set<String> chosenCurrencies = new TreeSet<>();
static void saveCurrencyPref(Context context, int appWidgetId, Set<String> chosenCurrencies) {
SharedPreferences.Editor prefs = context.getSharedPreferences(PREFS_NAME, 0).edit();
prefs.putStringSet(PREF_PREFIX_KEY + appWidgetId, chosenCurrencies);
prefs.apply();
}
static void deleteCurrencyPref(Context context, int appWidgetId) {
SharedPreferences.Editor prefs = context.getSharedPreferences(PREFS_NAME, 0).edit();
prefs.remove(PREF_PREFIX_KEY + appWidgetId);
prefs.apply();
}
public static Set<String> loadCurrencyPref(Context context, int appWidgetId) {
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, 0);
Set chosenCurrencies = prefs.getStringSet(PREF_PREFIX_KEY + appWidgetId, null);
return chosenCurrencies;
}
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Find the widget id from the intent.
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
mAppWidgetId = extras.getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
}
// If this activity was started with an intent without an app widget ID, finish with an error.
if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
finish();
return;
}
// Set the result to CANCELED. This will cause the widget host to cancel
// out of the widget placement if the user presses the back button.
setResult(RESULT_CANCELED);
// Create the layout with the checkboxes and the Button.
setContentView(R.layout.widget_configure);
LinearLayout ll = (LinearLayout) findViewById(R.id.configure_layout);
TextView txt = new TextView(this);
txt.setText("Must have: " + Integer.toString(checkBoxLimit) + " checkboxes");
ll.addView(txt);
// Create the checkboxes
currencies.addAll(Arrays.asList(getResources().getStringArray(R.array.currency_array)));
for(String item:currencies){
CheckBox ch = new CheckBox(this);
ch.setText(item);
ll.addView(ch);
ch.setOnCheckedChangeListener((cb, isChecked)->{
//If it's checked and more than the allowed limit, don't consider it
if(isChecked){
if(checkCounter>=checkBoxLimit){
cb.setChecked(false);
Toast.makeText(this, txt.getText(), Toast.LENGTH_SHORT).show();
}
// If it's within the allowed limit, add to list of chosenCurrencies.
else{
checkCounter+=1;
chosenCurrencies.add(cb.getText().toString());
}
}
// If its, unchecked remove the currency from the list of chosenCurrencies.
else{
checkCounter-=1;
chosenCurrencies.remove(cb.getText().toString());
}
});
}
// Create the button
Button btn = new Button(this);
btn.setText(R.string.apply);
ll.addView(btn);
// Finish this
//Launch the widget once the button is pressed
btn.setOnClickListener(v->{
//If User selects right amount of checkboxes
if(checkBoxLimit == checkCounter){
final Context context = AppWidgetConfigure.this;
// delete the previous currencies that existed there for that widget Id
deleteCurrencyPref(context, mAppWidgetId);
// Save the preferences
saveCurrencyPref(context, mAppWidgetId, chosenCurrencies);
// It is the responsibility of the configuration activity to update the app widget
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int[] oneIdList = new int[1];
oneIdList[0] = mAppWidgetId;
//Update the current type of widget
widget.onUpdate(context, appWidgetManager, oneIdList);
// Make sure we pass back the original appWidgetId
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);
finish();
}
else{
Toast.makeText(this, txt.getText(), Toast.LENGTH_SHORT).show();
}
});
}
// Set the currencies for each object
for (String currency : preferredCurrencies) {
if (currencyCount >= currencyObjects.size()) {
return
}
currencyObjects.get(currencyCount).setCurrencyType(currency);
currencyCount++;
}
your app crash because you want to get a invalid item of list. ex your list have 2 items but you call list.get(2)

Android widget becomes unresponsive after random amounts of time pass

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>

Allowing icon to change from user input

I am allowing the user to change the icon in the class Personalize by sending a request code holding an image from a user gallery.
The setIconImageinWidget() method sends the result here (in Drag_and_Drop_App):
else if(requestCode == RESULT_ICON){
byte[] byteArray = data.getByteArrayExtra("myIconBitmap");
Bitmap myIcon = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
setBackgroundImageForIcon(myIcon);
Log.d("Drag_and_Drop_App", "Icon is set");
}
}
Here is the setBackgroundImageForIcon method:
#SuppressLint("NewApi")
private void setBackgroundImageForIcon(Bitmap bitmap) {
ImageView ivICON = (ImageView) findViewById(R.id.bwidgetOpen);
Drawable dq = new BitmapDrawable(getResources(), bitmap);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
ivICON.setImageDrawable(dq);
} else {
ivICON.setImageDrawable(dq);
Log.d("Drag_and_Drop_App", "Icon is set");
}
}
This returns no errors but the icon is not changed at all based on whatever picture the user chooses to use.
After looking around a while I realized that I would have to change the app widget provider section of my coding here:
package com.example.awesomefilebuilderwidget;
IMPORTS
public class AFBWidget extends AppWidgetProvider{
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// TODO Auto-generated method stub
super.onUpdate(context, appWidgetManager, appWidgetIds);
Random r = new Random();
int randomInt = r.nextInt(1000000000);
String rand = String.valueOf(randomInt);
final int N = appWidgetIds.length;
for (int i = 0; i < N; i++){
int awID = appWidgetIds[i];
RemoteViews v = new RemoteViews(context.getPackageName(), R.layout.widget);
v.setTextViewText(R.id.tvwidgetUpdate, rand);
Intent configIntent = new Intent(context, Drag_and_Drop_App.class);
PendingIntent configPendingIntent = PendingIntent.getActivity(context, 0, configIntent, PendingIntent.FLAG_UPDATE_CURRENT);
v.setOnClickPendingIntent(R.id.bwidgetOpen, configPendingIntent);
//me trying to set the Bitmap from the above classes somehow... v.setImageViewBitmap(R.id.bwidgetOpen, R.id.);
appWidgetManager.updateAppWidget(awID, v);
}
}
#Override
public void onDeleted(Context context, int[] appWidgetIds) {
// TODO Auto-generated method stub
super.onDeleted(context, appWidgetIds);
Toast.makeText(context, "Thanks for checking us out!", Toast.LENGTH_SHORT).show();
}
}
And the imageView I am changing is this:
<ImageView
android:id="#+id/bwidgetOpen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_launcher"
android:contentDescription="#string/desc"/>
in Widget.xml
How can I change my Widget Provider so that it will allow the changing of the icon?
I know this is a lot to read but any help is apperciated!
UPDATED:
#SuppressLint("NewApi")
private void setBackgroundImageForIcon(Bitmap bitmap) {
Log.d("Drag_and_Drop_App", "Icon...");
ImageView ivICON = (ImageView) findViewById(R.id.bwidgetOpen);
BitmapDrawable dq = new BitmapDrawable(getResources(), bitmap);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
// ivICON.setImageDrawable(dq);
ivICON.setImageResource(R.drawable.pattern1);
} else {
// ivICON.setImageDrawable(dq);
ivICON.setImageResource(R.drawable.pattern1);
Log.d("Drag_and_Drop_App", "Icon is set");
}
}

Android appwidget click not working

Gosh, there must be a thousand different tutorials on android appwidgets and even more questions here, but I just cannot figure out why mine isn't working. sigh
Rhetorical question: why can't the code be the same here as just about every other object with the setOnClickListener (new new Button.OnClickListener() { // do stuff }...
Anyway, my widget shows up on the screen and the labels are correct, but when I tap on the widget, nothing happens. I've put breakpoints in all the places where I think something would happen, but nothing is being executed.
Question 1: What code is executed after a widget is tapped?
My widget doesn't really update when it is tapped. Rather, it just executes some code in the rest of my program. It just makes some networking http and/or socket server commands. Also, my widget is configured with an activity before it is placed on the desktop.
Here's the manifest:
<receiver android:name="PhcaAppWidgetProvider" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.skipmorrow.phca.PhcaAppWidgetProvider.WIDGET_CLICKED" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/phca_widget_info" />
</receiver>
Here's the widget configurator activity
private Activity act;
private static ListView listView;
private static ArrayAdapter<String> adapter;
private ArrayList<String> actionList;
private final String widgetPageName = "_widget";
int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
private static final String PREFS_NAME = "PHCA";
private static final String PREF_PREFIX_KEY = "prefix_";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("Choose an action for this widget");
actionList = GetActionList();
if (!actionList.isEmpty()) {
listView = getListView();
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, actionList);
setListAdapter(adapter);
}
else {
// no objects on the widget page
}
// Find the widget id from the intent.
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
mAppWidgetId = extras.getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
}
// If they gave us an intent without the widget id, just bail.
if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
finish();
}
}
private ArrayList<String> GetActionList() {
ArrayList<String> l = new ArrayList<String>();
Page p = CommonActivity.GetPageNamed(getApplicationContext(), widgetPageName);
if (p!=null) {
if (p.pageObjects.size()==0) DisplayEmptyPageHelpDialog();
for (int i = 0; i < p.pageObjects.size(); i++) {
l.add(p.pageObjects.get(i).GetParsedMajorLabel(getApplicationContext()).toString());
}
}
else {
CreateWidgetPage();
DisplayEmptyPageHelpDialog();
}
return l;
}
private void CreateWidgetPage() {
Page widgetPage = new Page(getApplicationContext());
widgetPage.setPageName(widgetPageName);
widgetPage.SetPageType("list");
widgetPage.setNote("Widget Page");
widgetPage.setPageTitle("Widget Page");
widgetPage.setImageFilename("");
widgetPage.setTransparentImageOverlayFilename("");
widgetPage.InsertInstanceIntoDatabase(getApplicationContext());
}
private void DisplayEmptyPageHelpDialog() {
Dialog helpDialog = new Dialog(this);
helpDialog.setContentView(R.layout.phca_help_dialog);
helpDialog.setTitle("PHCA Widget");
TextView helpText = (TextView) helpDialog.findViewById(R.id.tvHelpText);
helpText.setText("Your _widget page is empty. Please add an action to the _widget page so it can be used in a widget.");
TextView subTitle = (TextView) helpDialog.findViewById(R.id.tvSubject);
subTitle.setText("PHCA Widget configurator");
helpDialog.show();
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
SharedPreferences.Editor prefs = getSharedPreferences(PREFS_NAME, 0).edit();
prefs.putInt(PREF_PREFIX_KEY + mAppWidgetId, position);
prefs.commit();
// Push widget update to surface with newly set prefix
String majorLabel = CommonActivity.GetPageObjectAtIndex(getApplicationContext(), widgetPageName, position).GetParsedMajorLabel(getApplicationContext()).toString();
String minorLabel = CommonActivity.GetPageObjectAtIndex(getApplicationContext(), widgetPageName, position).GetParsedMinorLabel(getApplicationContext()).toString();
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getApplicationContext());
PhcaAppWidgetProvider.updateAppWidget(getApplicationContext(), appWidgetManager,
mAppWidgetId, majorLabel, minorLabel);
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);
finish();
}
And here's my appwidget provider
public class PhcaAppWidgetProvider extends AppWidgetProvider {
private static final String ACTION_CLICK = "WIDGET_CLICKED";
private final String widgetPageName = "_widget";
private static final String PREFS_NAME = "PHCA";
private static final String PREF_PREFIX_KEY = "prefix_";
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// Get all ids
ComponentName thisWidget = new ComponentName(context,
PhcaAppWidgetProvider.class);
//int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
final int N = appWidgetIds.length;
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
SharedPreferences myPrefs = context.getSharedPreferences(PREFS_NAME, context.MODE_WORLD_WRITEABLE);
Integer objNum = myPrefs.getInt(PREF_PREFIX_KEY + appWidgetId, -1);
if (objNum > -1) {
PageAction pa = (PageAction) CommonActivity.GetPageObjectAtIndex(context, widgetPageName, objNum);
String majorLabel = pa.GetUnparsedMajorLabel(context).toString();
String minorLabel = pa.GetUnparsedMinorLabel(context).toString();
updateAppWidget(context, appWidgetManager, appWidgetId, majorLabel, minorLabel);
}
}
}
#Override
public void onEnabled(Context context) {
Log.d("Widget", "onEnabled");
}
#Override
public void onReceive(Context context, Intent intent) {
String intentAction = intent.getAction();
updateWidgetState(context, intentAction);
if (intentAction.equals(ACTION_CLICK)) {
Bundle extras = intent.getExtras();
Integer appWidgetId = extras.getInt("appwidgetid");
SharedPreferences myPrefs = context.getSharedPreferences(PREFS_NAME, context.MODE_WORLD_WRITEABLE);
Integer objNum = myPrefs.getInt(PREF_PREFIX_KEY + appWidgetId, -1);
if (objNum > -1) {
PageAction pa = (PageAction) CommonActivity.GetPageObjectAtIndex(context, widgetPageName, objNum);
pa.ExecuteActionFromWidgetClick(context);
}
} else {
super.onReceive(context, intent);
}
}
public static void updateWidgetState(Context paramContext, String paramString)
{
RemoteViews localRemoteViews = buildUpdate(paramContext, paramString);
ComponentName localComponentName = new ComponentName(paramContext, PhcaAppWidgetProvider.class);
AppWidgetManager.getInstance(paramContext).updateAppWidget(localComponentName, localRemoteViews);
}
private static RemoteViews buildUpdate(Context ctx, String paramString)
{
RemoteViews views = new RemoteViews(ctx.getPackageName(), R.layout.phca_appwidget);
views.setTextViewText(R.id.majorlabel, "majorLabel");
views.setTextViewText(R.id.minorlabel, "minorLabel");
Intent intent = new Intent(ctx, PhcaAppWidgetProvider.class);
intent.setAction(ACTION_CLICK);
intent.putExtra("appwidgetid", 0);
PendingIntent pendingIntent = PendingIntent.getBroadcast(ctx, 0, intent , 0);
views.setOnClickPendingIntent(R.layout.phca_appwidget, pendingIntent);
if(paramString.equals(ACTION_CLICK))
{
Toast.makeText(ctx, "ACTION_CLICK", Toast.LENGTH_LONG).show();
}
return views;
}
}
When I add the widget and remove it, different intents are passed into the onReceive, so that is working, but nothing when a click happens.
Question 2: Can someone please be so kind as to point out what I did wrong? I pretty followed the tutorials here: http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/appwidget/ExampleAppWidgetProvider.html
Question 3: It would seem that I could put an android:onclick="WidgetClicked" in the layout xml for the widget, but I couldn't figure out where to put the WidgetClicked method. The WidgetProvider seemed logical, but that didn't work for me either. Is there a way to do this in the xml?
DISCLAIMER: the code above is the current state after a day and a half of troubleshooting. It just one iteration of many different tries.
you need to rigister a reciver for widget click as in manifest :
<receiver android:name="MyAppWidgetProvider" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.myname.myapp.MyAppWidgetProvider.ACTION_CLICK" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/my_widget_info" />
</receiver>
AppWidgetProvider.java
public class MyAppWidgetProvider extends AppWidgetProvider {
private static final String ACTION_CLICK = "ACTION_CLICK_WIDGET";
private final String widgetPageName = "_widget";
private static final String PREFS_NAME = "MYAPP";
private static final String PREF_PREFIX_KEY = "prefix_";
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
ComponentName thisWidget = new ComponentName(context,
MyAppWidgetProvider.class);
final int N = appWidgetIds.length;
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
SharedPreferences myPrefs =
context.getSharedPreferences(PREFS_NAME, context.MODE_WORLD_WRITEABLE);
Integer objNum = myPrefs.getInt(PREF_PREFIX_KEY + appWidgetId, -1);
if (objNum > -1) {
PageAction pa = (PageAction) CommonActivity
.GetPageObjectAtIndex(context, widgetPageName, objNum);
String majorLabel = pa.GetUnparsedMajorLabel(context).toString();
String minorLabel = pa.GetUnparsedMinorLabel(context).toString();
updateAppWidget(context, appWidgetManager,
appWidgetId, majorLabel, minorLabel);
}
}
}
#Override
public void onReceive(Context context, Intent intent) {
String intentAction = intent.getAction();
if (intentAction.equals(ACTION_CLICK)) {
updateWidgetState(paramContext, str);
Bundle extras = intent.getExtras();
Integer appWidgetId = extras.getInt("appwidgetid");
SharedPreferences myPrefs =
context.getSharedPreferences(PREFS_NAME, context.MODE_WORLD_WRITEABLE);
Integer objNum = myPrefs.getInt(PREF_PREFIX_KEY + appWidgetId, -1);
if (objNum > -1) {
PageAction pa = (PageAction) CommonActivity
.GetPageObjectAtIndex(context, widgetPageName, objNum);
pa.ExecuteActionFromWidgetClick(context);
}
} else {
super.onReceive(context, intent);
}
}
public static void updateWidgetState(Context paramContext, String paramString)
{
RemoteViews localRemoteViews = buildUpdate(paramContext, paramString);
ComponentName localComponentName = new ComponentName(paramContext, MyAppWidgetProvider.class);
AppWidgetManager.getInstance(paramContext).updateAppWidget(localComponentName, localRemoteViews);
}
private static RemoteViews buildUpdate(Context ctx, String paramString)
{
RemoteViews views =
new RemoteViews(ctx.getPackageName(), R.layout.my_appwidget);
views.setTextViewText(R.id.majorlabel, majorLabel);
views.setTextViewText(R.id.minorlabel, minorLabel);
Intent intent = new Intent(ctx, MyAppWidgetProvider.class);
intent.setAction(ACTION_CLICK);
intent.putExtra("appwidgetid", mAppWidgetId);
PendingIntent configPendingIntentprev = PendingIntent.getBroadcast(ctx, 0, intent , 0);
views.setOnClickPendingIntent(R.layout.my_appwidget, pendingIntent);
if(parmString.equals(ACTION_CLICK))
{
//Toast.maketext("").show();
//
}
return rview;
}
}
see my answer in this post for full example.

Multiple Android Widget instances only updating last widget

I tried solving my problem using this link
update - I figured out that there is something wrong with the setter of the pending intent- every time I click on the imageview- the intent sends the extre details of the last defined widget-
meaning that the other pending intents that where defined on the pre-added widgets were run-over by the newer widgets
I have an app widget that shows a picture chosen by the user.(many widgets- many pictures)
my problem is: no matter which widget on screen I press - only the last added widget gets updated:
here is my code
My Widget xml provider Code
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="#layout/widget_Test"
android:minHeight="146dip"
android:minWidth="146dip"
android:updatePeriodMillis="0" />
My Manifest xml code
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.BIND_REMOTEVIEWS" >
</uses-permission>
<application
android:icon="#drawable/icon"
android:label="#string/app_name" >
<activity
android:name=".Activities.WidgetConfig"
android:screenOrientation="portrait" >
<!-- prbbly delete this line -->
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</activity>
<!-- Test Widget -->
<receiver
android:name=".Simple.Widget"
android:label="#string/app_widget_Test" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/widget_Test_provider" />
</receiver>
<service android:name=".Simple.Widget$TestWidgetService" />
</application>
</manifest>
Widget provider
public class Widget extends AppWidgetProvider
{
public static String PREFENCES_WIDGET_CONFIGURE = "ActionConfigureWidget";
public static int[] widgets;
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds)
{
Intent svcIntent = new Intent(context, TESTWidgetService.class);
widgets = appWidgetIds;
context.startService(svcIntent);
}
public static class TESTWidgetService extends Service
{
#Override
public void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
// Update the widget
RemoteViews remoteView = buildRemoteView(this);
// Push update to homescreen
Mngr.getInstance().pushUpdate(remoteView,
getApplicationContext(), Widget.class);
// No more updates so stop the service and free resources
stopSelf();
}
public RemoteViews buildRemoteView(Context context)
{
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.widget_TEST);
if (widgets != null)
{
int length = widgets.length;
for (int i = 0; i < length; i++)
{
Intent configIntent = new Intent(context,
WidgetConfig.class);
configIntent.setAction(Widget.PREFENCES_WIDGET_CONFIGURE);
String number = AppWidgetManager.EXTRA_APPWIDGET_ID
+ "number";
configIntent.putExtra(number, length);
String widgetID = AppWidgetManager.EXTRA_APPWIDGET_ID + i;
int id = widgets[i];
configIntent.putExtra(widgetID, id);
PendingIntent runTESTPendingIntent = PendingIntent
.getActivity(context, 0, configIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.TESTWidgetImage,
runTESTPendingIntent);
Mngr controller = Mngr.getInstance();
controller.updateTESTWidget(context, remoteViews);
}
}
return remoteViews;
}
#Override
public void onConfigurationChanged(Configuration newConfig)
{
int oldOrientation = this.getResources().getConfiguration().orientation;
if (newConfig.orientation != oldOrientation)
{
// Update the widget
RemoteViews remoteView = buildRemoteView(this);
// Push update to homescreen
Mngr.getInstance().pushUpdate(remoteView,
getApplicationContext(), Widget.class);
}
}
#Override
public IBinder onBind(Intent arg0)
{
// TODO Auto-generated method stub
return null;
}
}
}
my config activity
public class WidgetConfig extends ListActivity // implements
{
private Bundle m_extras;
private ArrayList<Test> m_tests = null;
private int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
ImageAdapter m_adapter;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.imagelist);
Resources res = getResources();
Mngr mngr = Mngr.getInstance();
mngr.setResources(res);
Context ctx = getApplicationContext();
mngr.setContext(ctx);
getTests();
m_adapter = new ImageAdapter(ctx, R.layout.row, m_tests);
ImageDownloader.Mode mode = ImageDownloader.Mode.CORRECT;
m_adapter.getImageDownloader().setMode(mode);
setListAdapter(m_adapter);
Intent intent = getIntent();
m_extras = intent.getExtras();
}
private void getTests()
{
m_tests = new ArrayList<Test>();
Resources res = getResources();
String[] TestNames = res.getStringArray(R.array.fav_Test_array);
TypedArray imgs = getResources().obtainTypedArray(
R.array.fav_Test_integer);
for (int i = 0; i < TestNames.length; i++)
{
Test o1 = new Test();
String TestName = TestNames[i];
int resID = imgs.getResourceId(i, -1);
o1.setTestName(TestName);
o1.setIMGID(resID);
m_tests.add(o1);
}
imgs.recycle();
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id)
{
ListAdapter adapt = l.getAdapter();
Object obj = adapt.getItem(position);
if (obj != null)
{
Mngr mngr = Mngr.getInstance();
Context context = getApplicationContext();
String key = context.getString(R.string.TestWidget_string) + "_"
+ AppWidgetManager.EXTRA_APPWIDGET_ID;
Test Test = (Test) obj;
String val = Test.getIMGID().toString();
mngr.putString(context, key, val);
updateWidget();
}
super.onListItemClick(l, v, position, id);
}
private void updateWidget()
{
Context ctx = getApplicationContext();
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(ctx);
setResult(RESULT_CANCELED);
if (m_extras != null)
{
Intent resultValue = new Intent();
int numberOfWidgets = m_extras.getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID + "number",
AppWidgetManager.INVALID_APPWIDGET_ID);
for (int i = 0; i < numberOfWidgets; i++)
{
String stringID = AppWidgetManager.EXTRA_APPWIDGET_ID + i;
mAppWidgetId = m_extras.getInt(stringID,
AppWidgetManager.INVALID_APPWIDGET_ID);
/*************************************************************/
/*I Don't really know if I am using this piece of code right */
Uri data = Uri.withAppendedPath(Uri.parse("ABCD"
+ "://widget/id/"), String.valueOf(mAppWidgetId));
resultValue.setData(data);
/*************************************************************/
RemoteViews views = new RemoteViews(ctx.getPackageName(),
R.layout.widget_Test);
Mngr.getInstance().updateTestWidget(ctx, views);
appWidgetManager.updateAppWidget(mAppWidgetId, views);
resultValue.putExtra(stringID, mAppWidgetId);
}
setResult(RESULT_OK, resultValue);
finish();
}
}
}
My Mngr code
public void updateTestWidget(Context context, RemoteViews remoteViews)
{
String key = context.getString(R.string.TestWidget_string) + "_"
+ AppWidgetManager.EXTRA_APPWIDGET_ID;
String s = getString(context, key, "");
if (s != null && s.equals("") == false)
{
int resID = Integer.valueOf(s);
remoteViews.setImageViewResource(R.id.TestWidgetImage, resID);
}
}
public void pushUpdate(RemoteViews remoteView, Context ctx, Class<?> cls)
{
ComponentName myWidget = new ComponentName(ctx, cls);
AppWidgetManager manager = AppWidgetManager.getInstance(ctx);
manager.updateAppWidget(myWidget, remoteView);
}
The problem isn't your configActivity, the problem is in your widgetProvider. I had the same problem as you did but solved using the link you specified. You need to set the "hacked" intent on your configIntent in buildRemoteView.
I had the same problem when I tested my application on emulator of 2.2 or 2.3 version. On a real device everything should work fine. Moreover, in my case emulator 4.0 worked properly. In any case I recommend you to test it on a real device.

Categories

Resources