Oauth Callback not found after allowing the app on Twitter - android

Hey. I am developing an application using the Twitter4j api. In order to allow the application and get an access token, I launch the browser with the callback parameters which I had set in the manifest file.
<data android:scheme="scheme" android:host="authenticatorapp"></data>
After allowing the application, the browser calls the following and fails with a not found message.
scheme://authenticatorapp?oauth_token=n5vd99dfnmnf...
I tried it both on the emulator and the device.
In the emulator, LogCat gives me this :
12-12 15:04:05.743: ERROR/browser(230): onReceivedError -10 scheme://authenticatorapp?oauth_token=Jj...M&oauth_verifier=3ZfuY... The protocol is not supported.
-- The manifest file :
<activity android:name=".AuthenticatorApp"
android:launchMode="singleInstance"
>
<intent-filter>
<category android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.LAUNCHER" />
<data android:scheme="scheme" android:host="authenticatorapp"></data>
</intent-filter>
</activity>
<!-- Broadcast Receiver that will process AppWidget updates -->
<receiver android:name=".ZaytungWidget" android:label="#string/widget_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/tweet_metadata" />
</receiver>
<!-- Service to perform web API queries -->
<service android:name=".ZaytungWidget$UpdateService" />
</application>
<uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.INTERNET" />

Can you please post the whole manifest file?
I found the following question which may be useful later on: OAuth instance state in Android
The question linked to the following example application, which may be helpful:
http://code.google.com/p/jpoco/source/browse/trunk/jpoco-android-app/AndroidManifest.xml

This is what I have in my working Manifest.xml, where org.gpsagenda.OAUTH is the activity doing the Authenticating.
<activity android:name="org.gpsagenda.OAUTH" >
<intent-filter>
<action android:name="android.intent.action.VIEW"></action>
<category android:name="android.intent.category.DEFAULT"></category>
<category android:name="android.intent.category.BROWSABLE"></category>
<data android:scheme="gpsagenda" android:host="twitt" />
</intent-filter>
</activity>

If you're developing a native app, you don't use the callback parameters, but need to let the user enter the pin in your app somewhere - which he gets when you open the authorization_url in a browser or probably more comfortably within your app in a webview.
You could also automatically fetch the pin after the user has clicked on 'yes' in the authorization twitter webpage, but not sure if it's against the twitter ToS.

Related

How to open an Android application from a webpage

I'm currently trying to open an Android application from a webpage. And to pass two parameters.
I went for the intent solution as it seems that custom scheme are not recommended, and in this case, I don't need a deeplink.
Currently, in debug, the only thing that happens is that my intent url is opened inside chrome and display a white page.
It never opens the application.
This is my AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.MyApp">
<application android:allowBackup="true" android:icon="#mipmap/appicon" android:roundIcon="#mipmap/appicon_round" android:supportsRtl="true">
<activity
android:name="com.MyApp.activity.MainActivity"
android:exported="true"
android:label="MyApp">
<intent-filter>
<action android:name="com.MyApp.LAUNCH"></action>
<category android:name="android.intent.category.DEFAULT"></category>
<category android:name="android.intent.category.BROWSABLE"></category>
<data android:scheme="MyScheme" android:host="MyHost" android:path="/"/>
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
This is my javascript:
if (navigator.userAgent.match(/Android/i)) {
var uri = "intent://MyApp#Intent;scheme=MyScheme;action=com.MyApp.LAUNCH;package=com.MyApp;S.p=" + p + ";S.c=" + c + ";end";
window.open(uri);
}
I've seen a lot of way of doing this and tried a lot of things, but I don't get what is the good way to do with API 33.
I tried to use "intent:#Intent", "intent://#Intent", I tried with and without data property under activity, I tried my own scheme "MyScheme://".
I would like to avoid using deeplink as I would like to keep my website accessible without launching the app (different goals).
You need to check Handling Android App Link documentation.
Basically, to open the app you need to specify some specific scheme, for example:
<activity
android:name=".MyMapActivity"
android:exported="true"
...>
<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="myapp" />
</intent-filter>
</activity>
And the link to open will be: myapp://anypath_here?param1=value1&param2=value2
Try to use a unique scheme, otherwise, you will have an 'Open with..' dialog opening if another app can open it.
To enable link handling verification for your app, add intent filters that match the following format:
<!-- Make sure you explicitly set android:autoVerify to "true". -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- If a user clicks on a shared link that uses the "http" scheme, your
app should be able to delegate that traffic to "https". -->
<data android:scheme="http" />
<data android:scheme="https" />
<!-- Include one or more domains that should be verified. -->
<data android:host="..." />
</intent-filter>
More information you can refer to Verify Android App Links.

App already published onto Google Play but unable to use Google Voice Actions

I am unable to successfully use the Google System Voice Actions "Search in App" (com.google.android.gms.actions.SEARCH_ACTION) on an app that I have already published onto Google Play (Private Channel) and downloaded onto my phone.
The intent with the query extra from the search action is to be passed on to MainActivity after matching the intent filter.
Before publishing the app, I have already tested the app using the adb command below which works perfectly:
adb shell am start -a "com.google.android.gms.actions.SEARCH_ACTION" --es query "[query]" -n "com.testapp/.MainActivity"
Below is my Android manifest which contains the intent filters:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.testapp" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="23" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name=".app.AppController"
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:allowTaskReparenting="true">
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:exported="true"
android:launchMode="singleTop" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="com.google.android.gms.actions.SEARCH_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.VOICE" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.VOICE" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.VOICE" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="#xml/searchable" />
<meta-data
android:name="android.app.default_searchable"
android:value=".MainActivity" />
</activity>
</application>
</manifest>
Are my intent filters required for Google Voice Actions set up correctly, and if so, why did using Google App to search for keywords within my app not work? Or are there any other considerations such as (some personal guesses only): time needed for Google App to "cache/process" app contents/intent filters etc., the app name and search keywords not being "unique" enough, or the fact that the app being distributed onto a Private Channel instead?
Hoping for anyone who has successfully implemented Google Voice Actions before to share and provide some input.
I have found the answer from this blogpost which states the following:
Voice Actions that use your specific app name require you to have the app placed publicly in the app store so the name can get indexed by Google.
which, if accurate, would imply that Google will need time to associate the name of the app for the command "search for [keyword] in [app name]" to be successful, even after the app has been published. This would be more effective if the app is public and not in a Google Play private channel.

Open activity after intent 'click on phone number'

I found several answers on this issue, but it's not working for me. If you click a phone number in an email or on a website, a default dialer popup comes up to select the dialer/skype etc.
I'm trying to get my app in that list - so I don't want to handle the actual call, but open the activity and show the number the user clicked on.
I've tried this:
<receiver android:name=".MyOutgoingCallHandler">
<intent-filter>
<action android:name="android.intent.action.ACTION_DIAL" />
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
But it's not showing in the list. What intent should I filter for?
If you want to add an Activity to the list of Activitys that will be shown to the user as possible phone dialers, you need to have an Activity and the <activity> definition must contain this intent-filter> in the manifest:
<activity ...>
<intent-filter>
<action android:name="android.intent.action.DIAL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
What you've got is a BroadcastReceiver that will receive the outgoing call Intent. That's something different.
The official Android Developers blog has covered this process. You can read all about it there.
Your intent filter looks like it has the correct action, so it may be that you have not requested the correct Android permission.
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
Here is how the Android Developers blog suggest you declare the broadcast receiver.
<manifest>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<application>
...
<receiver android:name=MyOutgoingCallHandler">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
...
</application>
</manifest>

Android > 4.4.2 - Setting Default SMS App

I've been walking through the steps required to allow Android to recognize an app as a potential default Messaging (SMS/MMS) app detailed here and I've followed through on several posts on SO that have up-voted answers that fallback to the instructions outlined on the blog posting.
However, even after following these instructions, which I believe I have done so correctly, I'm still not able to get my app to appear in the system dialog which will allow me to choose which app I want as the default Messaging client. I can't help but feel like I'm still missing something in the manifest but I'm not too sure. If anyone has any advice on this, I'd really appreciate it.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gregfmartin.smsdemo">
<uses-sdk android:minSdkVersion="19"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application android:icon="#drawable/icon"
android:label="#string/app_name"
android:name=".ApplicationCore"
android:theme="#style/SmsDemo">
<!-- Listens for incoming SMS Messages -->
<receiver android:name=".components.receivers.SmsReceiver"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_DELIVER"/>
</intent-filter>
</receiver>
<!-- Listens for incoming MMS Messages -->
<receiver android:name=".components.receivers.MmsReceiver"
android:permission="android.permission.BROADCAST_WAP_PUSH">
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_DELIVER"/>
<data android:mimeType="application/vnd.wap.mms-message"/>
</intent-filter>
</receiver>
<!-- Activity -->
<activity android:name=".Main">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".components.activities.ConversationThreadViewer">
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<action android:name="android.intent.action.SENDTO"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="sms"/>
<data android:scheme="smsto"/>
<data android:scheme="mms"/>
<data android:scheme="mmsto"/>
</intent-filter>
</activity>
<!-- Headless SMS Handler -->
<service android:name=".components.services.HeadlessSmsSenderService"
android:permission="android.permission.SEND_RESPONSE_VIA_MESSAGE"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="sms"/>
<data android:scheme="smsto"/>
<data android:scheme="mms"/>
<data android:scheme="mmsto"/>
</intent-filter>
</service>
</application>
</manifest>
You need to add the category
android.intent.category.APP_MESSAGING
Refer http://developer.android.com/reference/android/content/Intent.html#CATEGORY_APP_MESSAGING
I finally figured out what was going on. I know I kicked myself after I figured it out and facepalmed for about ten minutes.
The Service, HeadlessSmsSenderService, the permission is supposed to be android.permission.SEND_RESPOND_VIA_MESSAGE not android.permission.SEND_RESPONSE_VIA_MESSAGE.
Respond/Response
Seriously? Send Respond?
What caught it was I copied and pasted the manifest from the Google Blog Post and just made a new app really quick that used it and low and behold, it showed up in the system dialog. So then I ran a diff against it and my manifest and everything matched up save for that misspelling (and the organizational changes that I had).
The nasty part about this is that there are some permissions and Intent Actions that IntelliJ won't automatically catch while you're typing them. I'm also not sure if Lint will catch these types of semantic errors or not. For all intents and purposes, the app will compile and run cleanly. No output was found on logcat so really this was a near totally silent issue.
Thanks for all of your help!

Intent Filter to Launch My Activity when custom URI is clicked

I am trying to allow a URI to be registered to open up with my app. Like the PatternRepository on the Blackberry and the CFBundleURLName/CFBundleURLSchemes on the iPhone. How do I achieve the same results on the Android?
The system will be sending emails with the following link: myapp://myapp.mycompany.com/index/customerId/12345. The idea is that the user should be able to click on the link to open up the customer activity in the application.
I've tried numerous suggestions from other SO posts but I cannot get the OS to recognize the pattern and open my app.
On The Gmail app it looks like this: myapp://myapp.mycompany.com/index/customerId/12345. It recognizes and underlines the myapp.mycompany.com/index/customerId/12345 portion of the link and it opens it in a browser. The myapp:// part is not linkified.
The standard mail application treats the entire link as plain text.
What am I missing here?
PS: I've already looked at
How to implement my very own URI scheme on Android
and How to register some URL namespace (myapp://app.start/) for accessing your program by calling a URL in browser in Android OS?
The Manifest:
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="2"
android:versionName="0.0.8"
package="com.mycompany.myapp.client.android">
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="7"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application
android:label="#string/app_name"
android:name="myappApplication"
android:icon="#drawable/ic_icon_myapp"
android:debuggable="true">
<activity
android:label="My App"
android:name=".gui.activity.LoginActivity"
label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".gui.activity.CustomerDetailActivity" >
<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="myapp"/>
</intent-filter>
</activity>
<activity android:name=".gui.activity.CustomerDetailActivity"/>
<activity android:name=".gui.activity.CustomerImageViewerActivity" />
<activity android:name=".gui.activity.CustomerListActivity" android:configChanges="orientation|keyboardHidden"/>
<activity android:name=".gui.activity.HomeActivity" android:configChanges="orientation|keyboardHidden"/>
<activity android:name=".gui.activity.AboutActivity" android:configChanges="orientation|keyboardHidden"/>
<activity android:name=".gui.activity.AccountActivity" android:configChanges="orientation|keyboardHidden" />
</application>
</manifest>
The final solution was a hacky workaround to cover all bases. The email now also contains an attachment with an extension that is registered to open with the app.
AndroidManifest.xml :
<activity android:name=".gui.activity.CustomerDetailActivity" >
<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="https"
android:host="myapp.mycompany.com" />
</intent-filter>
<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="myapp"
android:host="myapp.mycompany.com" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.EDIT" />
<action android:name="android.intent.action.PICK" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:mimeType="application/myapp" />
</intent-filter>
</activity>
When I was working on OAuth with Google Calendar, I had to add this filter to the Activity I wanted to receive the callback:
<intent-filter>
<action android:name="android.intent.action.VIEW"></action>
<category android:name="android.intent.category.DEFAULT"></category>
<category android:name="android.intent.category.BROWSABLE"></category>
<data android:scheme="yourapp" android:host="goog"></data>
</intent-filter>
The when the browser invoked the yourapp://goog URL, it would return to my Activity.
You can get around the issue of GMail not linking non-standard protocols by using a standard HTTP URL with a 302 redirect. You could either set it up on your website's webserver or application server, or for the quick and dirty test you could use a URL shortener like http://bit.ly.
This is solution for me. Thanks #DanO
<intent-filter>
<data android:scheme="yourcustomname"/>
<data android:host="*"/>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
Have you dried adding a category to your intent-filter:
<category android:name="android.intent.category.BROWSABLE" />
You could always try sending your emails using HTML and then use an <a> tag around to create the URL. I don't think there is a way to change the way the Gmail or Mail parse their text, since they probably use the Linkify class.
Another option would be use use http:// and then just parse for a specific custom subdomain which would provide your users with the option to open in a browser or your application.
I just ran into this also, but for standard http: scheme urls. Gmail doesn't appear to add any categories to the Intent. Now I check for BROWSABLE, but I also include a check for !intent.hasCategories() and allow that to go through as well.

Categories

Resources