我遇到的问题是,当我创建同一窗口小部件的两个实例时,它们会发生冲突。
当我刷新时,所以当我打电话时
if (WIDGET_LIST_REFRESH.equals (intent.getAction ())) {
仅更新最后一个小部件。
我认为的问题还在于,WidgetConfigureActivity.loadTitlePref
在创建窗口小部件的第二个实例时会更改第一个窗口小部件中的值。
ListWidgetProvider:
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;
import com.widgettwitter.AppIntent;
import com.widgettwitter.R;
/**
* Implementation of App Widget functionality.
* App Widget Configuration implemented in {@link WidgetConfigureActivity WidgetConfigureActivity}
*/
public class ListWidgetProvider extends AppWidgetProvider {
public static final int OPEN_CLICK_TYPE = 1;
private static final String TAG = ListWidgetProvider.class.getName();
private static final String WIDGET_APP_CONFIG = "com.widgettwitter.WIDGET_CONFIG";
public static String WIDGET_TWITTER_NEW = "com.widgettwitter.WIDGET_NEW";
public static String WIDGET_LIST_REFRESH = "com.widgettwitter.WIDGET_REFRESH";
private static String WIDGET_LIST_CLEAR = "com.widgettwitter.WIDGET_CLEAR";
static Context contextApp;
static int appWidgetIdApp;
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Log.v("Class:" + TAG, "onUpdate:" + appWidgetIds.length);
for (int appWidgetId : appWidgetIds)
updateAppWidget(context, appWidgetManager, appWidgetId);
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
contextApp = context;
appWidgetIdApp = appWidgetId;
CharSequence widgetText = WidgetConfigureActivity.loadTitlePref(context, appWidgetId);
Log.v("Class:" + TAG, "updateAppWidget:" + String.valueOf(widgetText));
RemoteViews remoteView = new RemoteViews(context.getPackageName(), R.layout.widget);
remoteView.setTextViewText(R.id.hashtag, widgetText);
Intent intent = new Intent(context, ListWidgetService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));//problem
remoteView.setRemoteAdapter(R.id.widgetListViewTweets, intent);
remoteView.setEmptyView(R.id.widgetListViewTweets, R.id.empty_view_tweets);
final Intent newIntent = new Intent(context, ListWidgetProvider.class);
newIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
newIntent.setAction(ListWidgetProvider.WIDGET_TWITTER_NEW);
PendingIntent newPendingIntent = PendingIntent.getBroadcast(context, appWidgetId, newIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteView.setOnClickPendingIntent(R.id.add, newPendingIntent);
final Intent configIntent = new Intent(context, ListWidgetProvider.class);
configIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
configIntent.setAction(ListWidgetProvider.WIDGET_APP_CONFIG);
PendingIntent configPendingIntent = PendingIntent.getBroadcast(context, appWidgetId, configIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteView.setOnClickPendingIntent(R.id.hashtag, configPendingIntent);
final Intent refreshIntent = new Intent(context, ListWidgetProvider.class);
refreshIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
refreshIntent.setAction(ListWidgetProvider.WIDGET_LIST_REFRESH);
PendingIntent refreshPendingIntent = PendingIntent.getBroadcast(context, appWidgetId, refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteView.setOnClickPendingIntent(R.id.refresh, refreshPendingIntent);
final Intent clearIntent = new Intent(context, ListWidgetProvider.class);
clearIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
clearIntent.setAction(ListWidgetProvider.WIDGET_LIST_CLEAR);
PendingIntent clearPendingIntent = PendingIntent.getBroadcast(context, appWidgetId, clearIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteView.setOnClickPendingIntent(R.id.clear, clearPendingIntent);
final Intent onClickIntent = new Intent(context, ListWidgetProvider.class);
onClickIntent.setAction(AppIntent.ACTION_CLICK_LIST_WIDGET);
onClickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
onClickIntent.setData(Uri.parse(onClickIntent.toUri(Intent.URI_INTENT_SCHEME)));
final PendingIntent onClickPendingIntent = PendingIntent.getBroadcast(context, appWidgetId, onClickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteView.setPendingIntentTemplate(R.id.widgetListViewTweets, onClickPendingIntent);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widgetListViewTweets);
appWidgetManager.updateAppWidget(appWidgetId, remoteView);
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds)
WidgetConfigureActivity.deleteTitlePref(context, appWidgetId);
}
@Override
public void onEnabled(Context context) {
}
@Override
public void onDisabled(Context context) {
}
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
String widgetText = WidgetConfigureActivity.loadTitlePref(context, appWidgetIdApp);
Log.v("Class:" + TAG, "onReceive:" + intent.getAction() + " widgetText:" + widgetText);
if (WIDGET_LIST_REFRESH.equals(intent.getAction())) {
Toast.makeText(contextApp, "Refresh:" + widgetText, Toast.LENGTH_SHORT).show();
ListWidgetViewsFactory.onRefresh();
} else if (WIDGET_APP_CONFIG.equals(intent.getAction())) {
Intent appIntent = new Intent(context, WidgetConfigureActivity.class);
appIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(appIntent);
} else if (WIDGET_LIST_CLEAR.equals(intent.getAction())) {
ListWidgetViewsFactory.onClear();
} else if (WIDGET_TWITTER_NEW.equals(intent.getAction())) {
String text = widgetText.replaceAll("#", "");
Intent appIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://twitter.com/intent/tweet?text=%23" + text + " "));
context.startActivity(appIntent);
} else if (AppIntent.ACTION_CLICK_LIST_WIDGET.equals(intent.getAction())) {
switch (intent.getIntExtra(AppIntent.EXTRA_CLICK_TYPE, -1)) {
case OPEN_CLICK_TYPE:
String id = intent.getStringExtra(AppIntent.EXTRA_ID);
String user = intent.getStringExtra(AppIntent.EXTRA_USERNAME);
user = user.replaceAll("@", "");
Log.v("Class:" + TAG, "ID:" + id + ",User:" + user);
Intent webIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://twitter.com/" + user + "/status/" + id));
context.startActivity(webIntent);
break;
}
}
}
}
ListWidgetViewsFactory:
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.os.AsyncTask;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews;
import android.widget.RemoteViewsService;
import com.widgettwitter.AppIntent;
import com.widgettwitter.R;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
class ListItem {
public String id, ch, fullname, username, timestamp, text, photo;
}
public class ListWidgetViewsFactory implements RemoteViewsService.RemoteViewsFactory {
private static final String TAG = ListWidgetViewsFactory.class.getName();
private static Context contextApp = null;
private static int appWidgetIdApp;
private static AppWidgetManager appWidgetManager = null;
private static RemoteViews remoteViewWidget = null;
public static ArrayList<ListItem> listItemList = new ArrayList<ListItem>();
public static String ultimeTwitter = "";
private static String url;
static String widgetText;
static Boolean tag = false;
public ListWidgetViewsFactory(Context context, Intent intent) {
contextApp = context;
appWidgetIdApp = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
widgetText = WidgetConfigureActivity.loadTitlePref(context, appWidgetIdApp);
Log.v("Class:" + TAG, widgetText);
String query = String.valueOf(widgetText);
if (query.contains("#")) {
widgetText = query.replaceAll("#", "");
url = "https://twitter.com/search?f=tweets&q=%23" + widgetText + "&lang=it";
tag = true;
} else {
url = "https://twitter.com/search?f=tweets&q=" + widgetText + "&lang=it";
tag = false;
}
appWidgetManager = AppWidgetManager.getInstance(context);
remoteViewWidget = new RemoteViews(context.getPackageName(), R.layout.widget);
}
@Override
public void onCreate() {
Log.v("Class:" + TAG, "onCreate:" + widgetText);
remoteViewWidget.setTextViewText(R.id.hashtag, "Init");
remoteViewWidget.setViewVisibility(R.id.progressBar, View.VISIBLE);
appWidgetManager.updateAppWidget(appWidgetIdApp, remoteViewWidget);
new Html().execute();
}
@Override
public void onDataSetChanged() {
Log.v("Class:" + TAG, "onDataSetChanged:");
}
public static void onClear(){
listItemList.clear();
ultimeTwitter = "";
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIdApp, R.id.widgetListViewTweets);
}
public static void onRefresh(){
remoteViewWidget.setTextViewText(R.id.hashtag, "#Refresh");
remoteViewWidget.setViewVisibility(R.id.progressBar, View.VISIBLE);
appWidgetManager.updateAppWidget(appWidgetIdApp, remoteViewWidget);
new Html().execute();
}
@Override
public void onDestroy() {
if (listItemList != null) listItemList.clear();
}
@Override
public int getCount() {
return listItemList.size();
}
@Override
public int getViewTypeCount() {
return 1;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public RemoteViews getLoadingView() {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public RemoteViews getViewAt(int position) {
Log.v("Class:" + TAG, "getViewAt:" + position);
final RemoteViews remoteView = new RemoteViews(contextApp.getPackageName(), R.layout.list_row);
ListItem listItem = listItemList.get(position);
URL url = null;
try {
url = new URL(listItem.ch);
} catch (MalformedURLException e) {
e.printStackTrace();
}
Bitmap bmp = null;
try {
bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
bmp = getCroppedBitmap(bmp);
remoteView.setImageViewBitmap(R.id.ch, bmp);
remoteView.setTextViewText(R.id.name, listItem.fullname);
remoteView.setTextViewText(R.id.username, listItem.username);
remoteView.setTextViewText(R.id.timestamp, listItem.timestamp);
remoteView.setTextViewText(R.id.text, listItem.text);
/*if (listItem.photo != "") {
try {
url = new URL(listItem.photo);
} catch (MalformedURLException e) {
e.printStackTrace();
}
bmp = null;
try {
bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
remoteView.setViewVisibility(R.id.photo, View.VISIBLE);
remoteView.setImageViewBitmap(R.id.photo, bmp);
}*/
final Intent openIntent = new Intent();
openIntent.putExtra(AppIntent.EXTRA_CLICK_TYPE, ListWidgetProvider.OPEN_CLICK_TYPE);
openIntent.putExtra(AppIntent.EXTRA_ID, listItem.id);
openIntent.putExtra(AppIntent.EXTRA_USERNAME, listItem.username);
remoteView.setOnClickFillInIntent(R.id.widgetItemContainer, openIntent);
return remoteView;
}
public Bitmap getCroppedBitmap(Bitmap bitmap) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
// canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2,
bitmap.getWidth() / 2, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
//Bitmap _bmp = Bitmap.createScaledBitmap(output, 60, 60, false);
//return _bmp;
return output;
}
private static class Html extends AsyncTask<Void, Void, Void> {
private JSONArray array = new JSONArray();
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Void doInBackground(Void... params) {
try {
// Connect to the web site
Document doc = Jsoup.connect(url).get();
// Using Elements to get the Meta data
Elements mElementDataSize = doc.select("div[class=content]");
// Locate the content attribute
int mElementSize = mElementDataSize.size();
for (int i = 0; i < mElementSize; i++) {
JSONObject obj = new JSONObject();
Elements mElementId = doc.select("li[class=js-stream-item stream-item stream-item]").eq(i);
String mId = mElementId.attr("data-item-id");
Elements mElementAvatar = doc.select("img[class=avatar js-action-profile-avatar]").eq(i);
String mAvatar = mElementAvatar.attr("src");
Elements mElementFullName = doc.select("strong[class=fullname show-popup-with-id u-textTruncate]").eq(i);
String mFullName = mElementFullName.text();
Elements mElementUsername = doc.select("span[class=username u-dir u-textTruncate]").eq(i);
String mUsername = mElementUsername.text();
Elements mElementTimestamp = doc.select("span[class=_timestamp js-short-timestamp js-relative-timestamp]").eq(i);
String mTimestamp = mElementTimestamp.text();
Elements mElementText = doc.select("p[class=TweetTextSize js-tweet-text tweet-text]").eq(i);
String mText = mElementText.text();
Elements mElementPhoto = doc.select("div[class=AdaptiveMedia-photoContainer js-adaptive-photo]").eq(i);
String mPhoto = mElementPhoto.attr("data-image-url");
try {
obj.put("id", mId);
obj.put("avatar", mAvatar);
obj.put("fullname", i + ") " + mFullName);
obj.put("username", mUsername);
obj.put("timestamp", mTimestamp);
obj.put("text", mText);
obj.put("photo", mPhoto);
array.put(obj);
} catch (JSONException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
populateListItem(array);
}
private void populateListItem(JSONArray array) {
int id = array.length() - 1;
if (!ultimeTwitter.equals("")) {
for (int i = array.length() - 1; i >= 0; i--) {
try {
JSONObject o = array.getJSONObject(i);
if (o.getString("id").equals(ultimeTwitter)) {
id = i - 1;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
for (; id >= 0; id--) {
ListItem listItem = new ListItem();
try {
JSONObject o = array.getJSONObject(id);
Log.v("Class:" + TAG, "populateListItem" + String.valueOf(array.getJSONObject(id)));
ultimeTwitter = o.getString("id");
listItem.id = o.getString("id");
listItem.fullname = o.getString("fullname");
listItem.username = o.getString("username");
listItem.timestamp = "· " + o.getString("timestamp");
listItem.text = o.getString("text");
listItem.ch = o.getString("avatar");
listItem.photo = o.getString("photo");
} catch (JSONException e) {
e.printStackTrace();
}
listItemList.add(listItem);
}
String str = tag ? "#" : "";
remoteViewWidget.setTextViewText(R.id.hashtag, str + String.valueOf(widgetText)+" ("+listItemList.size()+")");
remoteViewWidget.setViewVisibility(R.id.progressBar, View.INVISIBLE);
appWidgetManager.updateAppWidget(appWidgetIdApp, remoteViewWidget);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIdApp, R.id.widgetListViewTweets);
Log.v("Class:" + TAG, "TweetProvider:onPostExecute");
}
}
}
答案 0 :(得分:1)
您要将应用程序窗口小部件ID保存在静态变量中,因此在快速创建两个窗口小部件之后,在ListWidgetProvider中,静态appWidgetId将具有最后一个窗口小部件的值,该用户将在Launcher上占据一席之地。问题在于静态变量在所有类实例中都具有相同的值。那么我们有什么:在执行两个asynctask之后,它将更新最后一个窗口小部件,因为第一个窗口小部件的asynctask仍在执行,并且如果第二个窗口小部件的asynctask仍在更新。要使其正常工作,请将其设置为非静态字段,然后通过 ListWidgetService 在 ListWidgetViewsFactory 中传递应用小部件ID。是的,您需要删除所有使用该静态变量的静态方法,您可以通过 ListWidgetService 进行相同的操作,这些操作将触发 ListWidgetViewsFactory 并执行某些操作,例如 REFRESH ,清除。
当我检查您的代码时,您可以删除asynctask,并通过appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.widgetListViewTweets)
更新窗口小部件,并在 onDataSetChanged()中通过网络请求并填充窗口小部件。这个想法是 onDataSetChanged()在绑定线程(非主线程)上工作,因此可以安全地使用它。还要检查此回调图,实际上,如果您将当前线程记录在RemoteViewFactory回调中,则您会看到只有onCreate()在主线程上