前段时间在做一个Weather Widget,没有自己的Service接口,只有调用google api来实现。google的api还是挺好用的。可以使用google提供的接口获取城市列表和天气信息,天气可以通过好种方式查询,如城市名称,经纬度,邮编。google api 还提供了中文显示。所以用起来很方便。我看过一些weather widget的应用,都做得挺好的,比如过Go Weather 他们用的是经过自己解析的天气;再比如说FancyWidgetPro,是通过
http://weather.weatherbug.com
来获取天气情况的。好了,闲话少说,下面来总结下我在Widget开发中遇到的问题和应该注意的问题。
1、Widget中通过按钮点击进入Activity,这个比较简单。主要是通过RemoteViews的setOnClickPendingIntent时间来实现。请看下面代码:
view plain copy to clipboard print ?
- Intent intent = new Intent(context,WeatherActivity.class);
- intent.setAction(Globals.ACTION_APP_WIDGET_WEATHERACTIVITY);
- PendingIntent pIntent = PendingIntent.getActivity(context, 0, intent, 0);
- views.setOnClickPendingIntent(R.id.weathericon, pIntent);
Intent intent = new Intent(context,WeatherActivity.class); intent.setAction(Globals.ACTION_APP_WIDGET_WEATHERACTIVITY); PendingIntent pIntent = PendingIntent.getActivity(context, 0, intent, 0); views.setOnClickPendingIntent(R.id.weathericon, pIntent);
2、通过Service刷新界面,由于之前没有做过Widget方面的项目,所以在开始使用广播的形式,启动线程。来更新界面,是在是不爽。于是网上查了下,都是用Service来刷新界面的。那么具体如何使用呢?在AppWidgetProvider中设置Intent,并指定其Action,使用RemoteViews的setOnClickPendingIntent方法与具体的控件(weatherDate1)关联;启动Service服务;在继承Service的类中的onStart方法中得到设置的Action,做相应的动作。请看下面代码段:
在继承AppWidgetProvider的类中:
view plain copy to clipboard print ?
- Intent update1 = new Intent(Globals.ACTION_APP_WIDGET_UPDATE_1);
- PendingIntent pendingUpdate1 = PendingIntent.getService(context, 0, update1, 0);
- views.setOnClickPendingIntent(R.id.weatherDate1, pendingUpdate1);
Intent update1 = new Intent(Globals.ACTION_APP_WIDGET_UPDATE_1); PendingIntent pendingUpdate1 = PendingIntent.getService(context, 0, update1, 0); views.setOnClickPendingIntent(R.id.weatherDate1, pendingUpdate1);
启动服务:
view plain copy to clipboard print ?
- context.startService(new Intent(Globals.ACTION_APP_WIDGET_SERVICE));
context.startService(new Intent(Globals.ACTION_APP_WIDGET_SERVICE));
在继承Service的类中:
view plain copy to clipboard print ?
- if(Globals.ACTION_APP_WIDGET_UPDATE_2.equals(action)){
- Log.i(TAG, "update_2");
- updateWeatherInfo(views,1);
- }
if(Globals.ACTION_APP_WIDGET_UPDATE_2.equals(action)){ Log.i(TAG, "update_2"); updateWeatherInfo(views,1); }
以上只是简单的点击刷新操作,那么如果天气要15分钟获取更长的时间刷新界面,那么怎么办呢?必须用到线程,用线程来控制。如果让线程sleep15分钟或者更长时间,会出现ANR的问题。很是麻烦。请看第三点。
3、线程的使用
Ok,怎么避免ANR,网上有详细的说明,请google!不再多说,我也说不明白,哈哈。线程的使用请看下面代码:
view plain copy to clipboard print ?
- private Runnable runnable = new Runnable() {
-
- @Override
- public void run() {
- while (isRunRefresh && refreshTime!=0) {
- Log.i(TAG, "==real time refersh!==");
- try {
- Thread.sleep(refreshTime);
- mHandler.sendEmptyMessage(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- };
-
- private Handler mHandler = new Handler(){
- public void handleMessage(android.os.Message msg) {
- if (msg.what==1000) {
- updateWeatherInfo(views,-1);
- }
- };
- };
private Runnable runnable = new Runnable() { @Override public void run() { while (isRunRefresh && refreshTime!=0) { Log.i(TAG, "==real time refersh!=="); try { Thread.sleep(refreshTime); // 这里做一些耗时的操作 mHandler.sendEmptyMessage(1000); // 发送消息给UI } catch (InterruptedException e) { e.printStackTrace(); } } } }; private Handler mHandler = new Handler(){ public void handleMessage(android.os.Message msg) { if (msg.what==1000) { updateWeatherInfo(views,-1); // 更新消息 } }; };
启动线程:
view plain copy to clipboard print ?
- mThread = new Thread(runnable);
- mThread.start();
mThread = new Thread(runnable); // 主线程中创建子线程 mThread.start();
4、获取xml文件后中文的显示问题
view plain copy to clipboard print ?
- builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
- InputSource inputSource = new InputSource();
- inputSource.setByteStream(stream);
- inputSource.setEncoding("gbk");
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); InputSource inputSource = new InputSource(); inputSource.setByteStream(stream); inputSource.setEncoding("gbk"); // 设置InputSource的编码格式GBK
特此申明:这不是教程,这只是个人总结!欢迎交流。O(∩_∩)O哈哈~