使用Google+的Soundcloud API移动OAUTH登录无法在Android上运行 [英] Soundcloud API mobile OAUTH login using Google+ isn't working on Android

查看:126
本文介绍了使用Google+的Soundcloud API移动OAUTH登录无法在Android上运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个使用移动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 onError 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+,它重定向我熟悉的谷歌登录页面.然后,当我输入用户名和密码时,它会将我重定向到空白页面,并且不执行任何操作,包括不向我提供身份验证令牌.这是登录后生成的空白页面的示例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&p>

我想知道WebView中是否缺少某个设置.我已经必须使其他人能够使用SoundCloud移动网页中的其他功能.任何建议将不胜感激.

因此,Google +使用跨站点javascript注入来完成身份验证过程,这要求在Google身份验证过程中仍打开SoundCloud登录窗口.要解决此问题,您需要强制/允许Google身份验证进入新的Webview窗口.我在github上创建了一个演示项目,它在此处中显示了整个过程.

这是完成工作的课程,请查看全文以获取更多详细信息:

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);
      }
    }
  }
}

I am working on an Android application that uses the mobile SoundCloud web auth page to log in to SoundCloud. The SoundCloud mobile web auth page provides you with three options for logging in, using SoundCloud, Facebook, or Google+. The interface looks like so:

So far I can log in using my SoundCloud and my Facebook credentials but I fail when using Google+. Here's an abridged version of what I am doing:

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 onError 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);
        }
    }
}

When choosing to use Google+, it redirects me to the familiar Google login page. Then when I enter my username and password, it redirects me to a blank page and does nothing including not providing me with an auth token. This is a sample URL of the blank page that is generated after logging in:

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&

I'm wondering if there is a setting that I'm missing in WebView . I've already had to enable others to get other features in the SoundCloud mobile web page working. Any suggestions would be very much appreciated.

解决方案

So Google+ uses cross-site javascript injection to complete the authentication process which requires that the SoundCloud login window still be open during the Google auth process. To handle this you need to force/allow the Google auth into a new webview window. I created a demo project on github that shows the whole process here.

This is the class that does the work, look at comments throughout for more details:

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上运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆