Jared Jared - 1 month ago 13
Android Question

Tap on Widget To Open App

I have been trying to open my app through tapping on the widget for weeks but nothing seems to work. I think something about my code makes my situation different of something. My widget is just a list with tasks on it. I will just post entire classes so people can see what is going on.

Could someone please help me with this?

ListProvider:

public class ListProvider implements RemoteViewsService.RemoteViewsFactory {
private ArrayList<ListObject> listObjectList = new ArrayList<ListObject>();
private Context context = null;
private TinyDB tinyDB;

private ArrayList<Integer> checkedPositions = new ArrayList<>();

public ListProvider(Context context, Intent intent) {
this.context = context;

populateWidget();
}

private void populateWidget() {
if(MainActivity.user != null) {

checkedPositions.clear();

for(int i = 0; i < MainActivity.user.getTaskLists().size(); i++){
TaskList taskList = MainActivity.user.getTaskLists().get(i);

listObjectList.add(new ListTitle(taskList.getName()));

for (int j = 0; j < taskList.getTasks().size(); j++) {
ListItem listItem = new ListItem();
listItem.text = taskList.getTasks().get(j).getTitle();
listObjectList.add(listItem);

if(taskList.getTasks().get(j).isChecked()){
//if task is checked, add to checked list
checkedPositions.add(listObjectList.size() - 1);
}
}

listObjectList.add(new ListItem(" "));
}
}else{
loadLastSavedList();
}
}

@Override
public int getCount() {
return listObjectList.size();
}

@Override
public long getItemId(int position) {
return position;
}

/*
*Similar to getView of Adapter where instead of View
*we return RemoteViews
*
*/
@Override
public RemoteViews getViewAt(int position) {
RemoteViews remoteView = new RemoteViews(
context.getPackageName(), R.layout.widget_list_item);

ListObject listObject = listObjectList.get(position);

//get whether item is a item or title
if(listObject.getClass().equals(ListItem.class)) {
//list item
ListItem listItem = (ListItem) listObject;
remoteView.setTextViewText(R.id.title, "");
remoteView.setTextViewText(R.id.text, listItem.text);
}else{
//list title
ListTitle listTitle = (ListTitle) listObject;
remoteView.setTextViewText(R.id.text, "");
remoteView.setTextViewText(R.id.title, listTitle.title);
}

//text size
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());

String textSize = SP.getString(context.getString(R.string.widget_pref_key_text_size), context.getString(R.string.medium));
System.out.println(textSize);
if (textSize.equals(context.getString(R.string.small))) {
//small
remoteView.setTextViewTextSize(R.id.text, TypedValue.COMPLEX_UNIT_SP, 14);
remoteView.setTextViewTextSize(R.id.title, TypedValue.COMPLEX_UNIT_SP, 16);
} else if (textSize.equals(context.getString(R.string.large))) {
//large
remoteView.setTextViewTextSize(R.id.text, TypedValue.COMPLEX_UNIT_SP, 22);
remoteView.setTextViewTextSize(R.id.title, TypedValue.COMPLEX_UNIT_SP, 24);
} else {
//medium, default
remoteView.setTextViewTextSize(R.id.text, TypedValue.COMPLEX_UNIT_SP, 18);
remoteView.setTextViewTextSize(R.id.title, TypedValue.COMPLEX_UNIT_SP, 20);
}

//strikethrough if checked
if(checkedPositions.contains(position)){
remoteView.setInt(R.id.text, "setPaintFlags", Paint.STRIKE_THRU_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
}else{
remoteView.setInt(R.id.text, "setPaintFlags", (~ Paint.STRIKE_THRU_TEXT_FLAG) & Paint.ANTI_ALIAS_FLAG);
}


return remoteView;
}


@Override
public RemoteViews getLoadingView() {
return null;
}

@Override
public int getViewTypeCount() {
return 1;
}

@Override
public boolean hasStableIds() {
return false;
}

@Override
public void onCreate() {
loadLastSavedList();
}

private void loadLastSavedList() {
//load up saved items
tinyDB = new TinyDB(context);
ArrayList<String> strings = tinyDB.getListString(context.getString(R.string.saved_key));
System.out.println(strings.size());

//full up listItems
for(int i = 0; i < strings.size(); i++) {
if(i == 0){
//first object, title
listObjectList.add(new ListTitle(strings.get(i)));
}else if(strings.get(i - 1).equals(" ")){
//title
listObjectList.add(new ListTitle(strings.get(i)));
}else{
//list item
listObjectList.add(new ListItem(strings.get(i)));
}
}
}

@Override
public void onDataSetChanged() {
listObjectList.clear();
populateWidget();

//save list items
ArrayList<String> strings = new ArrayList<>();
for(ListObject listObject: listObjectList){
if(listObject.getClass().equals(ListItem.class)) {
//list item
ListItem listItem = (ListItem) listObject;
strings.add(listItem.text);
}else{
//list title
ListTitle listTitle = (ListTitle) listObject;
strings.add(listTitle.title);
}
}

tinyDB = new TinyDB(context);
tinyDB.putListString(context.getString(R.string.saved_key), strings);
}

@Override
public void onDestroy() {

}

}


WidgetProvider:

public class WidgetProvider extends AppWidgetProvider {

/**
* this method is called every 30 mins as specified on widgetinfo.xml
* this method is also called on every phone reboot
**/
@Override
public void onUpdate(Context context, AppWidgetManager
appWidgetManager, int[] appWidgetIds) {

/*int[] appWidgetIds holds ids of multiple instance
* of your widget
* meaning you are placing more than one widgets on
* your homescreen*/
final int N = appWidgetIds.length;
for (int i = 0; i < N; i++) {
RemoteViews remoteViews = updateWidgetListView(context,
appWidgetIds[i]);

appWidgetManager.updateAppWidget(appWidgetIds[i],
remoteViews);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}

private RemoteViews updateWidgetListView(Context context,
int appWidgetId) {

//which layout to show on widget
RemoteViews remoteViews = new RemoteViews(
context.getPackageName(), R.layout.widget_layout);

//RemoteViews Service needed to provide adapter for ListView
Intent svcIntent = new Intent(context, WidgetService.class);
//passing app widget id to that RemoteViews Service
svcIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
//setting a unique Uri to the intent
//don't know its purpose to me right now
svcIntent.setData(Uri.parse(
svcIntent.toUri(Intent.URI_INTENT_SCHEME)));
//setting adapter to listview of the widget
remoteViews.setRemoteAdapter(appWidgetId, R.id.listViewWidget,
svcIntent);
//setting an empty view in case of no data
remoteViews.setEmptyView(R.id.listViewWidget, R.id.empty_view);

return remoteViews;
}
}


Thanks in advance!

Answer

You do not have any code that tells Android that you are expecting to do anything when the user clicks on a list item.

In getViewAt(), you need to create an Intent, populate it with extras (e.g., to identify the data associated with this list row), and call setOnClickFillInIntent() on the RemoteViews that is supposed to respond to the click event.

Then, in onUpdate() of your AppWidgetProvider, you need to call setPendingIntentTemplate() on the RemoteViews that holds your ListView (or StackView or whatever you are using), where this PendingIntent wraps an Intent to be filled in and invoked when the user taps on an item in that ListView.

This sample app demonstrates this, by creating an app widget that shows a list of 25 Latin words and responding to clicks on each of them.