I am working authentication on an android phone which sends the user to Hunch to authentication after clicking a log in button. This sets up a new intent as below:
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri data = Uri.parse("hunch.com/authorize/v1/?app_id=1234&next=hoosheer-hunch-app://");
intent.setData(data);
startActivity(intent);
This is my manifest file
<activity android:name="hunch" android:label="hunch">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="hoosheer-hunch-app" />
</intent-filter>
</activity>
It gives me this error:
04-12 17:04:22.574: ERROR/AndroidRuntime(838): android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=hunch.com/authorize/v1/?app_id=1234&next=hoosheer-hunch-app:// }
But I have similar code working for logging in using Foursquare. The hunch.java class contains an onResume method
Hunch does not currently support custom URL schemes such as hoosheer-hunch-app://
Until we implement this functionality you should use the following URL to authenticate:
http://hunch.com/authorize/v1/?app_id=1234&next=/
After authorizing your application, the user will be redirected to
http://hunch.com/?auth_token_key=4d3d3d3d3&user_id=hn_5678&next=%2F
You should monitor the ACTION_VIEW Intent for the URL change, pull the auth_token_key out of the URL, and then exchange it for an auth_token using the get-auth-token API call.
Related
In my application I have two buttons, one is to open the device's camera and the other to open my applications camera. I'm giving the user the option to choose which one they would like to use.
This is how I open the devices camera:
Uri videoUri = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".provider", filePlusName);
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(MediaStore.EXTRA_OUTPUT, videoUri);
startActivityForResult(intent, VIDEO_REQUEST_CODE);
a "Popup" will appear, asking me to choose a camera application - Complete action using.
The problem is that my applications camera is one of the options. I would like to remove my app's camera from this options.
Is it possible to remove my application from the Complete action using popup?
Check you AndroidManifest. I think one of your app activity is registered to do the capture intent action.
Look for these intent actions- if anyone exists, remove it-
<intent-filter>
<action android:name="android.media.action.IMAGE_CAPTURE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<intent-filter>
<action android:name="android.media.action.STILL_IMAGE_CAMERA"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<intent-filter>
<action android:name="android.media.action.VIDEO_CAMERA"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
I have written two different Android applications.
I wish for one application to create an intent and in turn, start an activity in the other application.
The first application which creates the intent has the following code:
Intent intent = new Intent();
intent.setAction("com.example.printtest.ACTION_PRINT");
Uri.Builder builder = new Uri.Builder();
builder.scheme("PrintAPI")
.authority("StartPrintJob")
.appendQueryParameter("appId", "aaa");
Uri uri = builder.build();
intent.setData(uri);
startActivity(intent);
The second application which I want to receive the intent has the following defined in it's manifest:
<activity android:name=".PrintActivity">
<intent-filter>
<action android:name="com.example.printtest.ACTION_PRINT"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
From what I understand, the activity in the second application should be recognized as the one to start this intent. However, the same exception is thrown each time. The exception being thrown is:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.myapp, PID: 21665
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=com.example.printtest.ACTION_PRINT dat=PrintAPI://StartPrintJob?appId=aaa }
Is there something that I'm missing?
Is it valid to start an activity in another application just by setting action and data on an intent?
Any help or advice is greatly appreciated.
You forgot to add data part
<activity android:name=".PrintActivity"
android:exported="true">
<intent-filter>
<action android:name="com.example.printtest.ACTION_PRINT"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="PrintAPI"></data>
</intent-filter>
</activity>
I'm trying to open the default calculator app in a android application. Two calculators are installed in device: default android calculator and Google Calculator.
Intent calc = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, Intent.CATEGORY_APP_CALCULATOR);
startActivity(calc);
This code is throwing an ActivityNotFoundException and shows this in logcat:
system_process W/IntentResolver: resolveIntent failed: found match, but none with CATEGORY_DEFAULT
This code have the same behavior:
Intent calc = new Intent(Intent.ACTION_MAIN);
calc.addCategory(Intent.CATEGORY_APP_CALCULATOR);
startActivity(calc);
It's a Android bug? How to open the application chooser, to let user select the default app?
Stack Trace:
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] sel=act=android.intent.action.MAIN cat=[android.intent.category.APP_CALCULATOR]} }
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1805)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1514)
at android.app.Activity.startActivityForResult(Activity.java:3930)
at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:50)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:79)
at android.app.Activity.startActivityForResult(Activity.java:3890)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:859)
at android.app.Activity.startActivity(Activity.java:4213)
at android.app.Activity.startActivity(Activity.java:4181)
at com.MyActivity.openCalc(MyActivity.java:202)
at com.MyActivity.onOptionsItemSelected(MyActivity.java:191)
at android.app.Activity.onMenuItemSelected(Activity.java:2914)
at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:408)
at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:195)
at android.app.ActivityThread.main(ActivityThread.java:5461)
It seems like the way, that documentation points to doesn't work. Nevertheless, this code will normally open default calculator app.
Intent intent = new Intent();
intent.setClassName("com.android.calculator2", "com.android.calculator2.Calculator");
startActivity(intent);
The above answer works, but it does not answer the question. The question is how to launch a calculator implicitly via a category. The stock calculator (not the google play version) has the following in the manifest:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.APP_CALCULATOR" />
</intent-filter>
The problem is simple. If the intent filter is modified as shown below the calculator can be started (tested on Pixel2 running 8.1):
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.APP_CALCULATOR" />
</intent-filter>
The DEFAULT category is required (and this is clearly documented). The problem is an app that wants to start the activity has no control of the manifest in the target activity.
I have a little mystery here, I have this code in my onCreate method:
Intent intent = getIntent();
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
Log.i(TAG, "ACTION_VIEW START");
Uri uri = intent.getData();
SharedPreferences.Editor tEditor = getSharedPreferences("UserFormPreferences", MODE_PRIVATE).edit();
tEditor.putString("GuestRoomNumber", uri.getQueryParameter("h"));
tEditor.putString("GuestSurname", uri.getQueryParameter("a"));
tEditor.apply();
//it shows an alert to the user
GuestLogin(uri.getQueryParameter("h"), uri.getQueryParameter("a"));
Log.i(TAG, "ACTION_VIEW END");
}
And I have this code in my manifest:
<activity
android:name="epinom.jm.smarthotel.vcMainScreen"
android:label="#string/title_activity_home"
android:launchMode="standard"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="epinom.jm.smarthotel.vcMainScreen" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<data android:scheme="com.guestperience" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
And from a web page I'm executing this JS:
window.location = "com.guestperience://?h=x&a=x";
So here comes the funny part, if I plug my phone, and then in Android Studio, I click on the Play or Debug button, and then I go to the Mail App and tap over a hyperlink that takes me to my web page in Chrome that have the JS instruction, it opens My App and open the intent using the onCreate and onStart method like I expect and add it to the stack of intents in My App, this means that if I'm on any intent of my app and I execute the JS, the app comes to the front and it creates the intent and do what it is supposed to do and shows an alert to the user.
But if I pull the plug or I use the .apk that I have in the Play Store in Beta, this functionality does not work, and I don't understand the difference because to me is the same code, so this is what happens when I'm not connected to Android Studio:
If the app is close, I click on the link, it opens Chrome and the the app is started, and the first intent of the app that is the same that I'm calling, do what it is supposed to do and shows the alert.
Once the app is open if I repeat the steps it never shows the intent and it does not matter if I'm in the initial intent or in another intent.
I have tried to change the code to the onStart but it is almost the same behavior:
If the app is close, I click on the link, it opens Chrome and the the app is started, and the fist intent of the app that is the same that I'm calling, do what it is supposed to do and shows the alert.
Once the app is open if I repeat the steps it only shows the alert when I'm in the main intent (the same that I'm calling), if I'm in another intent it never shows the intent, but if I navigate to the intent the Alert is shown every time I call it. (on every onStart, this can be controlled with a bool).
At the end, I don't understand why the behavior is different when I'm plugged to Android Studio.
Maybe is some permission that I'm missing or something that I have to configure, but I'm lost.
Any help will be appreciated.
Thanks.
UPDATE 1:
I have detected this:
If I plug the phone and press play and keep the plug everything works like a charm.
If I plug the phone and press play and remove the plug everything works like a charm.
If I plug the phone and press play and close the app (the plug can be plugged or not) if I start the app with the link works like a charm, but if the app is started stops working on any intent.
There is something that Android Studio is doing that makes it work, I'm thinking that it has to be with permissions but I'm really lost.
UPDATE 2:
I have tried all the options of this examples and I still have the same result, if the app is open i can't get to the intent, but if the app is closed or is plugged to Android Studio works like a charm.
<!-- Allow web apps to launch Barcode Scanner by linking to http://zxing.appspot.com/scan. -->
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http" android:host="guestperience.com" android:path="/Main"/>
</intent-filter>
<!-- Support zxing://scan/?... like iPhone app -->
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="com.guestperience" android:host="Main" android:path="/"/>
</intent-filter>
I have tried to attach it to the launcher intent and nothing seems to work.
<category android:name="android.intent.category.LAUNCHER"/>
I have tried to launch the app from an href, to see if a user action is needed and still the same result.
CLICK HERE TO LOGIN
https://developer.chrome.com/multidevice/android/intents
https://github.com/zxing/zxing/blob/master/android/AndroidManifest.xml
UPDATE 3:
I have added this to track the action that is called once the app is open:
Log.i(TAG, intent.getAction().toString());
If I open my app for the first time the value is:
"com.guestperience://Main/"
But if I open another intent and open the app through the link again the result is the last action I have called i.e.:
"epinom.jm.smarthotel.vcMainScreen"
And of course if I open the app with Android Studio I always get this value:
"com.guestperience://Main/"
Because all the app is configurable through JSON files all my activities have intent filters so all my calls are like:
Intent tIntent = new Intent("epinom.jm.smarthotel.vcMainScreen"); //replacing this "epinom.jm.smarthotel.vcMainScreen" with the JSON string var of course
startActivity(tIntent);
finish();
I have read this too, and as far as I can tell I'm not missing anything:
http://developer.android.com/intl/es/training/app-indexing/deep-linking.html
After doing a lot of tests and reading a lot, I have ended doing a base class that extends Activity and my Main Activity extends from the Base Activity.
public class BaseActivity extends Activity {
}
public class vcMainScreen extends BaseActivity {
}
Then on the onStart() of the Base Activity I have added this code to handle the call from the browser:
#Override
protected void onStart() {
super.onStart();
Intent intent = getIntent();
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
Uri uri = intent.getData();
SharedPreferences.Editor tEditor = getSharedPreferences("UserFormPreferences", MODE_PRIVATE).edit();
tEditor.putString("GuestRoomNumber", uri.getQueryParameter("h"));
tEditor.putString("GuestSurname", uri.getQueryParameter("a").replace("/",""));
tEditor.apply();
Intent tIntent = new Intent("epinom.jm.smarthotel.vcMainScreen");
tIntent.putExtra("Login", "true");
startActivity(tIntent);
finish();
}
}
As you can see it calls the Main Activity an there in the onStart() I have added this lines to call my login method:
#Override
protected void onStart() {
super.onStart();
if (getIntent().getExtras() != null && getIntent().getExtras().getString("Login") != null && getIntent().getExtras().getString("Login").equals("true")) {
SharedPreferences tPrefs = getSharedPreferences("UserFormPreferences", MODE_PRIVATE);
GuestLogin(tPrefs.getString("GuestRoomNumber", ""), tPrefs.getString("GuestSurname", ""));
getIntent().putExtra("Login", "false");
}
}
And in the Manifest I have added this code:
<activity
android:name="epinom.jm.smarthotel.BaseActivity"
android:label="#string/title_activity_home"
android:launchMode="singleTask"
android:screenOrientation="portrait">
<intent-filter>
<data android:scheme="com.guestperience" android:host="Main" android:path="/"/>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="epinom.jm.smarthotel.vcMainScreen"
android:label="#string/title_activity_home"
android:launchMode="standard"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="epinom.jm.smarthotel.vcMainScreen" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Is important that the Base Activity has a launchMode="singleTask", and a the end I have to use a URL like this:
CLICK HERE TO LOGIN
And I'm using this GIT to handle my DeepLink with some changes:
https://github.com/hampusohlsson/browser-deeplink
I'm sure that this is not the correct way of doing this, but I hope this helps someone in the future.
Happy coding to all.
When someone clicks on a link in a webpage of form "com.foo.bar://testtest" I want it to open my unity game and for me to get the testtest data.
I'm an experienced programmer, but when it comes to android I kind of google my way around rather than really understanding anything. Bare that in mind. :)
I can react to links on android using intent-filters. However all the resources I've found have assumed you can extend your main activity to capture the new intent. It's possible to do that with unity, but for various reasons I'd rather not. I tried creating a new activity, exporting it to a jar, and adding this to my manifest in the application tag:
<activity android:name="com.foo.ProtocolCatcher"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<data android:scheme="com.foo.bar" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
</activity>
Clicking on a link successfully launches my game, but onto a black screen.
Edit: I've also tried this format to no change:
<activity android:name="com.foo.ProtocolCatcher"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="com.foo.bar" />
</intent-filter>
</activity>
What are the magic incantations to make the whole game boot, along with my custom activity, and let my custom activity read the incoming URL, without touching the main activity?
I suppose that you are missing a part of the boot sequence; the steps required are the following:
Define the ProtocolCatcher Activity with te proper scheme (OK)
Define the MainActivty, which represents your Unity3D game main Activity (OK)
Start the MainActivity when the ProtocolCatcher Activity gets started (MISSING)
Implementing the third step is super easy; just edit your ProtocolCatcher Activity's onCreate() method:
//ProtocolCatcher
//...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
Intent gameIntent = new Intent(this, MainActivity.class);
/*
//Pass the extra data to the game if needed
Intent sourceIntent = getIntent();
Uri data = sourceIntent.getData();
gameIntent.putExtra("uriData", data != null ? data.toString(): null);
*/
startActivity(gameIntent); //start the real game
finish(); //close the ProtocolCatcher activity
}
Considering the fact that you are "injecting" the ProtocolCatcher Activity manually, if you have problem to refer MainActivity from the ProtocolCatcher onCreate() you can lookup the relative Class using reflection.