What is the reason of Android 12 ACTION_SENDTO intent extra anomaly? - java

In Android 12 if you add informations as subject(EXTRA_SUBJECT) and message(EXTRA_TEXT) when you use ACTION_SENDTO Intent to send a text email, these don't appear in the email client message, contrarely to all previous versions.
An user in a similar Kotlin question seems has solved the problem using apply selector in this way:
private fun createIntent(
metadata: String
): Intent {
return Intent(ACTION_SEND)
.putExtra(
EXTRA_EMAIL,
arrayOf(EMAIL)
)
.putExtra(
EXTRA_SUBJECT,
TITLE
)
.putExtra(
EXTRA_TEXT,
metadata
)
.apply {
selector = Intent(ACTION_SENDTO).setData(Uri.parse("mailto:"))
}
}
What is the reason of this issue? What is the proper way to fix the issue in Java?

these don't appear in the email client message, contrarely to all previous versions
How apps handle inbound extras is up to the developers of the apps. And, since ACTION_SENDTO is not documented to have those extras, you should not be surprised when apps ignore those extras.
What is the proper way to fix the issue in Java?
Do what you have there in Kotlin, if ACTION_SEND will work for you. Intent works the same way whether you use it in Java, Kotlin, or any other suitable programming language. Your selector will limit your Intent to apps that have activities that support that mailto: Uri for ACTION_SENDTO (which may be more than just email apps).
By eyeball, the Java equivalent should be something like this:
private Intent createIntent(String metadata) {
Intent result = new Intent(ACTION_SEND)
.putExtra(
EXTRA_EMAIL,
new String[] { EMAIL }
)
.putExtra(
EXTRA_SUBJECT,
TITLE
)
.putExtra(
EXTRA_TEXT,
metadata
);
result.setSelector(new Intent(ACTION_SENDTO).setData(Uri.parse("mailto:")));
return result;
}

Related

Alternative for toast when using widgets in Android 12 as toasts are now truncated

hope someone can point me in the right direction.
I have created an app with a widget. The widget is a simple button that runs a bit of code and then returns a message to the user via a toast. However, I realise in Android 12 toasts are now truncated to two lines and often the message is longer. I'm not keen on snackbars but appreciate my main app can be converted to use them but what should I use to do the same job via a widget?
Snackbars require a layout view to work but I can't figure out how to retirve it from teh widget code. I could use an alertdialogue but although the code compiles they simple don't seem to show up. I'm open to suggestions here...
What is the best way of popping up a message on the homescreen when a widget is pressed? Is there any way of telling the app not to truncate toasts or if not what's the best alternative?
Many thanks
Nat
Finally worked out how to do this myself... Its kinda obvious when you know but isn't that always the way?
Create a new activity. You can make it look like a dialog by using this theme in your manifest - android:theme="#style/Theme.AppCompat.Dialog". Then from your widget simply call showmessage as outlined below...
public void showamessage (String thetitle, String themessage) {
PendingIntent pendingIntent;
Intent intent = new Intent();
intent.setClass(thecontext,MessageActivity.class);
intent.putExtra("TheTitle",thetitle);
intent.putExtra("TheMessage",themessage);
pendingIntent = PendingIntent.getActivity(thecontext, 0, intent, FLAG_IMMUTABLE);
try {
pendingIntent.send(thecontext, 0, intent);
} catch (PendingIntent.CanceledException e) {
System.out.println( "Sending pendingintent failed: " );
}
}

Handling a deep link from the google assistant in Java

Looking to handle a deep link from the Google Assistant. As I only have an emulator at the moment I am having trouble testing it (from what I have read it requires a real device). That said, I was wondering if I am handling it the correct way. I am unfamiliar with Kotlin and my code was turning into Spaghetti trying to integrate, so I put this together in my existing launcher activity just to try and get it bootstrapped for now. The manifest and actions.xml were set up like the fitness app tutorial.
Am I doing this correctly?
if (mAuth.getCurrentUser() != null) {
data = this.getIntent().getData();
if (data != null && data.isHierarchical()) {
uriData = data.toString();
containsStart = containsIgnoreCase(uriData,"start");
containsRun = containsIgnoreCase(uriData,"run");
if(containsStart && containsRun) {
Intent intent = new Intent(getApplication(), RunActivity.class);
intent.putExtra("runStart", true);
startActivity(intent);
}
}
else {
checkUserAccType();
}
//Else, if there is no current user, start the Authentication activity
}
A few observations and recommendation about your code:
Instead of using containsIgnoreCase uses getPath() and match the path. See example.
Also, for the activity parameter use URL query param instead of containsIgnoreCase. See example
Starting the activity or fragment. I assume startActivity and checkUserAccType will handle that part. See example.
// Else... section should go one line below.
Authentication. It looks fine. And it seems you're using Firebase by the getCurrent method signature. See example

Geo Intent Label not showing in Google Maps App

Since my Google Maps app updated recently, now version 10.11.1, the following code does not show the label as expected, documented, and previously working:
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("geo:38.8951,100.0364?q=38.8951,100.0364(foo)")).setPackage("com.google.android.apps.maps")
if (intent.resolveActivity(packageManager) == null) {
intent.setPackage(null)
}
startActivity(intent)
And neither does this version (with 0,0 immediately after geo:):
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("geo:0,0?q=38.8951,100.0364(foo)")).setPackage("com.google.android.apps.maps")
if (intent.resolveActivity(packageManager) == null) {
intent.setPackage(null)
}
startActivity(intent)
Neither does the example code in the official documentation show a label:
// Display a label at the location of Google's Sydney office
Uri gmmIntentUri = Uri.parse("geo:0,0?q=-33.8666,151.1957(Google+Sydney)");
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
mapIntent.setPackage("com.google.android.apps.maps");
startActivity(mapIntent);
Update: Scheduled to be fixed in v11.12 perhaps before the end of January 2022.
No solution still even with latest map update 10.12.1 the label still does not show even if the documentation still says it should
I've created an issue on Google's Issue tracker: https://issuetracker.google.com/issues/129726279
hopefully we'll have some information shortly.
Per Google, it's a bug in the Google Maps app. It's fixed in version 11.12.
I think we are going about it the wrong way here. If I was Google, I would also feel insecure about allowing developers to post directions with an abstract destination label, I am sure they never plan to fix this.
I recommend the following solution according to Google's new standards. https://developers.google.com/maps/documentation/urls/android-intents:
https://www.google.com/maps/dir/?api=1&destination=LATITUDE,LONGITUDE
If you look at most apps these days, including the ones I have built, this allows us to post a LAT/LONG for the user to go to with Google's own Address values built in as the destination label.
To actually launch the Google Maps application, simply launch a web intent, I use the application context in this case.
fun startGoogleMaps(context: Context, lat: Double, long: Double) {
startWebBrowser(
context,
Uri.parse("https://www.google.com/maps/dir/?api=1&destination=$lat,$long")
)
}
fun startWebBrowser(context: Context, link: Uri?) {
if (link != null) {
val webIntent = Intent(Intent.ACTION_VIEW, link).apply {
addFlags(FLAG_ACTIVITY_NEW_TASK)
}
if (webIntent.resolveActivity(context.packageManager) != null) {
context.startActivity(webIntent)
}
}
}

Android: How to launch call intent using google voice?

How to launch specific intent (such as call) using google voice? How to pass phone number using intent? Following code launches google voice but what value to be passed for making call using google voice as intent extras?
final Intent intent = new Intent();
intent.setComponent(new ComponentName("com.google.android.apps.googlevoice", "com.google.android.apps.googlevoice.activity.conversationlist.ConversationListActivity"));
intent.putExtra("label", "<phone number>");
startActivity(intent);
Here what should i put in label to start the intent that launches a call using google voice?
Any help is appreciated... Thanks in Advance...
NEVER target applications directly like that UNLESS it is in your package. You should be using the Intent filter to catch that particular application. Sometimes you have to target an application like this, but this brings up the risk of change in package name errors.
To handle your particular application, you need to look at how information is being passed into Google voice. this will give you insight and how to target it WITHOUT targeting the exact package name.
What #JoxTraex said makes sense. However some clients need funny features like this, so we have no way but to implement this:
try {
Intent intent = new Intent(Intent.ACTION_DIAL,Uri.parse("tel:" + mobile));
intent.setPackage("com.google.android.apps.googlevoice");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
} catch (ActivityNotFoundException anfe) {
GMHintManager.getInstance().showError(context, "Google Voice not installed");
}
Yes, you should try-catch ActivityNotFoundException.

Debugging Intents

I asked a question previously about what shows up in the IntentChooser when I send an Intent with ACTION_SEND and MIME type "image/png". The problem is that some phones come with a default messaging app that is not showing up in the list, mine included (myTouch 4G) as well as a user that I speak with over email (using an HTC EVO). If I choose a Send or Share option from the built in gallery app or another application on the same image I'm saving and attempting to send directly from my app, Messages shows up in the list. From my app it does not. Other phones don't have this problem, so it's clearly a platform specific thing. But that doesn't mean I should just ignore the problem.
So, I go to troubleshooting the issue. I register one of the activities in my app to receive the the same type of intent, and then hit a breakpoint to analyze the Intent object being sent from the two different ways of sending it.
The problem is, the intent I'm sending and the intent being sent from Gallery or AndroZip (where Messages does show up in the chooser) seem to be the same. They both have the same action, same categories, same flags, same mime type. What else can I inspect on the Intent from Gallery or AndroZip to tell if there's some more information I can add to my Intent to get the default messaging app to show up in the chooser in cases where it is not?
The problem is specific to HTC Sense phones, and it arises because their Gallery and Messaging apps are different to the stock ones.
Specifically the Intent sent from Gallery to Messaging has the action android.intent.action.SEND_MSG which is different to android.intent.action.SEND. The Sense messaging app doesn't handle SEND, unlike the stock messaging app.
So the question becomes, how is the Sense Gallery app creating an activity chooser dialog which combines both SEND and SEND_MSG ?
I've done some research and got mostway there... the code below works, but the "Messages" entry in the dialog appears at the top rather than in alphabetical order as per Gallery. Doubtless some more research into intents would correct that, but at least this works:
// Create a chooser for things that can ACTION_SEND images
Intent intent = new Intent(Intent.ACTION_SEND);
Uri data = Uri.parse("content://media/external/images/media/98");
intent.putExtra(Intent.EXTRA_STREAM, data);
intent.setType("image/jpeg");
Intent chooser = Intent.createChooser(intent, "Blah");
// Add the stupid HTC-Sense-specific secondary intent
Intent htcIntent = new Intent("android.intent.action.SEND_MSG");
htcIntent.putExtra(Intent.EXTRA_STREAM, data);
htcIntent.setType("image/jpeg");
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { htcIntent });
// Show the chooser
startActivity(chooser);
First of all, +1 to Reuben, he is the genius, not me. But I had to modify his code a bit to get it to work. Basically I had to putExtra() on the htcIntent or the image never got stuck to the Intent.
Tested and validated on a Droid X and HTC Incredible (which had the same problem until now thanks to Reuben).
Uri uri = Uri.fromFile(new File(mFile));
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.setType("image/png");
Intent htcIntent = new Intent("android.intent.action.SEND_MSG");
htcIntent.setType("image/png");
htcIntent.putExtra(Intent.EXTRA_STREAM, uri);
Intent chooser = Intent.createChooser(intent, "Send Method");
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { htcIntent });
startActivity(chooser);
Edit: I realize I'm putting the image on two Intents now, but I couldn't get it to work any other way.
Instead of debugging the intents, why not try to compare how your starting the chooser with how the gallery is doing it. It is open source after all, so instead of trying to guess at the issue with the result, you can debug from the cause.
https://android.googlesource.com/platform/packages/apps/Gallery3D

Categories

Resources