8.加入服务来实现自动更新和时钟功能
新建一个服务类,通过发送Intent来通知AppWidgetProvider:
1 import android.app.AlarmManager; 2 import android.app.IntentService; 3 import android.app.PendingIntent; 4 import android.content.Context; 5 import android.content.Intent; 6 import android.net.ConnectivityManager; 7 import android.widget.Toast; 8 9 import com.android.volley.Request; 10 import com.android.volley.RequestQueue; 11 import com.android.volley.Response; 12 import com.android.volley.VolleyError; 13 import com.android.volley.toolbox.JsonObjectRequest; 14 import com.android.volley.toolbox.Volley; 15 16 import org.json.JSONException; 17 import org.json.JSONObject; 18 19 import java.io.File; 20 import java.io.IOException; 21 import java.util.ArrayList; 22 23 public class UpdateService extends IntentService { 24 25 //这个是用来后台更新数据的,就是只是检查有无新数据的 26 27 private static final String TAG="UpdateService"; 28 private static final String url="http://api.k780.com:88/?app=weather.future&weaid=101270101&appkey=13217&sign=efb0ccae3443e25fe2238e5bb2f83bba&format=json"; 29 private static final int WEATHER_ALARM_CLOCK=3600000; 30 31 private static File configure; 32 private static boolean hasNew; 33 private static ArrayList<WeatherItem> weatherItems=new ArrayList<>(); 34 35 public UpdateService() { 36 super(TAG); 37 hasNew=false; 38 } 39 40 public static void setServiceAlarm(Context context,boolean isOn){ 41 Intent intent=new Intent(context,UpdateService.class); 42 PendingIntent pi=PendingIntent.getService(context,0,intent,0); 43 AlarmManager alarmManager=(AlarmManager)context.getSystemService(ALARM_SERVICE); 44 if(isOn){ 45 alarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis(), WEATHER_ALARM_CLOCK, pi); 46 }else { 47 alarmManager.cancel(pi); 48 pi.cancel(); 49 } 50 } 51 52 @Override 53 protected void onHandleIntent(Intent intent) { 54 ConnectivityManager cm=(ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE); 55 boolean isNetWorkAvailable=cm.getBackgroundDataSetting() && cm.getActiveNetworkInfo()!=null; 56 if(!isNetWorkAvailable){ 57 return; 58 } 59 configure=new File(getFilesDir()+"/"+FileTools.conf); 60 update(); 61 Intent i=new Intent(); 62 i.setAction(WeatherWidgetProvider.UPDATE_DATA); 63 sendBroadcast(i); 64 } 65 66 private void update(){ 67 68 if(!configure.exists()){ 69 Toast.makeText(getApplicationContext(), R.string.fetching, Toast.LENGTH_SHORT).show(); 70 fetchData(); 71 }else{ 72 try{ 73 hasNew = !(DateTools.getDate().equals(FileTools.loadConf(getApplicationContext()))); 74 }catch (IOException e){ 75 e.printStackTrace(); 76 } 77 if(hasNew){ 78 Toast.makeText(getApplicationContext(),R.string.fetching,Toast.LENGTH_SHORT).show(); 79 fetchData(); 80 } 81 } 82 } 83 84 private void fetchData(){ 85 RequestQueue mQueue= Volley.newRequestQueue(getApplicationContext()); 86 mQueue.add(new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() { 87 @Override 88 public void onResponse(JSONObject jsonObject) { 89 //服务器有响应的时候才会调用此方法 90 try { 91 weatherItems = ParseTools.getInstance(jsonObject.toString(),ParseTools.REQUEST_RAW); 92 //保存数据到文件 93 FileTools.saveData(getApplicationContext(),weatherItems); 94 Toast.makeText(getApplicationContext(),"更新完毕",Toast.LENGTH_SHORT).show(); 95 FileTools.saveWidgetData(getApplicationContext(), weatherItems.get(0)); 96 } catch (JSONException | IOException e) { 97 e.printStackTrace(); 98 } 99 } 100 }, new Response.ErrorListener() { 101 @Override 102 public void onErrorResponse(VolleyError volleyError) { 103 Toast.makeText(getApplicationContext(), "获取失败", Toast.LENGTH_SHORT).show(); 104 } 105 })); 106 mQueue.start(); 107 } 108 109 @Override 110 public void onDestroy() { 111 super.onDestroy(); 112 } 113 }
然后onReceive接受:
1 import android.appwidget.AppWidgetManager; 2 import android.appwidget.AppWidgetProvider; 3 import android.content.ComponentName; 4 import android.content.Context; 5 import android.content.Intent; 6 import android.text.format.DateFormat; 7 import android.widget.RemoteViews; 8 9 import org.json.JSONException; 10 11 import java.io.IOException; 12 import java.util.Date; 13 14 //管理所有Widget的类 15 @SuppressWarnings("NullableProblems") 16 public class WeatherWidgetProvider extends AppWidgetProvider { 17 18 public static final String UPDATE_DATA="action.appwidget.SEND_DATA"; 19 public static final String UPDATE_TIME="action.appwidget.UPDATE_TIME"; 20 private static WeatherItem mItem;//这里必须使用静态成员 21 22 @Override 23 public void onReceive(Context context, Intent intent) { 24 RemoteViews rv=new RemoteViews(context.getPackageName(),R.layout.widget_layout); 25 AppWidgetManager appWidgetManager=AppWidgetManager.getInstance(context); 26 ComponentName componentName=new ComponentName(context,WeatherWidgetProvider.class); 27 int[] appWidgetIds=appWidgetManager.getAppWidgetIds(componentName); 28 switch (intent.getAction()){ 29 case UPDATE_DATA: 30 for(int appWidgetId : appWidgetIds){ 31 rv.setTextViewText(R.id.date, mItem.getDate()); 32 rv.setTextViewText(R.id.week,mItem.getWeek()); 33 rv.setTextViewText(R.id.weather,mItem.getWeather()); 34 rv.setTextViewText(R.id.temp,mItem.getTemp_low() + "~" + mItem.getTemp_high() + "℃"); 35 rv.setTextViewText(R.id.wind,mItem.getWind()); 36 appWidgetManager.updateAppWidget(appWidgetId,rv); 37 } 38 break; 39 case UPDATE_TIME: 40 for(int appWidgetId : appWidgetIds){ 41 rv.setTextViewText(R.id.time, DateFormat.format("kk:mm",new Date())); 42 appWidgetManager.updateAppWidget(appWidgetId,rv); 43 } 44 break; 45 } 46 super.onReceive(context, intent); 47 } 48 49 @Override 50 public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { 51 RemoteViews rv; 52 try{ 53 mItem = FileTools.loadWidgetData(context); 54 }catch (IOException | JSONException e){ 55 e.printStackTrace(); 56 } 57 if(mItem != null){ 58 rv = new RemoteViews(context.getPackageName(),R.layout.widget_layout); 59 rv.setTextViewText(R.id.date,mItem.getDate()); 60 }else{ 61 rv = new RemoteViews(context.getPackageName(),R.layout.widget_void_layout); 62 } 63 64 for(int appWidgetId : appWidgetIds){ 65 appWidgetManager.updateAppWidget(appWidgetId,rv); 66 } 67 super.onUpdate(context, appWidgetManager, appWidgetIds); 68 } 69 70 @Override 71 public void onEnabled(Context context) { 72 super.onEnabled(context); 73 TimeService.setTimeAlarm(context,true); 74 UpdateService.setServiceAlarm(context,true); 75 } 76 77 @Override 78 public void onDisabled(Context context) { 79 super.onDisabled(context); 80 TimeService.setTimeAlarm(context,false); 81 UpdateService.setServiceAlarm(context,false); 82 } 83 }
这里面有一个实现时钟功能的Service:
1 import android.app.AlarmManager; 2 import android.app.IntentService; 3 import android.app.PendingIntent; 4 import android.content.Context; 5 import android.content.Intent; 6 7 public class TimeService extends IntentService { 8 private static final String TAG="TimeService"; 9 private static final int TIME_ALARM_CLOCK=1000; 10 11 public TimeService() { 12 super(TAG); 13 } 14 15 public static void setTimeAlarm(Context context, boolean isOn){ 16 Intent intent=new Intent(context,TimeService.class); 17 PendingIntent pi=PendingIntent.getService(context,0,intent,0); 18 AlarmManager alarmManager=(AlarmManager)context.getSystemService(ALARM_SERVICE); 19 if(isOn){ 20 alarmManager.setRepeating(AlarmManager.RTC,System.currentTimeMillis(),TIME_ALARM_CLOCK,pi); 21 }else{ 22 alarmManager.cancel(pi); 23 pi.cancel(); 24 } 25 } 26 27 @Override 28 protected void onHandleIntent(Intent intent) { 29 Intent i = new Intent(); 30 i.setAction(WeatherWidgetProvider.UPDATE_TIME); 31 sendBroadcast(i); 32 } 33 }
当然这些数据必须要在manifest中定义节点:
1 <?xml version="1.0" encoding="utf-8"?> 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 3 package=" " > 4 5 <uses-permission android:name="android.permission.INTERNET"/> 6 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> 7 8 <application 9 android:allowBackup="true" 10 android:icon="@drawable/ic_launcher" 11 android:label="@string/app_name" 12 android:theme="@style/AppTheme" > 13 <activity 14 android:name=".MainActivity" 15 android:label="@string/app_name" > 16 <intent-filter> 17 <action android:name="android.intent.action.MAIN" /> 18 19 <category android:name="android.intent.category.LAUNCHER" /> 20 </intent-filter> 21 </activity> 22 23 <receiver android:name=".WeatherWidgetProvider" android:label="@string/weather"> 24 <intent-filter> 25 <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/> 26 <action android:name="action.appwidget.SEND_DATA"/> 27 <action android:name="action.appwidget.UPDATE_TIME"/> 28 </intent-filter> 29 <meta-data android:name="android.appwidget.provider" 30 android:resource="@xml/widget_info"/> 31 </receiver> 32 <service android:name=".UpdateService"/> 33 <service android:name=".TimeService"/> 34 </application> 35 </manifest>
所有这些东西完成之后Widget效果如下,测试的过程中还是有些Bug:
所有的东西就是这样的,github地址:https://github.com/wylhyz/TimeAndWeather
时间: 2024-10-01 06:02:14