我正在使用移动SoundCloud Web身份验证页面登录到SoundCloud的Android应用程序上工作. SoundCloud移动Web身份验证页面为您提供了使用SoundCloud,Facebook或Google登录的三个选项.该界面如下所示:
到目前为止,我可以使用SoundCloud和Facebook凭据登录,但是使用Google时失败.这是我正在做的删节版:
public class SoundCloudActivity extends Activity { ... @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.twitter_login_layout); ... loadingProgressbar = (Progressbar) findVIEwByID(R.ID.loading_progressbar); WebVIEw webVIEw = (WebVIEw) findVIEwByID(R.ID.login_webvIEw); webVIEw.setVerticalScrollbarEnabled(true); webVIEw.setHorizontalScrollbarEnabled(true); webVIEw.setWebVIEwClIEnt(new SoundclouDWebVIEwClIEnt()); webVIEw.getSettings().setJavaScriptEnabled(true); webVIEw.getSettings().setAllowfileAccess(true); webVIEw.getSettings().setPluginState(PluginState.ON); webVIEw.getSettings().setJavaScriptCanopenwindowsautomatically(true); authUrl = API.wrapper.authorizationCodeUrl(Endpoints.CONNECT, Token.ScopE_NON_EXPIRING).toString(); webVIEw.loadUrl(authUrl); } private class SoundclouDWebVIEwClIEnt extends WebVIEwClIEnt { public boolean shouldOverrIDeUrlLoading(WebVIEw vIEw, String url) { Log.d(TAG, "shouldOverrIDeUrlLoading(): url: "+url); if (url.startsWith(REDIRECT_URI.toString())) { Uri result = Uri.parse(url); new Thread(new Runnable() { @OverrIDe public voID run() { try { token = API.wrapper.authorizationCode(code, Token.ScopE_NON_EXPIRING); } catch (IOException e) { e.printstacktrace(); } ... } }).start(); return true; } else if (url.startsWith("authorize")) { return false; } else if (url.startsWith("http")) { vIEw.loadUrl(url); } return true; } @OverrIDe public voID onReceivedError(WebVIEw vIEw, int errorCode, String description, String failingUrl) { Log.d(TAG, "Call one rror with error: "+description); super.onReceivedError(vIEw, errorCode, description, failingUrl); } @OverrIDe public voID onPageStarted(WebVIEw vIEw, String url, Bitmap favicon) { Log.d(TAG,"onPageStarted(): url: "+url+" favicon: "+favicon); loadingProgressbar.setVisibility(Progressbar.VISIBLE); super.onPageStarted(vIEw, url, favicon); } @OverrIDe public voID onPageFinished(WebVIEw vIEw, String url) { loadingProgressbar.setVisibility(Progressbar.GONE); super.onPageFinished(vIEw, url); } }}
选择使用Google时,它会将我重定向到熟悉的Google登录页面.然后,当我输入用户名和密码时,它会将我重定向到空白页面,并且不执行任何 *** 作,包括不向我提供身份验证令牌.这是登录后生成的空白页面的示例URL:
https://accounts.google.com/o/oauth2/auth?client_id=984739005367.apps.googleusercontent.com&redirect_uri=postmessage&response_type=code%20token%20id_token%20gsession&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fplus.login%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&state=539399140%7C0.873620491&access_type=offline&request_visible_actions=http%3A%2F%2Fschemas.google.com%2FAddActivity%20http%3A%2F%2Fschemas.google.com%2FListenActivity%20http%3A%2F%2Fschemas.google.com%2FCreateActivity&after_redirect=keep_open&cookie_policy=single_host_origin&include_granted_scopes=true&proxy=oauth2relay763648117&origin=https%3A%2F%2Fsoundcloud.com&
我想知道WebVIEw中是否缺少我需要的设置.我已经必须使其他人能够使用SoundCloud移动网页中的其他功能.任何建议将不胜感激.
解决方法:
因此,Google使用跨站点JavaScript注入来完成身份验证过程,这要求在Google身份验证过程中仍打开SoundCloud登录窗口.要解决此问题,您需要强制/允许Google身份验证进入新的WebvIEw窗口.我在github上创建了一个演示项目,该项目显示了整个过程here.
这是完成工作的课程,请查看全文以获取更多详细信息:
package com.bulwinkel.soundcloudlogin;import androID.content.Context;import androID.content.DialogInterface; import androID.graphics.Bitmap;import androID.graphics.color;import androID.net.Uri;import androID.os.Build;import androID.os.Bundle;import androID.os.Message;import androID.support.v7.app.AlertDialog;import androID.support.v7.app.AppCompatActivity;import androID.util.Log;import androID.vIEw.VIEw;import androID.vIEw.VIEwGroup;import androID.webkit.cookieManager;import androID.webkit.cookieSyncManager;import androID.webkit.WebChromeClIEnt;import androID.webkit.WebSettings;import androID.webkit.WebVIEw;import androID.webkit.WebVIEwClIEnt;import androID.Widget.FrameLayout;import androID.Widget.Progressbar;import androID.Widget.relativeLayout;public class SoundCloudLoginActivity extends AppCompatActivity { private static final String TAG = SoundCloudLoginActivity.class.getSimplename(); //todo - create a project in the SoundCloud developer portal: https://soundcloud.com/you/apps/ private static final String CALLBACK_SCHEME = "soundcloudlogindemo://authentication.complete"; //todo - replace private static final String CLIENT_ID = "e64276127b07b38ddfaf1ee458ffc2ac"; //todo - replace private static final String STATE = SoundCloudLoginActivity.class.getCanonicalname(); @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.activity_main); // clear the cookies to make sure the that the user is properly logged out if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LolliPOP_MR1) { final cookieManager cookieManager = cookieManager.getInstance(); cookieManager.removeAllcookies(null); cookieManager.flush(); } else { cookieSyncManager.createInstance(getApplicationContext()).startSync(); final cookieManager cookieManager = cookieManager.getInstance(); cookieManager.removeAllcookie(); cookieManager.removeSessioncookie(); } // SoundCloud oauth url final Uri authUri = new Uri.Builder().scheme("https") .authority("soundcloud.com") .appendpath("connect") .appendqueryParameter("scope", "non-expiring") .appendqueryParameter("response_type", "code") .appendqueryParameter("state", STATE) .appendqueryParameter("display", "popup") .appendqueryParameter("clIEnt_ID", CLIENT_ID) .appendqueryParameter("redirect_uri", CALLBACK_SCHEME) .build(); Log.d(TAG, "https://soundcloud.com/connect?scope=non-expiring&response_type=code&state=Boxset.soundCloudLoginActivity&display=popup&clIEnt_ID=6d483c5c02062da985379c36b5e7da95&redirect_uri=http%3A%2F%2Fwonder.fm%2Fincoming%2Fsoundcloud%2Fauth%2F"); Log.d(TAG, authUri.toString()); // we need a handle to this to add the second webvIEw during Google plus login final FrameLayout container = (FrameLayout) findVIEwByID(R.ID.container); // progress hud adds itself to the vIEw hIErarchy final LoadingHud loadingHud = new LoadingHud(container); final WebVIEw webVIEw = createWebVIEw(this); webVIEw.loadUrl(authUri.toString()); final WebVIEwClIEnt webVIEwClIEnt = new WebVIEwClIEnt() { // need to use the depricated method if you are supporting less than API 21 @OverrIDe public boolean shouldOverrIDeUrlLoading(WebVIEw vIEw, String url) { //GUARD - been stung by this if (url == null) return false; //GUARD - check if we have got our callback url yet // this occurs when navigating to facebook and Google plus login screens if (!url.contains(CALLBACK_SCHEME)) return false; final Uri uri = Uri.parse(url); //GUARD // the state query parameter is echoed back to us so we // kNow that the code is coming from a legitimate source final String state = uri.getqueryParameter("state"); if (!STATE.equals(state)) return false; //GUARD final String code = uri.getqueryParameter("code"); if (code == null) { // something went wrong during the auth process // you need to handle this Log.d(TAG, "No code returned from auth process"); return false; } // you Now have you code to use in the next step of the oauth process Log.i(TAG, "code = " + code); new AlertDialog.Builder(vIEw.getContext()) .setTitle("Auth Successful") .setMessage("Code: " + code) .setPositivebutton("OK", new DialogInterface.OnClickListener() { @OverrIDe public voID onClick(DialogInterface dialogInterface, int i) { finish(); } }) .create() .show(); return true; } @OverrIDe public voID onPageStarted(WebVIEw vIEw, String url, Bitmap favicon) { super.onPageStarted(vIEw, url, favicon); loadingHud.show(); } @OverrIDe public voID onPageFinished(WebVIEw vIEw, String url) { super.onPageFinished(vIEw, url); loadingHud.hIDe(true); } }; webVIEw.setWebVIEwClIEnt(webVIEwClIEnt); // require for Google login // Google login requires that the SoundCloud login window be open at the same time // as it uses cross window/site JavaScript injection to pass information back to // SoundCloud on completion webVIEw.setWebChromeClIEnt(new WebChromeClIEnt() { @OverrIDe public boolean onCreateWindow(WebVIEw vIEw, boolean isDialog, boolean isUserGesture, Message resultMsg) { // this WebVIEw has to has the same settings as the original for // the cross site JavaScript injection to work final WebVIEw GoogleSignInWebVIEw = createWebVIEw(vIEw.getContext()); GoogleSignInWebVIEw.setWebChromeClIEnt(this); GoogleSignInWebVIEw.setWebVIEwClIEnt(webVIEwClIEnt); container.addVIEw(GoogleSignInWebVIEw); // this is the glue code that wires the original webvIEw // and the new webvIEw together so they can communicate final WebVIEw.WebVIEwTransport transport = (WebVIEw.WebVIEwTransport) resultMsg.obj; transport.setWebVIEw(GoogleSignInWebVIEw); resultMsg.sendToTarget(); // this advises that we have actually created and displayed the new window return true; } // since we added the window we also have to handle removing it @OverrIDe public voID onCloseWindow(WebVIEw window) { container.removeVIEw(window); } }); container.addVIEw(webVIEw); } /** * @param context the WebVIEw must be given an activity context (instead of application context) * or it will crash in versions less than 4.4 * * @return a {@link WebVIEw} suitable for the soundcloud login process */ private static WebVIEw createWebVIEw(Context context) { final WebVIEw webVIEw = new WebVIEw(context); final WebSettings settings = webVIEw.getSettings(); // this allows the username and password valIDation to work settings.setJavaScriptEnabled(true); // these 2 are for login with Google support // which needs to open a second window settings.setJavaScriptCanopenwindowsautomatically(true); settings.setSupportMultiplewindows(true); // prevent caching of user data settings.setSaveFormData(false); // prevents the webvIEw asking the user if they want to save their password // needed for pre 18 devices settings.setSavePassword(false); return webVIEw; } private static class LoadingHud { private final relativeLayout container; public LoadingHud(VIEwGroup parentVIEw) { container = new relativeLayout(parentVIEw.getContext()); container.setAlpha(0); parentVIEw.addVIEw(container); final VIEwGroup.LayoutParams layoutParams = container.getLayoutParams(); layoutParams.height = VIEwGroup.LayoutParams.MATCH_PARENT; layoutParams.wIDth = VIEwGroup.LayoutParams.MATCH_PARENT; container.setLayoutParams(layoutParams); addMask(container); addProgressbar(container); } private voID addMask(relativeLayout container) { final VIEw vIEw = new VIEw(container.getContext()); vIEw.setBackgroundcolor(color.WHITE); vIEw.setAlpha(.5f); container.addVIEw(vIEw); final relativeLayout.LayoutParams layoutParams = (relativeLayout.LayoutParams) vIEw.getLayoutParams(); layoutParams.height = VIEwGroup.LayoutParams.MATCH_PARENT; layoutParams.wIDth = VIEwGroup.LayoutParams.MATCH_PARENT; vIEw.setLayoutParams(layoutParams); } private voID addProgressbar(relativeLayout container) { final Progressbar progressbar = new Progressbar(container.getContext()); container.addVIEw(progressbar); final relativeLayout.LayoutParams layoutParams = (relativeLayout.LayoutParams) progressbar.getLayoutParams(); layoutParams.addRule(relativeLayout.CENTER_IN_PARENT); progressbar.setLayoutParams(layoutParams); } voID show() { container.bringToFront(); container.animate().Alpha(1f).start(); } voID hIDe(Boolean animated) { float noAlpha = 0f; if (animated) { container.animate().Alpha(noAlpha).start(); } else { container.setAlpha(noAlpha); } } }}
总结 以上是内存溢出为你收集整理的使用Google的Soundcloud API移动OAUTH登录无法在Android上运行全部内容,希望文章能够帮你解决使用Google的Soundcloud API移动OAUTH登录无法在Android上运行所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)