2012-02-15 20 views
5

Ho bisogno di recuperare del testo da un oggetto RemoteViews. È possibile per me ottenere il LayoutId, ma non ho idea di come recuperare il testo da un TextView che è in questo RemoteView (vale a dire una notifica).Recupera testo da un oggetto RemoteViews

Anche il RemoteView contiene solo setter, ma non getter, quindi suppongo di dover usare il LayoutId (in qualche modo).

Potete aiutarmi con quello? Grazie!

/edit: Il motivo per cui lo sto chiedendo è perché ho uno AccessibilityService che recupera la notifica. Quindi questo è l'unico modo per recuperare il valore.

/EDIT2: utilizzare questo codice per ricevere la notifica:

@Override 
public void onAccessibilityEvent(AccessibilityEvent event) { 
    if (event.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) { 
     List<CharSequence> notificationList = event.getText(); 
     for (int i = 0; i < notificationList.size(); i++) { 
      Toast.makeText(this.getApplicationContext(), notificationList.get(i), 1).show(); 
     } 
     if (!(parcel instanceof Notification)) { 
      return; 
     } 
     final Notification notification = (Notification) parcel; 
     doMoreStuff(); 

    } 
} 

Con l'oggetto notification mi hanno accesso a un RemoteViews (notification.contentView) e ad una PendingIntent (notification.contentIntent). Per ottenere il layoutId, posso chiamare contentView.getLayoutId()

+0

Probabilmente sarebbe meglio per salvare le informazioni da qualche parte ('SharedPreferences', ecc), e quindi avere sia il' RemoteViews' e la vostra altra codice di accesso alle informazioni da lì. –

+0

Bene, sto usando un 'AccessibilityService' per recuperare la notifica, quindi non posso semplicemente memorizzare il valore da qualche parte, perché la mia applicazione non ha creato la notifica ;-) – Force

+0

Come si ottiene l'ID del layout? Puoi pubblicare il codice che riceve la notifica? –

risposta

4

Tratto da Extract notification text from parcelable, contentView or contentIntent:

Notification notification = (Notification) event.getParcelableData(); 
RemoteViews views = notification.contentView; 
Class secretClass = views.getClass(); 

try { 
    Map<Integer, String> text = new HashMap<Integer, String>(); 

    Field outerFields[] = secretClass.getDeclaredFields(); 
    for (int i = 0; i < outerFields.length; i++) { 
     if (!outerFields[i].getName().equals("mActions")) continue; 

     outerFields[i].setAccessible(true); 

     ArrayList<Object> actions = (ArrayList<Object>) outerFields[i] 
     .get(views); 
     for (Object action : actions) { 
      Field innerFields[] = action.getClass().getDeclaredFields(); 

      Object value = null; 
      Integer type = null; 
      Integer viewId = null; 
      for (Field field : innerFields) { 
       field.setAccessible(true); 
       if (field.getName().equals("value")) { 
        value = field.get(action); 
       } else if (field.getName().equals("type")) { 
        type = field.getInt(action); 
       } else if (field.getName().equals("viewId")) { 
        viewId = field.getInt(action); 
       } 
      } 

      if (type == 9 || type == 10) { 
       text.put(viewId, value.toString()); 
      } 
     } 

     System.out.println("title is: " + text.get(16908310)); 
     System.out.println("info is: " + text.get(16909082)); 
     System.out.println("text is: " + text.get(16908358)); 
    } 
} catch (Exception e) { 
    e.printStackTrace(); 
} 
+0

notification.contentView è deprecato se esiste una soluzione alternativa per estrarre i dati dall'oggetto AccessibilityEvent, per favore aiutatemi. –

0

CommonsWare in this question dice:

... i widget App sono sola scrittura: si può spingere i dati a loro, ma non li può leggere . Invece, quando aggiorni il widget dell'app con il nuovo testo , dovrai memorizzare quel testo da qualche parte, magari in un file .

La sua risposta sembra essere logica.

7

ho proposto una soluzione simile here che utilizza anche riflessione per risolvere il problema, ma in un modo più accessibile. Questa è la mia soluzione. In questo contesto, RemoteViews proviene da una notifica, quindi le prime tre righe possono probabilmente essere ignorate se si dispone già dell'accesso all'oggetto RemoteViews. Il link nella pagina fornisce una spiegazione molto più dettagliata di ciò che sta realmente accadendo. Spero che questo possa aiutare chiunque abbia un problema simile.

public static List<String> getText(Notification notification) 
{ 
    // We have to extract the information from the view 
    RemoteViews  views = notification.bigContentView; 
    if (views == null) views = notification.contentView; 
    if (views == null) return null; 

    // Use reflection to examine the m_actions member of the given RemoteViews object. 
    // It's not pretty, but it works. 
    List<String> text = new ArrayList<String>(); 
    try 
    { 
     Field field = views.getClass().getDeclaredField("mActions"); 
     field.setAccessible(true); 

     @SuppressWarnings("unchecked") 
     ArrayList<Parcelable> actions = (ArrayList<Parcelable>) field.get(views); 

     // Find the setText() and setTime() reflection actions 
     for (Parcelable p : actions) 
     { 
      Parcel parcel = Parcel.obtain(); 
      p.writeToParcel(parcel, 0); 
      parcel.setDataPosition(0); 

      // The tag tells which type of action it is (2 is ReflectionAction, from the source) 
      int tag = parcel.readInt(); 
      if (tag != 2) continue; 

      // View ID 
      parcel.readInt(); 

      String methodName = parcel.readString(); 
      if (methodName == null) continue; 

      // Save strings 
      else if (methodName.equals("setText")) 
      { 
       // Parameter type (10 = Character Sequence) 
       parcel.readInt(); 

       // Store the actual string 
       String t = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel).toString().trim(); 
       text.add(t); 
      } 

      // Save times. Comment this section out if the notification time isn't important 
      else if (methodName.equals("setTime")) 
      { 
       // Parameter type (5 = Long) 
       parcel.readInt(); 

       String t = new SimpleDateFormat("h:mm a").format(new Date(parcel.readLong())); 
       text.add(t); 
      } 

      parcel.recycle(); 
     } 
    } 

    // It's not usually good style to do this, but then again, neither is the use of reflection... 
    catch (Exception e) 
    { 
     Log.e("NotificationClassifier", e.toString()); 
    } 

    return text; 
} 
0

Se si prendono di mira su Android 19+, è possibile utilizzare il seguente codice per ottenere il titolo/testo da un oggetto di notifica senza l'utilizzo di API private.

Notification noty = ...; 
Bundle extras = noty.extras; 
if (extras != null) { 
    String title = extras.getString(Notification.EXTRA_TITLE); 
    String text = extras.getString(Notification.EXTRA_TEXT); 
} 
Problemi correlati