I'm making an app that can launch other apps. I've got it launching apps fine using Spinners, however, I would also like to give the user the ability to launch direct dials from it.
As it is right now I've got "hot key" buttons that the user can configure. Currently, when the user wants to configure one of these "hot keys" I use a spinner to let them choose from all the installed applications on their phone. For starters, I would like it if they are able to view both installed applications and shortcuts in the spinner so that they can map a direct dial to one of these "hot keys."
So my main questions are, how can I go about looking up all the defined shortcuts available and execute them and how could I create my own direct dials in my app?
To dial a number directly
startActivity(new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + NUMBER)));
here is a simple function for this
public static void go2Call(Context context, String phoneNo) {
Intent intent = null;
Uri destUri = null;
/*
* http://developer.android.com/guide/appendix/g-app-intents.html
<uses-permission id="android.permission.CALL_PHONE" />
tel: phone_number
*/
if(DEBUG)Log.d(TAG, "go2Call ->" + "phoneNo:"+phoneNo);
phoneNo = PhoneNumberUtils.convertKeypadLettersToDigits(phoneNo);
if(DEBUG)Log.d(TAG, "go2Call ->" + "phoneNo(normalized):"+phoneNo);
if ( !TextUtils.isEmpty(phoneNo) ) {
destUri = Uri.parse("tel:" + phoneNo);
}
if (destUri!=null) {
intent = new Intent( Intent.ACTION_VIEW, destUri );
}
if ( intent!=null && isIntentAvailable(context, intent) ) {
context.startActivity(intent);
}
else {
// TODO: display error msg
Log.w(TAG, "error pr intent not available! ->" + "phoneNo:"+phoneNo);
}
}
Related
I am launching my app from the browser and if the app is not already loaded/running then it launches the app through onCreate and collects the intent.data and does the right thing. If the app is already running then launching the app from the browser bypasses the onCreate and goes right to onResume which I "believe" is expected behavior. But the intent.data associated with the launch from the browser is null. I was hoping that the intent data would be overwritten with the new intent data from scheme url string so that I can relaunch the webview inside the app with the new parameters. Is there some way that I can push this new data into the app when it is launched (i.e., resumed) by the browser?
// JS Browser code with arguments to be passed to the app.
var r = Math.random();
window.open("myScheme://caca.com/?mode=driver" + "&ec=" + ec + "&uh=" + $("#userHandle").val() + "&at=0" + "&random=" + r);
// Xamarin
onResume(...) {
...
try
{
// currentActivity.Intent.Data != null if app is not already running
// is null if already running
Android.Net.Uri data = currentActivity.Intent.Data;
string scheme = data.Scheme;
DebugToast("scheme " + scheme, ToastLength.Long);
if (scheme == "myScheme")
{
// force the cookies so the web app will come up as we specify
SetStorageValue("browserLaunched", "true");
SetStorageValue("mode", data.GetQueryParameter("mode"));
SetStorageValue("ec", data.GetQueryParameter("ec"));
SetStorageValue("uh", data.GetQueryParameter("uh"));
SetStorageValue("authToken", data.GetQueryParameter("at"));
SetStorageValue("at", data.GetQueryParameter("at"));
DebugToast("parms " + data.GetQueryParameter("mode") + " " + data.GetQueryParameter("ec") + " " + data.GetQueryParameter("uh") + " " + data.GetQueryParameter("at"), ToastLength.Long);
// restart the web view with arguments above
...
}
}
catch
{
....
}
}
Homer Simpson D'oh!. Needed to add 'onNewIntent()' to activity which receives the "um er dah" new Intent with the appropriate data attached.
It is well known that menu driven USSD applications are always got it's pre defined order of taking parameters in. for Example
User sends #111# (Sri Lanka), and gets a menu of about 12 sub items to select by sending its sub menu number back. Then it may ask to select another one from a set of sub menu. Send the number etc. etc. and send pin, send phone number to reload (if it is reloading) then send yes(1) no(2) to confirm then 99 to finish USSD event.
I have succeeded sending continues signals from VB.NET to phone using NOKIA ASHA 501 (using its Bluetooth outgoing com port) as follows.
strCommand = "AT+CUSD=1," & Chr(34) & "#111#" & Chr(34) & ",15" & vbCrLf
comport.Write(strCommand)
Thread.Sleep(5000)
This will bring up the USSD menu. The DataReceivedHandler of the com port port.DataReceived can give you if there is any error returned like com is not open to error dialing USSD.
Next I will send is response string contains "OK"
strCommand = "AT+CUSD=1," & Chr(34) & "1" & Chr(34) & ",15" & vbCrLf
comport.Write(strCommand)
Thread.Sleep(5000)
Again check for OK etc. This works and I wanted to do this from Android.
Succeeded up to getting the first menu as follows.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
String encodedHash = Uri.encode("#");
call(encodedHash + "111" + encodedHash);
}
});
}
protected void call(String phoneNumber) {
try {
startActivityForResult(
new Intent("android.intent.action.CALL", Uri.parse("tel:"
+ phoneNumber)), 1);
} catch (Exception e) {
view.append("\n Here \n " + "\n" + e.toString() + " hi");//
}
}
So far so good.
I don't need to read the response from USSD. Just want to send next command like "1" to the same USSD thread giving a sleep time of 4/5 seconds.
If i use the same way, it brings up another thread calling the number "1"
String encodedHash = Uri.encode("#");
call(encodedHash + "1" + encodedHash);
startActivityForResult(
new Intent("android.intent.action.CALL", Uri.parse("tel:"
+ phoneNumber)), 1);
Tried many things (without any lead from so many documents rotating).
Thanks in advance. All those cods above are taken from great places like stackoverflow and they are working.
I tried to make an intent like calling intent
Intent skype = new Intent("android.intent.action.VIEW");
skype.setData(Uri.parse("skype:" + "user_name" + "?message=ddd"));
startActivity(skype);
and it did not work.
The problem with official Android SDK, as well as Skype URI's is that they not allow to share predefined message. You can just open chat with list of users (or empty to create a new one). If you want to explicity share some text with Skype you can try to use system Intents with Skype package name (remember to check if this package name is installed, otherwise startActivity call will crash your app):
val SKYPE_PACKAGE_NAME = "com.skype.raider"
fun shareSkype(context: Context, message: String) {
if (!isAppInstalled(context, SKYPE_PACKAGE_NAME)) {
openAppInGooglePlay(context, SKYPE_PACKAGE_NAME)
return
}
val intent = context.packageManager.getLaunchIntentForPackage(SKYPE_PACKAGE_NAME)
intent.action = Intent.ACTION_SEND
intent.putExtra(Intent.EXTRA_TEXT, message)
intent.type = "text/plain"
context.startActivity(intent)
}
fun isAppInstalled(context: Context, packageName: String): Boolean {
val packageManager = context.packageManager
try {
packageManager.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES)
} catch (e: PackageManager.NameNotFoundException) {
return false
}
return true
}
If Skype or other Android messaging applications do not have publicly available Intents, it will not be possible to do so until they are available.
You could however try to find a proxy service that skype uses to call within your application as a means to send messages.
http://developer.skype.com/skype-uris/reference#uriChats
Notice:
Caveats:
The optional topic argument applies to multi-chats only.
Special characters in the topic argument value—specifically whitespace—must be escaped.
Mac OS X: ignores any topic argument.
iOS: not supported.
Android: recognizes the initial participant only; multi-chats are not supported.
Android Docs - http://developer.skype.com/skype-uris/skype-uri-tutorial-android
/**
* Initiate the actions encoded in the specified URI.
*/
public void initiateSkypeUri(Context myContext, String mySkypeUri) {
// Make sure the Skype for Android client is installed
if (!isSkypeClientInstalled(myContext)) {
goToMarket(myContext);
return;
}
// Create the Intent from our Skype URI
Uri skypeUri = Uri.parse(mySkypeUri);
Intent myIntent = new Intent(Intent.ACTION_VIEW, skypeUri);
// Restrict the Intent to being handled by the Skype for Android client only
myIntent.setComponent(new ComponentName("com.skype.raider", "com.skype.raider.Main"));
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Initiate the Intent. It should never fail since we've already established the
// presence of its handler (although there is an extremely minute window where that
// handler can go away...)
myContext.startActivity(myIntent);
return;
}
I'm new in Android dev and I'm developing an Android App using Eclipse. I provided a functionality to Synchronize database on Dropbox. To do it, Dropbox give me a key value to use for authentication. This key have to be inserted in AndroidManifest.xml
<activity
android:name="com.dropbox.client2.android.AuthActivity"
android:configChanges="orientation|keyboard"
android:launchMode="singleTask" >
<intent-filter>
<!-- Change this to be db- followed by your app key -->
<data android:scheme="db-xxxxxxxxxx" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
But using this logic, the end user will not be able to change this value to synchronize database on his dropbox account, and not on my. I've made a preference screen to store the key in Application Preferences, but I' don't find code where the value is read from Android Manifest. I think it's about here but I'm new and I don't understand how to edit my code:
public void startAuthentication(Context context) {
AppKeyPair appKeyPair = getAppKeyPair();
// Check if the app has set up its manifest properly.
Intent testIntent = new Intent(Intent.ACTION_VIEW);
String scheme = "db-" + appKeyPair.key;
String uri = scheme + "://" + AuthActivity.AUTH_VERSION + "/test";
testIntent.setData(Uri.parse(uri));
PackageManager pm = context.getPackageManager();
List<ResolveInfo> activities = pm.queryIntentActivities(testIntent, 0);
if (0 == activities.size()) {
throw new IllegalStateException("URI scheme in your app's " +
"manifest is not set up correctly. You should have a " +
"com.dropbox.client2.android.AuthActivity with the " +
"scheme: " + scheme);
} else if (activities.size() > 1) {
// Check to make sure there's no other app with this scheme.
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Security alert");
builder.setMessage("Another app on your phone may be trying to " +
"pose as the app you are currently using. The malicious " +
"app cannot access your account, but linking to Dropbox " +
"has been disabled as a precaution. Please contact " +
"support#dropbox.com.");
builder.setPositiveButton("OK", new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.show();
return;
} else {
// Just one activity registered for the URI scheme. Now make sure
// it's within the same package so when we return from web auth
// we're going back to this app and not some other app.
String authPackage = activities.get(0).activityInfo.packageName;
if (!context.getPackageName().equals(authPackage)) {
throw new IllegalStateException("There must be an " +
"AuthActivity within your app's package registered " +
"for your URI scheme (" + scheme + "). However, it " +
"appears that an activity in a different package is " +
"registered for that scheme instead. If you have " +
"multiple apps that all want to use the same access" +
"token pair, designate one of them to do " +
"authentication and have the other apps launch it " +
"and then retrieve the token pair from it.");
}
}
// Start Dropbox auth activity.
Intent intent = new Intent(context, AuthActivity.class);
intent.putExtra(AuthActivity.EXTRA_INTERNAL_CONSUMER_KEY,
appKeyPair.key);
intent.putExtra(AuthActivity.EXTRA_INTERNAL_CONSUMER_SECRET,
appKeyPair.secret);
if (!(context instanceof Activity)) {
// If starting the intent outside of an Activity, must include
// this. See startActivity(). Otherwise, we prefer to stay in
// the same task.
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(intent);
Can you help me?
Thank you in advance
I think that you may be misunderstanding what that key is used for. It is not used for choosing which account to sync files with.
The key you want to change is an APP API key. Each user does not need a unique key unless you are targeting at developers who would have their own API keys already. This is used to identify your app and shut it down, among other things, if it's causing trouble for Dropbox.
The specific instance of this key you are trying to edit is what gets control back to your app after a user authenticates with their personal account. This needs to be kept in sync with the key you use for authentication when calling AppKeyPair appKeys = new AppKeyPair(APP_KEY, APP_SECRET);
You will not be able to modify the the data tag in that intent filter at runtime.
The object appKeyPair.key contains the key that you want.
I d'ont know what AppKeyPair appKeyPair = getAppKeyPair(); does, but I think you can remove it and put a simple string from the shared preferences instead of calling appKeyPair.key.
I have application, which sends some USSD codes. In one type of situation, from user actions with interface, in another - when some SMS (with wildcard) received.
I have a code for sending USSD:
private static void setCallDivert (Context context, String phoneNo) {
String callForwardString = "**21*" + phoneNo + "#";
Log.i("Call forward string", callForwardString);
Intent intentCallForward = new Intent(Intent.ACTION_CALL);
intentCallForward.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri uri2 = Uri.fromParts("tel", callForwardString, "#");
intentCallForward.setData(uri2);
context.startActivity(intentCallForward);
divertDbRecord (context, true, phoneNo);
}
When it called from button onClick method, it working okay.
When it called from SMS Handler, message "Call forwarding Connection problem or invalid MMI code" appear.
In logcat, I can see a request. It is a same, in both situations.
Of course, I testing it on real Android phone, not on emulator.
Maybe, someone can help me?
You need to encode your Uri hash
public static final String encodedHash = Uri.encode("#");
This allows the dialler to interpret the # value correctly