Okay so I am creating a twitter clone, the only problem I am having right now is that the callback URL is getting me back to the app but instead giving me a page not found error.
I saw some similar questions here in stackoverflow and followed the steps.
I am getting the Authentication URL using the code:
public String beginAuthorization(){
try{
if(null==currentRequestToken){
currentRequestToken = twitter.getOAuthRequestToken(TWITTER_CALLBACK_URL);
}
return currentRequestToken.getAuthenticationURL();
}catch (TwitterException te){
te.printStackTrace();
}
return null; }
Next I am retrieving the Access Token using the code:
public void setAccessToken(Uri uri) {
if (uri != null && uri.toString().startsWith(TWITTER_CALLBACK_URL)) {
String verifier = uri.getQueryParameter("oauth_token");
try {
AccessToken accessToken = twitter.getOAuthAccessToken(app.currentRequestToken, verifier);
//shared prefs
SharedPreferences.Editor e = yambaSharedPrefs.edit();
e.putString(PREF_KEY_OAUTH_TOKEN, accessToken.getToken());
e.putString(PREF_KEY_OAUTH_SECRET, accessToken.getTokenSecret());
//store log in status
e.putBoolean(PrefSharedTwitterLoggedIn, true);
e.apply();
Intent intent = new Intent(this, StatusActivity.class);
startActivity(intent);
} catch (TwitterException e) {
e.printStackTrace();
}
} }
My Callback URL looks like this:
public static final String OAUTH_CALLBACK_SCHEME = "twitter4j-MiYAMBA";public static final String OAUTH_CALLBACK_HOST = "callback";public static final String TWITTER_CALLBACK_URL = OAUTH_CALLBACK_SCHEME + "://" + OAUTH_CALLBACK_HOST;
I have also added the callback URL in the intent filter, like:
data android:host="callback" android:scheme="twitter4j-MiYAMBA"
Now I am not sure where the problem might be.
Also here is how the control flows through out the app:
StatusActivity is launched when the app is run, it checks if AccessToken are set or not using a function isAuthorised() which is defined in an Android application class named YAMBAapp, if it is defined then it begins the setup of layout, that is making buttons and stuff visible else it passes the control to a function beginAuthorization(), which starts an Activity named AuthorizationActivity, which gets the Authentication URL and passes it to the WebView, all of this is done in the function onResume, in this function I call another function setAccessToken and pass the 'uri' that has has data using:
uri = getIntent().getData();
setAccessToken(uri);
I have pasted the code for setAccessToken above.
Also in the manifest I have defined the "data" item in the intent filter of "AuthorizationActivity" and not the "StatusActivity", though it has no effect what so ever.
Please help, I really am stuck for few days now :)
First thing first, when you launch twitter authentication using default web browser, you will never return back to your main application, once access tokens are received and hence page not found, as url being invalid.
What you need is to load authenticaton using a web view through your own app, now you can override few functioanlities here like when being redirected. here you need to do final processing and terminate web view, which will result into control coming back to your own application rather then seeing page not found in browser.
Example: Here is how you oveerride an webview mechanism, now you create an actvity with theme like dialog or whatever, and load this webview in it with twitter auth url, once user authtenticate himself shouldOverrideUrlLoading will be called, here you retrive back verifier and quit..
webView.setWebViewClient( new WebViewClient()
{
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
// your url pattern here
if( url.contains("callback://twitter4j-MiYAMBA"))
{
Uri uri = Uri.parse( url );
// you get the verifier here
String oauthVerifier = uri.getQueryParameter( "oauth_verifier" );
// Do whateever u want here
..oauthVerifier.
//
// Finish this task, so you return back to activity from where it started
finish();
return true;
}
return false;
}
});
I guess this would be enough to finish rest of implementation. more info here '
http://daiwei.lu/2014/01/22/twitter-oauth-flow-on-android/
Related
I HAVE ALREADY TRIED How to handle intent:// on a webView URL?
This solution just opens up a Google Play Store Web Page in my WebView, what I want is on the click, another app should open whose intent is provided as happens in Chrome.
My app has a WebView that works fine. At one stage, the WebView requests access to the following(an external payment app):
intent://pay/?pa=digitalshowroom1.payu#indus&pn=DOTPE%20PRIVATE%20LIMITED&tr=13261664955&tid=CX0FOrvSrHzDh7gP&am=1.00&cu=INR&tn=OrderId-CX0FOrvSrHzDh7gP
When I use the same website that my WebView is using in Chrome, it opens the external payment app successfully, i.e. Chrome is able to handle that intent, how can my app handle the same intent.
I seem to know I have to use
public boolean shouldOverrideUrlLoading(WebView view, String url)
for this, and I'm using it as follows:
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url != null && (url.startsWith("whatsapp://") || url.startsWith("tel") || url.startsWith("market"))) {
view.getContext().startActivity(
new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
return true;
}
else {
return false;
}
Now, this piece of code is handling the intents like opening WhatsApp, Calling app, etc. fine as they start with whatsapp or tel, so I'm able to leverage the url.startsWith() method.
How can I handle the links that request access to external apps and start with intent://?
Thanks in advance!
I tried something similar and found you have to build the URI like this and handle all URL parameters and call the build method. I did it for a UPI payments app. Call this method in shouldOverrideUrlLoading().
public void openPaymentApp(final String url)
{
try {
String pa= url.substring(url.indexOf("pa=")+3,url.indexOf("&pn"));
String pn=url.substring(url.indexOf("pn=")+3,url.indexOf("&tr"));
String tr=url.substring(url.indexOf("tr=")+3,url.indexOf("&tid"));
String tid=url.substring(url.indexOf("tid=")+4,url.indexOf("&am"));
String am=url.substring(url.indexOf("am=")+3,url.indexOf("&cu"));
String cu=url.substring(url.indexOf("cu=")+3,url.indexOf("&tn"));
String tn=url.substring(url.indexOf("tn=")+3,url.indexOf("#Intent"));
Uri uri =
new Uri.Builder()
.scheme("upi")
.authority("pay")
.appendQueryParameter("pa",pa)
.appendQueryParameter("pn",pn)
.appendQueryParameter("tr",tr)
.appendQueryParameter("tid",tid)
.appendQueryParameter("am",am)
.appendQueryParameter("cu",cu)
.appendQueryParameter("tn",tn)
.build();
Intent launchIntent = getPackageManager()
.getLaunchIntentForPackage( "com.package.name");
launchIntent.setData(uri);
startActivity( launchIntent );
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(),"Coudln't open", Toast.LENGTH_SHORT).show();
}
}
Use below code:
Uri uri = Uri.parse(url);
if (uri.getScheme().equals("intent")) {
String appPackage = getAppPackageFromUri(uri);
if (appPackage != null) {
PackageManager manager = getContext().getPackageManager();
Intent appIntent = manager.getLaunchIntentForPackage(appPackage);
if (appIntent != null) {
getActivity().startActivity(appIntent);
} else {
// open external website
}
}
}
Please use code if any issue let me know
Happy coding!
I am a web developer and am trying to develop an application that basically is a Webview that can receive instructions through push requests to redirect the user to specific pages. It is already functional, I just need to correct an issue:
I have tried to make a function in the class that receives and processes the push information that updates the contents of the Webview. But there is some conflict and it is impossible to do so, because one class is static and the other not due to their inheritance.
The way I found around this was creating an string variable inside my "watch messages class" started with "EMPTY" value that receives the value sent in a specific field within the push request 'date' when the notification is clicked. There's my public class FireBaseWatchMessages that extends FirebaseMessagingService:
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d("LOG_ONRECEIVE_1", "From: " + remoteMessage.getFrom());
if (remoteMessage.getData().size() > 0) {
Log.d("LOG_VALID_DATA", "Message data payload: " + remoteMessage.getData());
}
if (remoteMessage.getNotification() != null) {
Log.d("LOG_NULL_NOTIFICATION", "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
Map<String, String> data = remoteMessage.getData();
sendNotification(remoteMessage);
if (data.containsKey("appReportedAction")) {
Log.d("SET_ACTION", "/appReportedAction/" + data.get("appReportedAction"));
NEW_URL_FROM_ACTION = MainActivity.SSLPROTOCOL + "://" + MainActivity.MAIN_URL +"/appReportedAction/" + data.get("appReportedAction");
}
}
In my MainActivity there's a function to change webview content. It works like this:
public void changeViewContent(String actionView){
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.activity_main_webview);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
if(FireBaseWatchMessages.NEW_URL_FROM_ACTION != "EMPTY"){
mWebView.loadUrl(FireBaseWatchMessages.NEW_URL_FROM_ACTION);
} else {
mWebView.loadUrl( SSLPROTOCOL + "://" + MAIN_URL + actionView);
}
mWebView.setWebViewClient(new HelloWebViewClient());
}
So when the application opens it checks if this variable has a value other than "EMPTY", if so Webview opens the modified URL according to its value, not the default URL.
It happens that when the application is closed when clicking on the message sent by the push the URL doesn't open with the appropriate modifications, as if the variable was not really receiving the value sent by the push.
Using the app debugger I noticed that its log commands do not appear on the console when it is not open, which makes me believe that the function does not really run when the application is closed.
Any idea how I can correct this behavior? How can I make the action of clicking the notification send the parameter to the webview?
I want to first say that your approach is uncommon and I do not recommend storing url in such a manner, since services can be killed/stopped (by user or device) and so you lose your data or the device was turned off so you lose your data. So instead of using variables I have made two methods using Shared Preferences its easy and the storage is permanent in the device even when your app is not in use!
HERE HOW:
The first method is:
public boolean addNewUrl(Context context, String url) {
SharedPreferences sharedPref = context.getSharedPreferences("SHARED URL", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("url", url);
return editor.commit();
}
Define the first method in the FireBaseWatchMessages and it stores the URL and returns true if successfully stored.
And the second is:
public String getUrlAndSetEmpty(Context context) {
SharedPreferences sharedPref = context.getSharedPreferences("SHARED URL", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
String current_url = sharedPref.getString("url", "EMPTY");
editor.putString("url", "EMPTY");
editor.apply();
return current_url;
}
Define this in the MainActivity to get Url returned and also sets the url to "EMPTY" after its takes it!
The first method will be called from the Service FireBaseWatchMessages. This will accept context which for our case it is this or FireBaseWatchMessages.this and it will also accept a URL in form of a string so change your URL into a String. It will then store it in your app internal storage as url!
So just call:
addNewUrl(this,your_url_string);
The second method will be called in the MainActivity or any activity that you want it to work. So define it in the MainActivity. What it does it check if there is a url stored in the storage if it doesn't find any it returns String "EMPTY" and if it finds it it returns it as a current url and also change the value of the stored String to empty because it has already got one. So just call:
String url= getUrlAndSetEmpty(this);
And cheers the url returned can be a really URL STRING OR just a String "EMPTY". Handle the Logic.
This is the best APPROACH for your case! It works any time! It does not depend if the app is visible on foreground or not!
Check your code if you handled the intent correctly on Activity creation!
But also in java when we compare Objects( String included) we use the (Object1.equals(Object2)) instead of (=) sign. So change the line where you called:
if(FireBaseWatchMessages.NEW_URL_FROM_ACTION != "EMPTY")
Change to:
if(!((FireBaseWatchMessages.NEW_URL_FROM_ACTION).equals("EMPTY")))
Do not forget the ! sign there in the condition!
If that doesn't work check the Intent you used to start the Activity.
I am attempting to verify if a user is logged in or not, and if not sending them to a log in page. I am using the log in page template from Android Dev. and trying to use an Intent to send either a Boolean or a value ( 1 for logged in 0 for not). Here is the part of the code in LoginActivity with the Intent:
for (String credential : DUMMY_CREDENTIALS) {
String[] pieces = credential.split(":");
if (pieces[0].equals(mEmail)) {
// Account exists, return true if the password matches.
return pieces[1].equals(mPassword);
final boolean logged_in = true;
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.putExtra("log", logged_in);
startActivity(intent);
}
here I am trying as a Boolean and I am getting the error Unreachable code for the line with final boolean Logged_in = true. When I try as an int
int logged_in =1;
I get the same error. All the questions asked on SO state that I needed to use the current class, LoginActivity.this, instead of just this. When I did use just this, I got another error entirely.
How do I send a value to my MainActivity class to show whether they are logged in or not?
return pieces[1].equals(mPassword);
return ends the method routine so everything after is not reachable.
In Android i have a webview that lead to an google authentication form. When the authentication form is loaded in the webview it will call onReceivedLoginRequest:
public void onReceivedLoginRequest(final AuthenticationWebView client, final WebView view, final String realm,
final String account, final String args) {
...
}
When this method is called i get the Accounts stored on the device and let the user choose one and use that one to retrieve an authtoken:
mAccountManager.getAuthToken(account, mAuthToken, null, mWebViewActivity, this, null);
It all works perfectly fine (i think) and the next step looks good also:
final String result = bundle.getResult().getString(AccountManager.KEY_AUTHTOKEN);
if (result != null) {
// authentication succeeded, new url given as result for redirection
mWebView.loadUrl(result);
} else {
onLoginFailed();
}
A new method is called and returns the new url for redirection which i load in the webview. The result String returns a new adress which looks good but does nothing, it doens't log in but i don't get any message error either from the webview.
Url:
https://accounts.google.com/MergeSession?args=..&uberauth=WILL_NOT_SIGN_IN&source=AndroidWebLogin
I modified the url a bit with (triple)dots, don't know how secure it is and it was not such an interesting part of the url.
Anyone know why the url will not redirect me to the website behind it? When i use this url in my browser it recognizes my account, i only have to fill in my password and it redirects me correctly.
I use a native Android webview and i inject it with javascript but this only happens on the page after the login.
The settings i added to the webview are:
mSettings = getSettings();
mSettings.setJavaScriptEnabled(true);
mSettings.setDomStorageEnabled(true);
mSettings.setAllowFileAccess(true);
mSettings.setGeolocationEnabled(true);
In my application I've got a WebView which might be used to display www.youtube.com or m.youtube.com content. I've got the following code in the onLoadResource callback:
#Override
public void onLoadResource (WebView view, String url)
{
if(matchYouTubeWatchUrl(url))
{
invokeYouTubePlayer(m_context,url);
}
}
The invokeYouTubePlayer function looks like this:
private static void invokeYouTubePlayer(Context c, String url)
{
try
{
Uri uri = Uri.parse(url);
String videoId = uri.getQueryParameter("v");
if(videoId != null)
{
Intent youtubeIntent = new Intent(Intent.ACTION_VIEW);
youtubeIntent.setData(Uri.parse("vnd.youtube://"+videoId));
try
{
c.startActivity(youtubeIntent);
}
catch(ActivityNotFoundException e)
{
Log.e(TAG,"No handler for native youtube - expanding scope");
// Try an alternate approach if there's no youtube app installed
youtubeIntent = new Intent(Intent.ACTION_VIEW);
youtubeIntent.setData(Uri.parse("http://www.youtube.com/watch?v="+videoId));
try
{
c.startActivity(youtubeIntent);
}
catch(ActivityNotFoundException e2)
{
e2.printStackTrace();
}
}
}
}
catch(NullPointerException e)
{
e.printStackTrace();
}
}
What I'm finding is that on most Android devices the first startActivity call invokes the YouTube application, however on KF what I'm seeing is that it invokes the browser which then invokes a video player application.
Not having a KF myself what I'd like to find out is whether there's a URI that can be passed to startActivity which will directly invoke the video player on Kindle Fire without having to pass through the browser as an intermediate step.
Just a observation. There is a better way to detect if a Intent can be called
private boolean isCallable(Intent intent) {
List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
}
Ok just to be clear on KF it never fires first activity then it fires second and then KF takes over and takes you to the YouTube app.
If so all i can think is that your details in first Intent is not correct or for KF its not the same as in other phones/tab