I've been working on an android app concept in which the app has to auto-dial some special USSD codes in order to initiate certain telco services of interest to the user when the user initiates the service via a shortcut in the app.
The trouble I'm finding is that when the app tries to auto-dial such short codes or USSD numbers, the phone's OS (or is it the Call Intent), doesn't auto-dial, but instead presents the user with the code/number in the dial-pad and so the user has to manually initiate the call - which sort of defeats my intention of allowing users to initiate the services with just one click - the shortcut.
Currently, this is how I'm initiating these calls:
intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:" + number.trim()));
try {
activity.startActivity(intent);
} catch (Exception e) {
Log.d(Tag, e.getMessage());
}
Interestingly, a number such as +256772777000 will auto-dial, launching the user into the call automatically, but a number/code such as 911, *112#, *1*23#, etc won't.
So, what do I need to do differently, or is this not possible at all?
UPDATE
Actually, looking at another app in which I was autodialling user-specified numbers, the problem with the above code trying to auto-dial ussd codes was that instead of using intent.ACTION_CALL, I was using intent.ACTION_DIAL - which definitely just prompts the user with the number to call, without directly calling it. When I fixed that, the app now works as expected. See answer below...
Code samples are most welcome.
Actually, despite what some people were claiming about Android preventing such a feature. When I looked at the code in one of my older apps which auto-dials user-specified numbers, I found the solution to be:
intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:" + number.trim()));
try {
activity.startActivity(intent);
} catch (Exception e) {
Log.d(Tag, e.getMessage());
}
This works as expected - USSD codes get auto-dialled when above code runs. The only important thing to note when using this approach, being that you have to add the following permissions to your manifest:
<uses-permission android:name="android.permission.CALL_PHONE" />
So, as indicated in the update to my question, the problem with my original approach was using intent.ACTION_DIAL instead of intent.ACTION_CALL.
Related
I'm currently developing an Android application in order to display home screen widgets. Those ones are related to Microsoft Outlook (Events + Messages) in order to show incoming events and unread new messages in a kind of dynamic tiles.
The Msal graph library helps me a lot to authenticate and retrieve in formations which contains an identifier for each event / message results
But now I want to know if the outlook application is installed on the user device and if there is a way to open Outlook when the user click on the widget. Moreover if the user can open the corresponding clicked event or message with the identifier.
For example the Event widget currently displaying a birthday event. The user click on it. Then it opens Outlook and display directly that birthday event.
Regards
I don't think this is officially documented somewhere. But here's what you can do to find out about it.
You can list all Microsoft applications installed on your device...
val packages = context.packageManager
.getInstalledApplications(PackageManager.GET_META_DATA)
for (info in packages) {
if(info.packageName.startsWith("com.microsoft", true)){
Log.d("package name:" + info.packageName)
Log.d("Launch Activity: " + context.packageManager.getLaunchIntentForPackage(info.packageName))
}
}
Take a note of the "launch intent" displayed in the LogCat. You can use that to launch Outlook. Just make sure you don't hard-code those values because Microsoft can change those values at any point, for example the activity class can change. So, instead of doing this...
context.startActivity(
Intent().apply {
action = Intent.ACTION_MAIN
addCategory(Intent.CATEGORY_LAUNCHER)
setPackage("com.microsoft.office.outlook")
component = ComponentName("com.microsoft.office.outlook", "com.microsoft.office.outlook.MainActivity")
}
)
Do this...
context.startActivity(
Intent().apply {
action = Intent.ACTION_MAIN
addCategory(Intent.CATEGORY_LAUNCHER)
component = ComponentName(
outlookLaunchIntent?.component?.packageName,
outlookLaunchIntent?.component?.className
)
setPackage(outlookLaunchIntent.package)
}
)
Also, remember that getLaunchIntentForPackage and component can return null, so make sure you check for null values properly
I am relaying a suggestion from a couple of internal folks:
Please try to open the event using one of the following URLs:
ms-outlook://events/open?restid=%s&account=test#om.com (if you have a regular REST id)
ms-outlook://events/open?immutableid=%s&account=test#om.com (if you are using an immutable id)
Since immutable IDs are still in preview stage in Microsoft Graph, and customers should not use preview APIs in their production apps, I think option #1 applies to your case.
Please reply here if the URL works, or not, and if you have other related questions. I requested the couple of folks to keep an eye on this thread as well.
Well, i managed to open the outlook android application with the help of your code #Leo. As im not developping with Kotlin, ill post the JAVA code below :
Intent outlookLaunchIntent = context.getPackageManager().getLaunchIntentForPackage("com.microsoft.office.outlook");
if (outlookLaunchIntent != null) {
context.startActivity(outlookLaunchIntent );
}
Below code to open event/message in a web browser provided by webLink property of the graph API. (I only test for event and the url provided not working. Ill post a new issue on StackOverFlow for that but you already see the issue over there : https://github.com/microsoftgraph/microsoft-graph-docs/issues/4203
try {
Intent webIntent = new Intent(Intent.ACTION_VIEW).setData(Uri.parse(calendarWebLink));
webIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(webIntent);
} catch (RuntimeException e) {
// The url is invalid, maybe missing http://
e.printStackTrace();
}
However im still stuck on the decicive goal of my widget item click which is to open the relative event/email in the Microsoft Outlook Android application.
Microsoft Outlook Android app contains widgets which can achieve what im looking for. So i wonder if it is possible to list its broadcast receivers.
The best thing i found is an old manifest for that app but it doesnt help me.
https://gist.github.com/RyPope/df0e61f477af4b73865cd72bdaa7d8c2
Hi may you try to open the event using one of the url:
ms-outlook://events/open?restid=%s&account=test#om.com (If the
user is having rest id)
ms-outlook://events/open?immutableid=%s&account=test#om.com (If
the user is having immutable id)
public void executeApp(ExecuteABCDEvent event) {
PackageManager pm = this.getContext().getPackageManager();
try {
String packageName = "package name here";
Intent launchIntent = pm.getLaunchIntentForPackage(packageName);
this.getContext().startActivity(launchIntent);
} catch (Exception e1) {
Log.d("Exception", e1.getMessage());
}
}
I am opening a 3rd pary application using the above code.
Along with opening of this 3rd party application I also want to populate some text fields.
Solution 1: put and get data from intent.
I cannot user solution 1 as i cannot use the get methods in 3rd party app.
Solution 2: Content provider.I am not sure how content provider of application works and how it helps.
Is there another approach for this.
You have no good way of doing what you want. For obvious security reasons, apps cannot hack into other apps.
You are welcome to create an AccessibilityService and attempt to use that to achieve your ends. I am skeptical that it will work, and even if it does, I am skeptical that many people will install your app, given the large security warnings that are presented when the user goes in to activate your AccessibilityService.
In my app, I am writing a functionality to share a shopping list to Google Keep. For this, I use the Intent.ACTION_SEND action and set the package to the one of Google Keep.
Everything works great, but I am wondering if it is possible to add an EXTRA parameter to the Intent telling Google Keep it must be displayed as a list with checkboxes, like it is possible to add extra event-specific extra's when creating a Calendar Event. Now, it is displayed as plain text.
Here is my code:
try {
Intent keepIntent = new Intent(Intent.ACTION_SEND);
keepIntent.setType("text/plain");
keepIntent.setPackage("com.google.android.keep");
keepIntent.putExtra(Intent.EXTRA_SUBJECT, "Shopping List " + recipe.getName());
keepIntent.putExtra(Intent.EXTRA_TEXT, "Flower\nyeast\nbutter\nalmonds");
startActivity(keepIntent);
} catch (Exception e) {
Dialogs.toastShort(this, "Google Keep is not installed on your device");
}
Now, I get this as result:
What, I want to get is this as result - without that the user has to select "show checkboxes" in the actionbar:
Thanks for your help.
Unfortunately, it's not possible. Google has not published an API for public nor 3rd party use. If you check out the http traffic you can see the underlying API but there's no real way to replicate it. Sorry
whenever we get a call, we do see missed call notification. Is there a way to remove the missed call notification in android programatically?
We see missed calls numbers & its count. Can we remove them via code?
The only "legal" but extremely ugly and usually useless way to achieve what you want is to show Call Log to user. And I mean literally show (becomes visual, gets focus). In case you want to do this, here's how:
public static boolean showCallLog(Context context)
{
try
{
Intent showCallLog = new Intent();
showCallLog.setAction(Intent.ACTION_VIEW);
showCallLog.setType(android.provider.CallLog.Calls.CONTENT_TYPE);
context.startActivity(showCallLog);
return true;
}
catch (Exception e)
{
Log.d("Couldn't show call log.", e.getMessage());
}
return false;
}
The reason behind this mess is the fact that apps authoritatively responsible for call logging and notifying users about missed calls (stock phone apps) use cached values. Why? Because of overall performance. You need to somehow notify those apps that Call Log has changed (seen means changed, as well) and that it should update it. It would be nice if all such apps on all devices would receive a broadcast in order to refresh, but as far as I know, it's not the case.
I hope someone will find a better way to force refresh on stock phone apps.
on Android phones, under Call -> Additional settings -> Caller ID
it is possible to hide your caller ID. I want to do that programatically from my code, but was not able to find a way to do that.
I searched through
android.provider
android.telephony
for 2.1 release and was not able to find it.
Has anybody successfully solved this issue?
Thanks in advance. Best regards.
Here I will describe two approaches I tried.
1.) It is possible to display Additional Call Settings screen from your application. Although it looks like it is part of the Settings application, that is not true. This Activity is part of the Native Phone Application, and it may be approached with the following intent:
Intent additionalCallSettingsIntent = new Intent("android.intent.action.MAIN");
ComponentName distantActivity = new ComponentName("com.android.phone", "com.android.phone.GsmUmtsAdditionalCallOptions");
additionalCallSettingsIntent.setComponent(distantActivity);
startActivity(additionalCallSettingsIntent);
Then user has to manually press on the CallerID preference and gets radio button with 3 options.
This was not actually what I wanted to achieve when I asked this question. I wanted to avoid step where user has to select any further options.
2.) When approach described under 1.) is executed in the Native Phone Application, function setOutgoingCallerIdDisplay() from com.android.internal.telephony.Phone has been used.
This was the basis for the next approach: use Java Reflection on this class and try to invoke the function with appropriate parameters:
try
{
Class <?> phoneFactoryClass = Class.forName("com.android.internal.telephony.PhoneFactory");
try
{
Method getDefaultPhoneMethod = phoneFactoryClass.getDeclaredMethod("getDefaultPhone");
Method makeDefaultPhoneMethod = phoneFactoryClass.getMethod("makeDefaultPhone" , Context.class);
try
{
makeDefaultPhoneMethod.invoke(null, this);
Object defaultPhone = getDefaultPhoneMethod.invoke(null);
Class <?> phoneInterface = Class.forName("com.android.internal.telephony.Phone");
Method getPhoneServiceMethod = phoneInterface.getMethod("setOutgoingCallerIdDisplay", int.class, Message.class);
getPhoneServiceMethod.invoke(defaultPhone, 1, null);
}
catch (InvocationTargetException ex)
{
ex.printStackTrace();
}
catch (IllegalAccessException ex)
{
ex.printStackTrace();
}
}
catch (NoSuchMethodException ex)
{
ex.printStackTrace();
}
}
catch (ClassNotFoundException ex)
{
ex.printStackTrace();
}
Firstly I tried just to use getDefaultPhone(), but I get RuntimeException
"PhoneFactory.getDefaultPhone must be called from Looper thread"
Obviously, issue lies in the fact that I tried to call this method from the Message Loop that was not the Native Phone App one.
Tried to avoid this by making own default phone, but this was a security violation:
ERROR/AndroidRuntime(2338): java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.provider.Telephony.SPN_STRINGS_UPDATED from pid=2338, uid=10048
The only way to overcome (both of) this would be to sign your app with the same key as the core systems app, as described under
Run secure API calls as root, android
I'm not sure if this is a global feature, but Australian phones can hide their number by prefixing the caller's number with #31# or 1831. This may not be the perfect solution, but a prefix like this could possibly work for your requirements during coding.