J'ai passé la dernière semaine de travail avec un problème similaire et peut proposer une solution similaire à Tom Taché (à l'aide de la réflexion), mais peut-être un peu plus facile à comprendre. La méthode suivante sera peigne une notification pour n'importe quel texte présent et de renvoyer ce texte en une liste de tableaux, si possible.
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;
}
Parce que c'est probablement ce qui ressemble un peu à de la magie noire, laissez-moi vous expliquer plus en détail. Nous avons d'abord tirer la RemoteViews objet de la notification elle-même. Ceci représente le point de vue à l'intérieur de la notification réel. Pour accéder à ces points de vue, nous avons pour gonfler le RemoteViews objet (qui ne fonctionne que lorsqu'un contexte d'activité est présent) ou utiliser la réflexion. La réflexion va travailler dans les deux cas et c'est la méthode utilisée ici.
Si vous examinez la source pour RemoteViews ici, vous verrez que l'un des membres privés est une liste de tableaux, d'objets d'Action. Cela représente ce qui va être fait à l'opinion une fois qu'ils sont gonflés. Par exemple, après les vues sont créées, setText() sera appelée à un certain point à chaque TextView qui est une partie de la hiérarchie à affecter le bon Chaînes. Ce que nous faisons est d'obtenir l'accès à cette liste d'actions et d'itérer à travers elle. L'Action est définie comme suit:
private abstract static class Action implements Parcelable
{
...
}
Il y a un certain nombre de sous-classes concrètes d'Action définies dans RemoteViews. Celui qui nous intéresse est appelé ReflectionAction et est définie comme suit:
private class ReflectionAction extends Action
{
String methodName;
int type;
Object value;
}
Cette action est utilisée pour assigner des valeurs aux points de vue. Une seule instance de cette classe serait susceptible d'avoir les valeurs {"setText", 10, "contenu de la textview"}. Donc, nous sommes seulement intéressés par les éléments de mActions qui sont "ReflectionAction" objets et affecter un texte d'une certaine façon. Nous pouvons dire à un particulier de "l'Action" est un "ReflectionAction" en examinant le champ "TAG" dans l'Action, ce qui est toujours le premier de lire la valeur de la parcelle. Les balises de 2 représentent ReflectionAction objets.
Après cela, il nous suffit de lire les valeurs de la parcelle selon l'ordre dans lequel ils ont été écrits (voir le lien vers la source, si vous êtes curieux). Nous trouvons toute la chaîne qui est définie avec setText() et de l'enregistrer dans la liste. (setTime() est également inclus, dans le cas où le délai de notification est également nécessaire. Si non, ces lignes peuvent être supprimés en toute sécurité.)
Alors que je généralement s'opposer à l'utilisation de la réflexion dans des cas comme cela, il y a des moments où il est nécessaire. Sauf si il y a un contexte d'activité disponibles, le "standard" méthode ne fonctionne pas correctement, c'est donc la seule option.