Listing all extras of an Intent - android

For debugging reasons I want to list all extras (and their values) of an Intent. Now, getting the keys isn't a problem
Set<String> keys = intent.getExtras().keySet();
but getting the values of the keys is one for me, because some values are strings, some are boolean... How could I get the values in a loop (looping through the keys) and write the values to a logfile? Thanks for any hint!

Here's what I used to get information on an undocumented (3rd-party) intent:
Bundle bundle = intent.getExtras();
if (bundle != null) {
for (String key : bundle.keySet()) {
Log.e(TAG, key + " : " + (bundle.get(key) != null ? bundle.get(key) : "NULL"));
}
}
Make sure to check if bundle is null before the loop.

This is how I define utility method to dump all extras of an Intent.
import java.util.Iterator;
import java.util.Set;
import android.os.Bundle;
public static void dumpIntent(Intent i){
Bundle bundle = i.getExtras();
if (bundle != null) {
Set<String> keys = bundle.keySet();
Iterator<String> it = keys.iterator();
Log.e(LOG_TAG,"Dumping Intent start");
while (it.hasNext()) {
String key = it.next();
Log.e(LOG_TAG,"[" + key + "=" + bundle.get(key)+"]");
}
Log.e(LOG_TAG,"Dumping Intent end");
}
}

You can do it in one line of code:
Log.d("intent URI", intent.toUri(0));
It outputs something like:
"#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10a00000;component=com.mydomain.myapp/.StartActivity;sourceBounds=12%20870%20276%201167; l.profile=0; end"
At the end of this string (the part that I bolded) you can find the list of extras (only one extra in this example).
This is according to the toUri documentation:
"The URI contains the Intent's data as the base URI, with an additional fragment describing the action, categories, type, flags, package, component, and extras."

private TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tv = new TextView(this);
tv.setText("Extras: \n\r");
setContentView(tv);
StringBuilder str = new StringBuilder();
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
Set<String> keys = bundle.keySet();
Iterator<String> it = keys.iterator();
while (it.hasNext()) {
String key = it.next();
str.append(key);
str.append(":");
str.append(bundle.get(key));
str.append("\n\r");
}
tv.setText(str.toString());
}
}

A Kotlin solution useful for evaluation in debug mode:
// list: List<Pair<String!, Any?>>?
val list = intent.extras?.keySet()?.map { it to (intent.extras?.get(it) ?: "null") }
Log.d("list", list.toString();
That would print the list of all extras in the bundle extras

The get(String key) method of Bundle returns an Object. Your best bet is to spin over the key set calling get(String) on each key and using toString() on the Object to output them. This will work best for primitives, but you may run into issues with Objects that do not implement a toString().

I wanted a way to output the contents of an intent to the log, and to be able to read it easily, so here's what I came up with. I've created a LogUtil class, and then took the dumpIntent() method #Pratik created, and modified it a bit. Here's what it all looks like:
public class LogUtil {
private static final String TAG = "IntentDump";
public static void dumpIntent(Intent i){
Bundle bundle = i.getExtras();
if (bundle != null) {
Set<String> keys = bundle.keySet();
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("IntentDump \n\r");
stringBuilder.append("-------------------------------------------------------------\n\r");
for (String key : keys) {
stringBuilder.append(key).append("=").append(bundle.get(key)).append("\n\r");
}
stringBuilder.append("-------------------------------------------------------------\n\r");
Log.i(TAG, stringBuilder.toString());
}
}
}
Hope this helps someone!

Bundle extras = getIntent().getExtras();
Set<String> ks = extras.keySet();
Iterator<String> iterator = ks.iterator();
while (iterator.hasNext()) {
Log.d("KEY", iterator.next());
}

You could use for (String key : keys) { Object o = get(key); to return an Object, call getClass().getName() on it to get the type, and then do a set of if name.equals("String") type things to work out which method you should actually be calling, in order to get the value?

I noticed in the Android source that almost every operation forces the Bundle to unparcel its data. So if (like me) you need to do this frequently for debugging purposes, the below is very quick to type:
Bundle extras = getIntent().getExtras();
extras.isEmpty(); // unparcel
System.out.println(extras);

Sorry if this is too verbose or too late, but this was the only way I could find to get the job done. The most complicating factor was the fact that java does not have pass by reference functions, so the get---Extra methods need a default to return and cannot modify a boolean value to tell whether or not the default value is being returned by chance, or because the results were not favorable. For this purpose, it would have been nicer to have the method raise an exception than to have it return a default.
I found my information here: Android Intent Documentation.
//substitute your own intent here
Intent intent = new Intent();
intent.putExtra("first", "hello");
intent.putExtra("second", 1);
intent.putExtra("third", true);
intent.putExtra("fourth", 1.01);
// convert the set to a string array
Set Documentation
String[] anArray = {};
Set<String> extras1 = (Set<String>) intent.getExtras().keySet();
String[] extras = (String[]) extras1.toArray(anArray);
// an arraylist to hold all of the strings
// rather than putting strings in here, you could display them
ArrayList<String> endResult = new ArrayList<String>();
for (int i=0; i<extras.length; i++) {
//try using as a String
String aString = intent.getStringExtra(extras[i]);
// is a string, because the default return value for a non-string is null
if (aString != null) {
endResult.add(extras[i] + " : " + aString);
}
// not a string
else {
// try the next data type, int
int anInt = intent.getIntExtra(extras[i], 0);
// is the default value signifying that either it is not an int or that it happens to be 0
if (anInt == 0) {
// is an int value that happens to be 0, the same as the default value
if (intent.getIntExtra(extras[i], 1) != 1) {
endResult.add(extras[i] + " : " + Integer.toString(anInt));
}
// not an int value
// try double (also works for float)
else {
double aDouble = intent.getDoubleExtra(extras[i], 0.0);
// is the same as the default value, but does not necessarily mean that it is not double
if (aDouble == 0.0) {
// just happens that it was 0.0 and is a double
if (intent.getDoubleExtra(extras[i], 1.0) != 1.0) {
endResult.add(extras[i] + " : " + Double.toString(aDouble));
}
// keep looking...
else {
// lastly check for boolean
boolean aBool = intent.getBooleanExtra(extras[i], false);
// same as default, but not necessarily not a bool (still could be a bool)
if (aBool == false) {
// it is a bool!
if (intent.getBooleanExtra(extras[i], true) != true) {
endResult.add(extras[i] + " : " + Boolean.toString(aBool));
}
else {
//well, the road ends here unless you want to add some more data types
}
}
// it is a bool
else {
endResult.add(extras[i] + " : " + Boolean.toString(aBool));
}
}
}
// is a double
else {
endResult.add(extras[i] + " : " + Double.toString(aDouble));
}
}
}
// is an int value
else {
endResult.add(extras[i] + " : " + Integer.toString(anInt));
}
}
}
// to display at the end
for (int i=0; i<endResult.size(); i++) {
Toast.makeText(this, endResult.get(i), Toast.LENGTH_SHORT).show();
}

The Kotlin version of Pratik's utility method which dumps all extras of an Intent:
fun dumpIntent(intent: Intent) {
val bundle: Bundle = intent.extras ?: return
val keys = bundle.keySet()
val it = keys.iterator()
Log.d(TAG, "Dumping intent start")
while (it.hasNext()) {
val key = it.next()
Log.d(TAG,"[" + key + "=" + bundle.get(key)+"]");
}
Log.d(TAG, "Dumping intent finish")
}

Get it as a string separated with "," in Kotlin!
val extras = intent?.extras?.keySet()?.map { "$it: ${intent.extras?.get(it)}" }?.joinToString { it }
based on ruX answer.

If for debugging all you want is a string (sort of implied by the OP but not explicitly stated), simply use toString on the extras Bundle:
intent.getExtras().toString()
It returns a string such as:
Bundle[{key1=value1, key2=value2, key3=value3}]
Documentation: Bundle.toString() (it's unfortunately the default Object.toString() javadoc and as such quite useless here.)

Related

Can Xposed log current method name?

I want to test an application but it's too large to do by static approach.
I started googling. I found a interesting tool called Xposed Framework.
I read a lot of documents / examples. But I cant find the theads about getting method name of application.
My purpose is to log current method name when I press a button in app. Which parameters are sent when the methods are called?
For more information, the application I want to test is a chat application. I want to check that is it secured to use ? Is it true that developers claims the application uses blah blah blah encryption ? Is it real end-to-end encryption?.
According to the large of application, I need some tools to help me analyse this. When I send a message what methods are called ? what values are sent along with ?
If it is opensource you can easily insert a few logs in the source code and recompile. Some code coverage tools allow you to log the executed methods but i am unsure about the parameters (e.g. EMMA coverage).
If it is closed-source then you can do it with Xposed, but it has some challenges. Xposed allows you to hook Java methods, if it is opensource you can lookup the specific methods you want to intercept and print their parameters. If it is closed source, you can always check the method names through decompiling the app with apktool.
Check the Xposed tutorial on how to register hooks. Assuming you created your class that extends XC_MethodHook, the following methods should do the trick for primitive parameters:
#Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
String threadname = Thread.currentThread().getName();
String d = _dateFormat.format(new Date());
Class<?> cls = param.this.getClass();
//Extend XC_MethodHook to receive the mthName in the constructor
//and store it as a static field.
Log.v("MethodInvocation", "[A][" + d + "]"
+ "[" + cls.getName() + "."
+ mthName
+ "(" + args(param) + ")" + " = " + result(param)
+ "]" + " [" + threadname + "]");
}
public boolean shouldPrintContent(Object o) {
if (o.getClass().isPrimitive()
|| o.getClass().getName().contains("java.lang"))
return true;
return false;
}
public String args(MethodHookParam param) {
String args = "";
int counter = 0;
if (param != null) {
for (Object o : param.args) {
if (counter > 0)
args += ",";
// argument can be null
if (o == null) {
args += "null";
} else { // if it is an object lets print its type and content.
args += printclean(o.getClass().getName());
if (shouldPrintContent(o)) {
args += ":" + printclean(o.toString());
} else
args += ":nonPrimitiveOrJavaLang";
}
counter++;
}
}
return args;
}
//avoid identation chars in strings
public String printclean(String str) {
char[] res = str.toCharArray();
for (int i = 0; i < str.length(); i++) {
if (res[i] == '\n' || res[i] == '\r' || res[i] == '\t'
|| res[i] == '[' || res[i] == ']') {
res[i] = '*';
}
}
return String.valueOf(res);
}
public String result(MethodHookParam param) {
String res = "";
Object retobj = param.getResult();
if (retobj == null) {
res += "null";
} else {
res += printclean(retobj.getClass().getName());
if (shouldPrintContent(retobj)) {
res += printclean(retobj.toString());
} else
res += "(nonPrimitiveOrJavaLang)";
}
return res;
}
Note that printing any object is not trivial. Here I printed only known types like primitives or other java.lang objects. More complex objects (including collections) you can try using Gson to represent them but this also comes with limitations (e.g. can't often handle reference loops).
Finally, be careful with what method you hook as hooking and logging methods that are called often will impact the performance of the app.
Good luck!
A new Xposed module called Inspeckage does (among many other useful inspections) what you want to do: you can use it to hook any method and view and even change its input and output.

Cannot assign variable value to a string from extra.getString();

New to android, I'm currently trying to send a String value from one Activity to another. I have looked through several threads like How to use putExtra() and getExtra() for string data for an answer, but I cannot get it to work.
The string I want to send is:
public void golf(View view) {
Intent intent = new Intent(SearchSport.this, EventList.class);
intent.putExtra("type", "golf");
startActivity(intent);
and my receiver looks like
String type;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event_list);
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if ( extras != null)
type = extras.getString("type");
if (type == "golf"){
TextView eventName = (TextView) findViewById(R.id.EOName);
TextView eventTime = (TextView) findViewById(R.id.EOTime);
TextView eventLocation = (TextView) findViewById(R.id.EOLocation);
DatabaseOperations dop = new DatabaseOperations(ctx);
Cursor CR = dop.getInformation(1);
CR.moveToFirst();
eventName.setText(CR.getString(1));
eventTime.setText(CR.getString(7) + " " + CR.getString(8) + ". " + CR.getString(9) + " kl. " + CR.getString(10) + ":" + CR.getString(11));
eventLocation.setText(CR.getString(4));}
else {Toast toast = Toast.makeText(this, "Error in Type.", Toast.LENGTH_LONG);
toast.show();}
I have no Idea what's wrong here. The app displays the toast everytime I test it, instead of filling out the TextViews with the data from my database entry.
EDIT: Code has been changed based on answers, but the problem has not yet been solved. Writing if (type.equals("golf")){} instead of if (type == "golf"){} crashed the app.
EDIT 2: Problem solved! Fixed case sensitivity, used .equals instead of ==, and wrote the receiver as
if(getIntent().hasExtra("Type"))
type = getIntent().getStringExtra("Type");
In the end, it turns out is was the virtual device I used which crashed the app, for as of yet unknown reasons. When tested on an actual android phone, the app works as intented.
Thanks to everyone for their help!
try this
if(getIntent().hasExtra("Type"))
type = getIntent().getStringExtra("Type");
Change the key it is case sensitive :
type = extras.getString("Type");
Key is wrong when try to get String from Intent Extra :
type = extras.getString("type");
Replace with :
type = extras.getString("Type");
Note : Also use equals() instead == for comparing String
if (type.equals("golf")){
1) First keys are case sensitive
2) pass as
Bundle bundle = new Bundle()
bundle.putString("type","golf");
intent.putExtras(bundle);
after that get it using
Bundle received = i.getExtras();
received.getString("type");
As you are passing the value using Extra. You must have to catch that using getStringExtra(); and the Key must be case sensitive.
Intent i = getIntent();
type = i.getStringExtra("Type");

Deleting a word in a String/String Array

So if you are adding in a string, you can just add them via += method(the one i know and using atm). but how can you delete a word in a string/string array?
example: i have a string
String="Monday,Tuesday,Wednesday"
how do you make it into
String="Monday,Wednesday"
any help please?
You could use the replace method.
String sentence = "Monday,Tuesday,Wednesday";
String replaced = sentence.replace("Tuesday,", "");
its easy
just use
yourString = yourString.replaceAll("the text to replace", ""); //the second "" show empty string so the text will get replace by empty string
finally yourString will contain the text u desire Thats it :)
You can use the "public String replace(char oldChar, char newChar)" method if you want to remove "Tuesday" and not the second element
https://stackoverflow.com/questions/16702357/how-to-replace-a-substring-of-a-string
I think, i will use it for simplicity otherwise go to other suggested answer...
Use Arraylist for storing days:
ArrayList<String> days = new ArrayList<String>();
days.add("Monday");
days.add("Tuesday");
days.add("Wednesday");
Use it for creating days string:
public String getDays() {
String daysString = "";
for (int i = 0; i < days.size(); i++) {
if (i != 0)
daysString += ", ";
daysString += days.get(i);
}
return daysString;
}
And whenever you want to remove use
days.remove(1);
or
days.remove("Tuesday");
then again call getDays();
IInd Method if you want to use only string:
String list = "Monday,Tuesday,Wednesday";
System.out.println("New String : " + removeAtIndex(list, 1));
and
public String removeAtIndex(String string, int index) {
int currentPointer = 0;
int lastPointer = string.indexOf(",");
while (index != 0) {
currentPointer = string.indexOf(',', currentPointer) + 1;
lastPointer = string.indexOf(',', lastPointer + 1);
index--;
}
String subString = string.substring(currentPointer,
lastPointer == -1 ? string.length() : lastPointer);
return string.replace((currentPointer != 0 ? "," : "") + subString
+ (currentPointer == 0 ? "," : ""), "");
}
Something like this using a regular expression:
String contents = "Monday,Tuesday,Wednesday";
contents = contents.replaceAll("[\\,]+Tuesday|^Tuesday[\\,]*", "");

How to remove duplicates from ArrayList of type Object? [duplicate]

This question already has answers here:
How to remove duplicates from a list?
(15 answers)
Closed 8 years ago.
I want to remove duplicates from ArrayList of type Alerts where Alerts is a class.
Class Alerts -
public class Alerts implements Parcelable {
String date = null;
String alertType = null;
String discription = null;
public Alerts() {
}
public Alerts(String date, String alertType, String discription) {
super();
this.date = date;
this.alertType = alertType;
this.discription = discription;
}
}
Here is how I added the elements -
ArrayList<Alerts> alert = new ArrayList<Alerts>();
Alerts obAlerts = new Alerts();
obAlerts = new Alerts();
obAlerts.date = Date1.toString();
obAlerts.alertType = "Alert Type 1";
obAlerts.discription = "Some Text";
alert.add(obAlerts);
obAlerts = new Alerts();
obAlerts.date = Date2.toString();
obAlerts.alertType = "Alert Type 1";
obAlerts.discription = "Some Text";
alert.add(obAlerts);
What I want to remove from them-
I want all alerts which have unique obAlerts.date and obAlerts.alertType. In other words, remove duplicate obAlerts.date and obAlerts.alertType alerts.
I tried this -
Alerts temp1, temp2;
String macTemp1, macTemp2, macDate1, macDate2;
for(int i=0;i<alert.size();i++)
{
temp1 = alert.get(i);
macTemp1=temp1.alertType.trim();
macDate1 = temp1.date.trim();
for(int j=i+1;j<alert.size();j++)
{
temp2 = alert.get(j);
macTemp2=temp2.alertType.trim();
macDate2 = temp2.date.trim();
if (macTemp2.equals(macTemp1) && macDate1.equals(macDate2))
{
alert.remove(temp2);
}
}
}
I also tried-
HashSet<Alerts> hs = new HashSet<Alerts>();
hs.addAll(obAlerts);
obAlerts.clear();
obAlerts.addAll(hs);
You need to specify yourself how the class decides equality by overriding a pair of methods:
public class Alert {
String date;
String alertType;
#Override
public boolean equals(Object o) {
if (this == 0) {
return true;
}
if ((o == null) || (!(o instanceof Alert)))
return false;
}
Alert alert = (Alert) o;
return this.date.equals(alert.date)
&& this.alertType.equals(alert.alertType);
}
#Override
public int hashCode() {
int dateHash;
int typeHash;
if (date == null) {
dateHash = super.hashCode();
} else {
dateHash = this.date.hashCode();
}
if (alertType == null) {
typeHash = super.hashCode();
} else {
typeHash = this.alertType.hashCode();
}
return dateHash + typeHash;
}
}
You can then loop through your ArrayList and add elements if they aren't already there as Collections.contains() makes use of these methods.
public List<Alert> getUniqueList(List<Alert> alertList) {
List<Alert> uniqueAlerts = new ArrayList<Alert>();
for (Alert alert : alertList) {
if (!uniqueAlerts.contains(alert)) {
uniqueAlerts.add(alert);
}
}
return uniqueAlerts;
}
However, after saying all that, you may want to revisit your design to use a Set or one of its family that doesn't allow duplicate elements. Depends on your project. Here's a comparison of Collections types
You could use a Set<>. By nature, Sets do no include duplicates. You just need to make sure that you have a proper hashCode() and equals() methods.
In your Alerts class, override the hashCode and equals methods to be dependent on the values of the fields you want to be primary keys. Afterwards, you can use a HashSet to store already seen instances while iterating over the ArrayList. When you find an instance which is not in the HashSet, add it to the HashSet, else remove it from the ArrayList. To make your life easier, you could switch to a HashSet altogether and be done with duplicates per se.
Beware that for overriding hashCode and equals, some constraints apply.
This thread has some helpful pointers on how to write good hashCode functions. An important lesson is that simply adding together all dependent fields' hashcodes is not sufficient because then swapping values between fields will lead to identical hashCodes which might not be desirable (compare swapping first name and last name). Instead, some sort of shifting-operation is usually done before adding the next atomic hash, eg. multiplying with a prime.
First store your datas in array then split at as one by one string,, till the length of that data execute arry and compare with acyual data by if condition and retun it,,
HashSet<String> hs = new HashSet<String>();
for(int i=0;i<alert.size();i++)
{
hs.add(alert.get(i).date + ","+ alert.get(i).alertType;
}
alert.clear();
String alertAll[] = null;
for (String s : hs) {
alertAll = s.split(",");
obAlerts = new Alerts();
obAlerts.date = alertAll[0];
obAlerts.alertType = alertAll[1];
alert.add(obAlerts);
}

Retrieve text from a RemoteViews Object

I need to retrieve some text from a RemoteViews object. It is possible for me to get the LayoutId, but I have no idea how to retrieve text from a TextView that is in this RemoteView (namely a notification).
Also the RemoteView only contains setters, but no getters, so I guess I have to use the LayoutId (somehow).
Can you help me with that? Thanks!
/edit: The reason why I am asking this, is because I have an AccessibilityService that retrieves the notification. Therefore this is the only way of retrieving the value.
/edit2: I use this code for receiving the notification:
#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();
}
}
With the notification object I have access to a RemoteViews (notification.contentView) and to a PendingIntent (notification.contentIntent).
To get the layoutId, I can call contentView.getLayoutId()
I proposed a similar solution here that also uses reflection to solve the problem, but in a more approachable fashion. This is my solution. In this context, the RemoteViews came from a Notification, so the first three lines can probably be ignored if you already have access to the RemoteViews object. The link on the page provides a much more detailed explanation of what is actually going on. I hope this will help anyone with a similar problem.
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;
}
Taken from 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();
}
CommonsWare in this question says:
... App widgets are write-only: you can push data to them, but you
cannot read them. Instead, when you update your app widget with
new text, you will need to store that text somewhere, perhaps in a
file.
His answer seems to be logical.
If you are targeting on Android 19+, you can use the following code for getting title/text from a Notification object without using any private APIs.
Notification noty = ...;
Bundle extras = noty.extras;
if (extras != null) {
String title = extras.getString(Notification.EXTRA_TITLE);
String text = extras.getString(Notification.EXTRA_TEXT);
}

Categories

Resources