0

Я разработал виджет несколько лет назад. Виджет прекрасно работает до сих пор. Он не работает нормально в устройствах Android 5.1.1, но он отлично работает в Android 4.4 и более низких версиях. Виджет отображает три числовых значения, заданные операционной системой. Эти значения правильно получены, потому что я могу отображать их вне этого виджета в тестовом приложении, и они обновляются в этом приложении без виджета.Виджет не работает хорошо в Android 5.1, но отлично в 4.1, 4.4 и т. Д.

В андроиде 5.1.1 значок иконки не отображается в меню виджетов, отображается значок иконка по умолчанию для Android. Кроме того, виджет не обновляется !!! Я не знаю, что не так. Мне нужен виджет, который должен работать на устройствах 4.1, 4.4 и 5.1.

Что-то изменилось в виджетах Android 5.1.1, которые должны быть реализованы? Я не могу найти что-нибудь другое в документации

Это мой виджет:

манифеста:

<receiver android:name="com.myapp.CPUWidgetProvider" android:label="@string/app_name" android:icon="@drawable/icon128"> 
      <intent-filter> 
       <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> 
      </intent-filter> 
      <intent-filter> 
       <action android:name="AUTO_UPDATE" /> 
      </intent-filter> 
      <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_provider" /> 
     </receiver> 

     <service android:name="com.myapp.UpdateService"/> 

мой widget_provider.xml файл:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" 
    android:minWidth="40dp" 
    android:minHeight="40dp" 
    android:initialLayout="@layout/widget_layout" 
    android:updatePeriodMillis="0" 
/> 

мой widget_layout. xml файл:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/fondo" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:background="@drawable/widget_background"  
    android:paddingLeft="1dp" 
    android:paddingRight="1dp" 
    android:paddingTop="10dp" 
    android:paddingBottom="10dp"> 

    <TextView 
    android:id="@+id/freq" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:gravity="center" 
    android:text="@string/loading"   
    android:textSize="12sp" 
    android:textColor="#EE08B608" 
    android:layout_weight="1"/>  

    <TextView 
    android:id="@+id/usage" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:gravity="center" 
    android:text="..." 
    android:textSize="12sp" 
    android:textColor="#EE08B608" 
    android:layout_weight="1"/>    

    <TextView 
    android:id="@+id/temp" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:gravity="center" 
    android:text="27ºC 80ºF" 
    android:textSize="11sp" 
    android:textColor="#EE08B608" 
    android:layout_weight="1"/>   
</LinearLayout> 

мой будильник виджет:

public class WidgetAlarm{ 
    private final int ALARM_ID = 0; 
    private final int INTERVAL_MILLIS = 5000; 
    private Context mContext; 

    public WidgetAlarm(Context context){ 
     mContext = context; 
    } 

    public void startAlarm(){  
     Intent alarmIntent = new Intent(CPUWidgetProvider.ACTION_AUTO_UPDATE); 
     PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, ALARM_ID, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT); 
     AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);   
     alarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis(), INTERVAL_MILLIS, pendingIntent); // RTC does not wake the device up 
    } 

    public void stopAlarm(){ 
     Intent alarmIntent = new Intent(CPUWidgetProvider.ACTION_AUTO_UPDATE); 
     PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, ALARM_ID, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT); 
     AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 
     alarmManager.cancel(pendingIntent); 
    } 
} 

мой updateservice:

public class UpdateService extends Service implements SensorEventListener { 
    private SensorManager mSensorManager; 
    private Sensor mTempSensor; 
    double auxBatteryTemp; 
    String systemTemp=null; 
    String systemTempFarenheit=null; 
    String batteryTemp="25"; 
    String batteryTempFarenheit="80"; 
    int processorMaxFreq=-1; 
    DecimalFormatSymbols symbols; 
    DecimalFormat tempDecimalFormat; 
    boolean serviceDestroyed=false; 

    Context ctx; 
    PowerManager pm; 
    RemoteViews remoteViews; 
    ComponentName thisWidget; 

    private BroadcastReceiver mBatInfoReceiver;  //Broadcast receiver for the battery temperature 
    private BroadcastReceiver screenoffReceiver; //Broadcast receiver for stop the alarm when the screen is off 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) {  
     //System.out.println("XXXXX SERVICE START COMMAND"); 

     /* receivers */  
     mBatInfoReceiver = new BroadcastReceiver(){ 
      @Override 
      public void onReceive(Context arg0, Intent intent) { 
       try { 
        auxBatteryTemp = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0); 
        batteryTemp = ""+(int) (auxBatteryTemp/10); 
        auxBatteryTemp=auxBatteryTemp/10; 
        batteryTempFarenheit = ""+(int)(((auxBatteryTemp*((float)9/5))+32)); 
        updateTemperatures(); 
       } catch (Exception e) {e.printStackTrace();} 
      } 
     }; 

     screenoffReceiver = new BroadcastReceiver() { 
      @Override 
      public void onReceive(Context context, Intent intent) { 
       if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { 
        WidgetAlarm widgetAlarm = new WidgetAlarm(context.getApplicationContext()); 
        widgetAlarm.stopAlarm(); 
       } 
       else if(intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { 
        WidgetAlarm widgetAlarm = new WidgetAlarm(context.getApplicationContext()); 
        widgetAlarm.startAlarm(); 
       } 
       return; 
      } 
     }; 

     symbols = new DecimalFormatSymbols(Locale.GERMAN); 
     symbols.setDecimalSeparator('.'); 
     tempDecimalFormat = new DecimalFormat("#.#", symbols); 

     this.ctx = this; 
     pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE); 
     remoteViews = new RemoteViews(ctx.getPackageName(), R.layout.widget_layout); 
     thisWidget = new ComponentName(ctx, CPUWidgetProvider.class); 

     //Temperature sensors 
     mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE); 
     if (Build.VERSION.SDK_INT >= 14) 
      mTempSensor = mSensorManager.getDefaultSensor(13); //13 = Sensor.TYPE_AMBIENT_TEMPERATURE //this constant required Android 4.0 
     else 
      mTempSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_TEMPERATURE); 

     mSensorManager.registerListener(this, mTempSensor, SensorManager.SENSOR_DELAY_FASTEST); 

     //adding receivers 
     registerReceiver(this.mBatInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); 

     IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); 
     filter.addAction(Intent.ACTION_SCREEN_OFF); 
     registerReceiver(screenoffReceiver, filter); 

     //return super.onStartCommand(intent, flags, startId); 
     return Service.START_STICKY; 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     try { 
      mSensorManager.unregisterListener(this); 
      unregisterReceiver(this.mBatInfoReceiver); 
      unregisterReceiver(this.screenoffReceiver); 
      serviceDestroyed=true; 
     } catch (Exception e) {e.printStackTrace();} 
     //System.out.println("XXXXX SERVICE DESTROY"); 
    } 

    @Override 
    public IBinder onBind(Intent arg0) { 
     return null; 
    } 

    @Override 
    public void onAccuracyChanged(Sensor sensor, int accuracy) {} 

    @Override 
    public void onSensorChanged(SensorEvent event) { 
     if (Build.VERSION.SDK_INT >= 14){ 
      if (event.sensor.getType() == 13) { //13 = Sensor.TYPE_AMBIENT_TEMPERATURE //this constant required Android 4.0 
       getTemperature(event); 
      } 
     }else{ 
      if (event.sensor.getType() == Sensor.TYPE_TEMPERATURE) { 
       getTemperature(event); 
      } 
     }  
    } 

    public void getTemperature(SensorEvent event){ 
     float values[] = event.values; 
     if (values.length>0){ 
      systemTemp = ""+(int)values[0]; 
      systemTempFarenheit = ""+(int)((values[0]*((float)9/5))+32); 
      updateTemperatures(); 
     } 
    } 

    public void updateTemperatures(){ 
     if (pm.isScreenOn() && serviceDestroyed==false){                    
      //si hemos podido obtener la temperatura del sistema, la mostramos, si no, mostramos la temperatura de la bateria. 
      if (systemTemp!=null){ 
       remoteViews.setTextViewText(R.id.temp,systemTemp+"ºC"+" "+systemTempFarenheit+"ºF"); 
      } 
      else{ 
       remoteViews.setTextViewText(R.id.temp,batteryTemp+"ºC"+" "+batteryTempFarenheit+"ºF"); 
      } 

      AppWidgetManager.getInstance(ctx).updateAppWidget(thisWidget, remoteViews); 
      //System.out.println("XXXXX SERVICE UPDATE TEMPERATURES"); 
     }  
    } 
} 

мой провайдер приложение виджет:

public class CPUWidgetProvider extends AppWidgetProvider{   
    public static final String ACTION_WIDGET_CLICK = "ActionWidgetClick"; 
    public static final String ACTION_AUTO_UPDATE = "AUTO_UPDATE"; 

    DecimalFormatSymbols symbols; 
    DecimalFormat tempDecimalFormat; 
    int processorMaxFreq=-1; 
    String cpuCurrentFreq=null; 
    int freq = 0; 
    float usage =-1; 
    BufferedReader freqBufferedReader; 
    PowerManager pm; 
    RemoteViews remoteViews; 
    ComponentName thisWidget; 
    WidgetAlarm widgetAlarm; 
    ActivityManager manager; 

    Intent active; 
    PendingIntent actionPendingIntent; 

    @Override 
    public void onDisabled(Context context) { 
     super.onDisabled(context); 
     context.stopService(new Intent(context, UpdateService.class)); 

     //stop alarm 
     widgetAlarm = new WidgetAlarm(context.getApplicationContext()); 
     widgetAlarm.stopAlarm(); 

     //System.out.println("XXXXX onDISABLED"); 
    } 

    @Override 
    public void onDeleted(Context context, int[] appWidgetIds) { 
     super.onDeleted(context, appWidgetIds); 

     //System.out.println("XXXXX onDELETED"); 
    } 

    @Override 
    public void onEnabled(Context context) { 
     super.onEnabled(context); 

     //System.out.println("XXXXX onENABLED"); 
    } 

    @Override 
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { 
     super.onUpdate(context, appWidgetManager, appWidgetIds); 
     if (isMyServiceRunning(context)==false){ 
      context.startService(new Intent(context, UpdateService.class)); 
     } 

     remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout); 
     thisWidget = new ComponentName(context, CPUWidgetProvider.class); 

     //preparamos el evento para cuando el usuario presiona en el widget, ese evento será recibido en onReceive() 
     active = new Intent(context, CPUWidgetProvider.class); 
     active.setAction(ACTION_WIDGET_CLICK); 
     actionPendingIntent = PendingIntent.getBroadcast(context, 0, active, 0); 
     remoteViews.setOnClickPendingIntent(R.id.fondo, actionPendingIntent); 

     AppWidgetManager.getInstance(context).updateAppWidget(thisWidget, remoteViews);  

     // start alarm 
     widgetAlarm = new WidgetAlarm(context.getApplicationContext()); 
     widgetAlarm.startAlarm(); 

     //System.out.println("XXXXX onUPDATE"); 
    }  

    @Override 
    public void onReceive(Context context, Intent intent){ 
     if (intent.getAction().equals(ACTION_WIDGET_CLICK)){ 
      switchWidget(context); 
     }else if(intent.getAction().equals(ACTION_AUTO_UPDATE)){ 

      symbols = new DecimalFormatSymbols(Locale.GERMAN); 
      symbols.setDecimalSeparator('.'); 
      tempDecimalFormat = new DecimalFormat("#.#", symbols);  

      pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 
      remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout); 
      thisWidget = new ComponentName(context, CPUWidgetProvider.class); 

      if (pm.isScreenOn()){ 
       try{     
        freqBufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(new File("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq")))); 
        freq = Integer.valueOf(freqBufferedReader.readLine()).intValue(); 
        freqBufferedReader.close(); 
        freqBufferedReader = null; 
        cpuCurrentFreq=freq/1000 + " Mhz";      
       } 
       catch (Exception Exception){ 
        cpuCurrentFreq=null; 
       }           

       remoteViews.setTextViewText(R.id.freq,cpuCurrentFreq); 

       if (processorMaxFreq==-1) 
        getProcessorMaxFreq(); 

       usage=(float) (freq/processorMaxFreq);     
       remoteViews.setTextViewText(R.id.usage,tempDecimalFormat.format(usage/10.0D)+" %"); 

       //preparamos el evento para cuando el usuario presiona en el widget, ese evento será recibido en onReceive() 
       active = new Intent(context, CPUWidgetProvider.class); 
       active.setAction(ACTION_WIDGET_CLICK); 
       actionPendingIntent = PendingIntent.getBroadcast(context, 0, active, 0); 
       remoteViews.setOnClickPendingIntent(R.id.fondo, actionPendingIntent); 

       AppWidgetManager.getInstance(context).updateAppWidget(thisWidget, remoteViews); 
       //System.out.println("XXXXX UPDATING WIDGET"); 

      } 

     }else{ 
      super.onReceive(context, intent); 
     } 

     //System.out.println("XXXXX onRECEIVE: "+intent.getAction()); 
    } 

    public void switchWidget(Context context){ 
     symbols = new DecimalFormatSymbols(Locale.GERMAN); 
     symbols.setDecimalSeparator('.'); 
     tempDecimalFormat = new DecimalFormat("#.#", symbols);  

     remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout); 
     thisWidget = new ComponentName(context.getPackageName(), CPUWidgetProvider.class.getName()); 
     widgetAlarm = new WidgetAlarm(context.getApplicationContext()); 
     if (isMyServiceRunning(context)==true){ //si el widget está encendido la apagamos 
      context.stopService(new Intent(context, UpdateService.class));   
      widgetAlarm.stopAlarm(); 
      remoteViews.setTextViewText(R.id.freq,""); 
      remoteViews.setTextViewText(R.id.usage,"OFF"); 
      remoteViews.setTextViewText(R.id.temp,""); 
     } 
     else{ //si el widget está apagado lo encendemos 
      context.startService(new Intent(context, UpdateService.class)); 
      widgetAlarm.startAlarm(); 
      remoteViews.setTextViewText(R.id.freq,"-----"); 
      remoteViews.setTextViewText(R.id.usage,"--"); 
      remoteViews.setTextViewText(R.id.temp,""); 
     } 
     AppWidgetManager.getInstance(context).updateAppWidget(thisWidget,remoteViews); 
    } 

    private boolean isMyServiceRunning(Context context) { 
     manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 
     for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { 
      if (UpdateService.class.getName().equals(service.service.getClassName())) { 
       return true; 
      } 
     } 
     return false; 
    } 

    public void getProcessorMaxFreq(){ 
     int freq = 0; 
     try{    
      freqBufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(new File("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq")))); 
      freq = Integer.valueOf(freqBufferedReader.readLine()).intValue(); 
      freqBufferedReader.close(); 
      freqBufferedReader=null; 
      processorMaxFreq=(freq/1000);     
     } 
     catch (Exception e){e.printStackTrace();} 
    } 
} 
+0

Меню виджета управляется отдельными пусковыми установками: не привязано к версии для Android. Есть ли причина, по которой вы не предоставляете «previewImage»? Когда вы говорите «не обновлять», вы имеете в виду, что ваш «UpdateService» не запускается вообще? Или он работает, но виджет не обновляется? – ianhanniballake

+0

Я пробовал с previewImage и без предварительного просмотра. ни один из них не работает. Я имею в виду, что никакие обновления не получаются или, по крайней мере, очень низкие, каждые каждые Х минут. В Android 4.4 и ниже он работает отлично, с обновлениями каждые 5 или 10 секунд. – NullPointerException

ответ

3

this blog post Per и associated bug closed as Working as Intended:

низкие периоды опроса округлены до 60000ms (одна минута)

и вы увидите сообщение LogCat к этому эффекту:

Подозрительно короткий интервал 5000 Миллис; расширение до 60 секунд

На вопрос об альтернативах, post #9 on the bug состояний:

Если вы пытаетесь запустить чаще, чем через каждые 5 секунд, тревоги неправильный способ пойти об этом. Пробуждение устройства, которое часто очень плохо для аккумулятора. Если у вас есть живой пользовательский интерфейс, который необходимо постоянно обновлять, используйте wakelock, а затем планируйте свою деятельность на обработчике. Это фактически больше аккумулятор эффективен, чем установка тревоги каждую секунду.

Помните, что виджеты предназначены для запуска только изредка; самый маленький updatePeriodMillis, который предоставит ОС, составляет 30 минут.

Смежные вопросы