프로그래밍/안드로이드

안드로이드 - app widget 버튼이 동작을 안해요 해결법

가카리 2014. 1. 11. 12:52
반응형

출처 : http://stackoverflow.com/questions/6684982/android-widget-buttons-stop-working

 

내용을 번역 한 것입니다.

 

저는 안드로이드 앱 개발 하고있는데요 버튼이 있는 widget이에요.

 

뭔가 일어났을때 이 버튼은 가끔 멈추는데요. 예를들어서 핸드폰의 언어설정을 바꾼다거나할때요. 저는 shared preferences를 사용하는데

 

요 그래서 만약에 유저가 앱을 재설치할때(언인스톨 없이) 버튼은 다시 동작하네요.

 

제가 알아낸것은 저의 AppWidgetProvider  클래스가 적절하게 만들어진게 아닌것 같아요.

 

저는 AppWidgetProvider으로부터 인스턴트를 만든 Call1 클래스에서 토스트메시지를 더했는데요. 그러나 이게 보이지가 않네요.

 

UpdateService.java 는 단지 preference를 얻고 위젯의 출력을 커스터마이징했어요 그래서 저는 이게 저의 문제랑 관련됬다고 생각 안해요.

 

Main.java 은 오직 스피너와 preference 저장만 구성되있는데요. 만약에 스피너에서 컴퓨터 선택하면 텍스트메시지가 컴퓨터선택함 으로 바뀌는것을 해요. 이것 또한 제가 언어 설정 바꿨을때 사라지네요. 물론 이미지도요. 그래서 저는 UpdateService.java 는 괜찮은것 같아요.

 

I have an Android application with a widget, that has buttons. This code works.

The buttons on the widget stop working when something happens, such as changing the language of the phone. I use shared preferences, so if the user reinstalls the app (without uninstalling), the buttons are working again and the settings remain the set ones.

  • I have noticed the Intents in my AppWidgetProvider class (code beneath this analysis) are not fired appropriately.
  • I added a Toast message to the Call1 class instantiated from AppWidgetProvider, but it doesn't display.
  • My UpdateService.java is just getting the set preferences and customizing the widget's appearance, so I don't think it could possibly be related to my issue.
  • My Main.java file merely consists of spinners and saves shared preferences, which means I select "Computer" in a spinner, so that the "Computer" text appears on the widget. It also does not disappear when I change the language of the phone, and neither do images. Therefore, I believe UpdateService.java must be ok.

Here is the AppWidgetProvider class:

 

여기 AppWidgetProvider class에요.

 

public class HelloWidget extends AppWidgetProvider {

 

    public static String ACTION_WIDGET_CONFIGURE = "ConfigureWidget";

    public static String ACTION_WIDGET_CONFIGURE2 = "ConfigureWidget";

    public static String ACTION_WIDGET_RECEIVER = "ActionReceiverWidget";

    public static String ACTION_WIDGET_RECEIVER2 = "ActionReceiverWidget";

    private static final int REQUEST_CODE_FOUR = 40;

    private static final int REQUEST_CODE_FIVE = 50;

    private static final int REQUEST_CODE_SIX = 60;

    private static final int REQUEST_CODE_SEVEN = 70;

    private static final int REQUEST_CODE_EIGHT = 80;

 

    @Override

    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

        context.startService(new Intent(context, UpdateService.class));

        //Intent widgetUpdateIntent = new Intent(context, UpdateService.class);

        //context.startService(widgetUpdateIntent );

 

         RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetmain2);

 

         //P1 starts Call1.class

         Intent configIntent4 = new Intent(context, Call1.class);

         configIntent4.setAction(ACTION_WIDGET_CONFIGURE);

         PendingIntent configPendingIntent4 = PendingIntent.getActivity(context, REQUEST_CODE_FOUR, configIntent4, 0);

         remoteViews.setOnClickPendingIntent(R.id.ImageView01, configPendingIntent4);

 

         //P2 starts Call2.class

         Intent configIntent5 = new Intent(context, Call2.class);

         configIntent5.setAction(ACTION_WIDGET_CONFIGURE);

         PendingIntent configPendingIntent5 = PendingIntent.getActivity(context, REQUEST_CODE_FIVE, configIntent5, 0);

         remoteViews.setOnClickPendingIntent(R.id.ImageView02, configPendingIntent5);

 

         //P3 starts Call3.class

         Intent configIntent6 = new Intent(context, Call3.class);

         configIntent6.setAction(ACTION_WIDGET_CONFIGURE);

         PendingIntent configPendingIntent6 = PendingIntent.getActivity(context, REQUEST_CODE_SIX, configIntent6, 0);

         remoteViews.setOnClickPendingIntent(R.id.ImageView03, configPendingIntent6);

 

         //P4 starts Call4.class

         Intent configIntent7 = new Intent(context, Call4.class);

         configIntent7.setAction(ACTION_WIDGET_CONFIGURE);

         PendingIntent configPendingIntent7 = PendingIntent.getActivity(context, REQUEST_CODE_SEVEN, configIntent7, 0);

         remoteViews.setOnClickPendingIntent(R.id.ImageView04, configPendingIntent7);

 

         //P5 starts Call5.class

         Intent configIntent8 = new Intent(context, Call5.class);

         configIntent8.setAction(ACTION_WIDGET_CONFIGURE);

         PendingIntent configPendingIntent8 = PendingIntent.getActivity(context, REQUEST_CODE_EIGHT, configIntent8, 0);

         remoteViews.setOnClickPendingIntent(R.id.ImageView05, configPendingIntent8);

 

         appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);

   }

 

    @Override

    public void onReceive(Context context, Intent intent) {

 

        final String action = intent.getAction();

        if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action))

        {

            final int appWidgetId = intent.getExtras().getInt(

                    AppWidgetManager.EXTRA_APPWIDGET_ID,AppWidgetManager.INVALID_APPWIDGET_ID);

            if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID)

            {

                this.onDeleted(context, new int[] { appWidgetId });

            }

        }

        else

        {

            if (intent.getAction().equals(ACTION_WIDGET_RECEIVER))

            {

                String msg = "null";

                try {

                    msg = intent.getStringExtra("msg");

                    } catch (NullPointerException e) {

                    //Log.e("Error", "msg = null");

                    }

            }

            super.onReceive(context, intent);

            }

    }

}

 

저는 또한 EditPreferences.java, GlobalVars.java   그리고 별로 의미없는 클래스가 있어요 클래스의 이름은 즉 그 클래스의 의미에요.

다른것은  Widgetmain.java 클래스가 있어요.

 

I also have an EditPreferences.java, GlobalVars.java and some other now meaningless classes. The names of the classes speak for themselves.

One other thing. I also have a Widgetmain.java:

 

public class WidgetMain extends Activity {

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.widgetmain2);

    }

    static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId)

    {

        RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetmain2);

 

          appWidgetManager.updateAppWidget(appWidgetId, remoteViews);

 

    }

}

 

제가 친구의 ZTE 블레이드에 앱 설치 해보니까 적절한 텍스트가 로딩이 안되네요. 단시 한개가 되었는데 string.xml파일에 있는 것만요.

 

제가 앱을 재설치하면 모든 텍스트뷰는 또 잘되요... 즉 저의 HTC 디자이어여서 그런게 아니라 프로그래밍을 잘못 한것 같아요.

 

텍스뷰는 이미 언급했듯이 UpdateService.java에서 SET해요.

 

Edit: How about this:

When I install this app on my colleague's ZTE Blade the textviews on the widget are not loaded with the appropriate text, just with the one determined in the strings.xml.

When I reinstall the app (without uninstalling), the textviews are loaded and everything is fine. This problem doesn't emerge on my HTC Desire HD.

The textviews are load in the aforementioned UpdateService.java like this (part of the code):

 

RemoteViews updateViews = new RemoteViews(this.getPackageName(), R.layout.main);

updateViews.setTextViewText(R.id.widget_textview, name);

ComponentName thisWidget = new ComponentName(this, HelloWidget.class);

AppWidgetManager manager = AppWidgetManager.getInstance(this);

manager.updateAppWidget(thisWidget, updateViews);

 

심지어 name을 static으로 (예를들어 String name="something"으로 해도 첫인스톨때 텍스트뷰가 로딩이 안되요.

 

Even if "name" is static (e.g. String name="Something"), that textview is still not loaded at the first install

 

 

답변!!

 

 

My UpdateService.java is just getting the set preferences and customizing the widget's appearance, so I don't think it could possibly be related to my issue.

 

It is possible it is related, in as much that you could use it to "refresh" the pending intent. I have a similar issue in my appwidget that an image button stops responding to clicks after some random run time (hours).

I found this thread: AppWidget Button onClick stops working

 

UpdateService.java 는 단지 preference를 얻고 위젯의 출력을 커스터마이징했어요 그래서 저는 이게 저의 문제랑 관련됬다고 생각 안해요.

라고 하셨죠?

 

저는 이게 관련됬다고 생각하는데요. 너가 만약에 리프레쉬 pending intent를 사용하면요. 제가 비슷한 문제점을 저의 appwidget에서 있었는

 

데요 저는 AppWidget Button onClick stops working에서 해결책을 찾았어요.

 

인용해서 말을 하자면

 

The pending intent is "burned" after each use. You need to set it again. Or wait for the widget to get refreshed, then it happens, too, but that's probably not the desired way.

 

각 사용한후에 pending intent가 없어져버려요. 그래서 님은 다시 set하는게 필요해요 또는 위젯이 다시 리프레쉬 될때까지 기다려야되요. 물론 이것은 저희가 바라는 방법으로 일어나지 않아요(시스템 재부팅 위젯 재설치때만 일어남)

 

Given that the widget update time normally is set at many hours or days (mine is 86400000 milli seconds) in order to prevent the phone going out of suspend every so many minutes your widget will not often run onUpdate. It is possible that setting the pending intent ALSO in the update service will prevent the problem you describe.Each time the update service runs the pending intent is re-created.

I have today added this possible fix to my appwidget and I have to wait and see if the fix really works, but so far so good.

I added the following code in the update service' loop where it refreshes each widget:

 

위젯 업데이트 타임은 일반적으로 86400000 milli seconds 이상 시간이나 하루에 한번 set이 되요. 이유는 폰의 배터리 문제때문에 그런거죠.

 

즉 이의미는 update service는 님이 겪고있는 문제를 해결하기위해서 항상 pending intent를 set해줘야된다는 사실이에요. 각 update service

 

시간에 pending inten를 재 생성하면되죠.

 

저는 이 방법으로 저의 앱위젯 문제점을 해결했어요. 몇일동안 해보니까 잘되더군요. 즉 지금까지 좋다는 얘기에요. 저는 다음의 코드를

 

update service 루프에 추가해줘야된다고 생각이 드네요.

 

for (int i=0; i<appWidgetIds.length; i++)

{

  appWidgetId=appWidgetIds[i];

 

  /* other stuff to do */

 

  RemoteViews views=new RemoteViews(context.getPackageName(), R.layout.example_appwidget);

 

  /* here you "refresh" the pending intent for the button */

  Intent clickintent=new Intent("net.example.appwidget.ACTION_WIDGET_CLICK");

  PendingIntent pendingIntentClick=PendingIntent.getBroadcast(context, 0, clickintent, 0);

  views.setOnClickPendingIntent(R.id.example_appwidget_button, pendingIntentClick);

  appWidgetManager.updateAppWidget(appWidgetId, views);

 

  /* then tell the widget manager to update */

  appWidgetManager.updateAppWidget(appWidgetId, views);

}

 

추가 댓글

 

1. 와 몇일동안 테스트해보니까 진자 되네요. 저는 이렇게 동작하는 줄 진짜로 몰랐네요 왜냐하면 저는 이문제는 버그나 핸드폰 종특인줄 알았거든요.

 

2. 저도 위 방법으로 해결책을 찾았네요. 이거 찾는데 한달 더걸린것 같아요. 또한 이앱은 안드로이드 마켓에 올렸어요 저에겐 만족할만한

 

해결책입니다.

 

 

반응형