原文 http://www.learn2crack.com/2014/01/android-oauth2-webview.html?utm_source=tuicool


OAuth is an open standard for authorization. OAuth2 authorization uses access token to access APIs instead of using username and password. In OAuth2 method we would initially request Authorization code from the Authority using scope, redirect URL, and client id,then exchange the code with client id and client secret to get access token and refresh token. In Android WebView method can be applicable for all types of Services. In this tutorial we are going to see how to perform OAuth2 authorization in Android using WebView to obtain the Access Token for performing API calls. To perform OAuth2 Authorization using Android AccountManager refer the tutorialAndroid Google OAuth2 using AccountManager and making API calls

Enable Google API for making Request

1. Go toGoogle API Console.
2. Create a new project. In the Dialog give a Project name and Project- ID, then press next.

3.In the APIs & auth pane Turn on a Service. Here I am enabling URL Shortener API.
4. In the credentials pane selectCREATE NEW CLIENT ID.
5. Select Application type as Installed application and select Installed application type as Other.
6. Finally select Create client ID.
8. Now your application is eligible for making API calls. Note down the Client Id and Client Secret.

Creating Project

Create a new project in eclipse as File->New->Android Application Project. In the Dialog give Application name and Package name. Create the Main Activity asMainActivity.javaand Main layout asactivity_main.xml. Here my applicaion name isWebOAuth2and my package name islearn2crack.weboauth2.

Download Complete Project

WebOAuth2
WebOAuth2.zip
Version: 1.0
1.4 MiB
324 Downloads
DETAILS

Creating Layout

The layout has a single button widget to start the WebView dialog.

activity_main.xml

< LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android" xmlns:tools = "http://schemas.android.com/tools" android:layout_width = "match_parent" android:layout_height = "match_parent" android:orientation = "vertical" tools:context = ".MainActivity" > < TextView android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_gravity = "center" android:textSize = "25sp" android:text = "Google OAuth2 WebView" /> < Button android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_gravity = "center" android:id = "@+id/auth" android:text = "Sign in with Google" /> < TextView android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:id = "@+id/Access" android:autoLink = "all" android:textIsSelectable = "true" android:layout_gravity = "center" android:textSize = "10sp" /> </ LinearLayout >

The next layout is for WebView dialog. It contains a WebView widget which loads the Authorization webpage.

auth_dialog.xml

<? xml version = "1.0" encoding = "utf-8" ?> < LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android" android:layout_width = "match_parent" android:layout_height = "match_parent" android:orientation = "vertical" > < WebView android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:id = "@+id/webv" /> </ LinearLayout >

Creating Activity

Before proceeding to the MainActivity class we must create aGetAccessTokenclass which makes http request with the authorization code to get the Access Token, Time, Refresh Token inJSONformat. The http request has five parameters which should be in url form encoded format.

GetAccessToken.java

package learn2crack.weboauth2; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.json.JSONException; import org.json.JSONObject; import android.util.Log; public class GetAccessToken { static InputStream is = null ; static JSONObject jObj = null ; static String json = "" ; public GetAccessToken() { } List<NameValuePair> params = new ArrayList<NameValuePair>(); Map<String, String> mapn; DefaultHttpClient httpClient; HttpPost httpPost; public JSONObject gettoken(String address,String token,String client_id,String client_secret,String redirect_uri,String grant_type) { // Making HTTP request try { // DefaultHttpClient httpClient = new DefaultHttpClient(); httpPost = new HttpPost(address); params.add( new BasicNameValuePair( "code" , token)); params.add( new BasicNameValuePair( "client_id" , client_id)); params.add( new BasicNameValuePair( "client_secret" , client_secret)); params.add( new BasicNameValuePair( "redirect_uri" , redirect_uri)); params.add( new BasicNameValuePair( "grant_type" , grant_type)); httpPost.setHeader( "Content-Type" , "application/x-www-form-urlencoded" ); httpPost.setEntity( new UrlEncodedFormEntity(params)); HttpResponse httpResponse = httpClient.execute(httpPost); HttpEntity httpEntity = httpResponse.getEntity(); is = httpEntity.getContent(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { BufferedReader reader = new BufferedReader( new InputStreamReader( is, "iso-8859-1" ), 8 ); StringBuilder sb = new StringBuilder(); String line = null ; while ((line = reader.readLine()) != null ) { sb.append(line + "n" ); } is.close(); json = sb.toString(); Log.e( "JSONStr" , json); } catch (Exception e) { e.getMessage(); Log.e( "Buffer Error" , "Error converting result " + e.toString()); } // Parse the String to a JSON Object try { jObj = new JSONObject(json); } catch (JSONException e) { Log.e( "JSON Parser" , "Error parsing data " + e.toString()); } // Return JSON String return jObj; } }

In the MainActivity we useWebViewClientto get the authorization code by loading the URL. The authorization URL should be in the form of

"https: //accounts.google.com/o/oauth2/auth? scope=email%20profile& redirect_uri=urn:ietf:wg:oauth: 2.0 :oob& response_type=code& client_id=CLIENT_ID"

After obtaining the Authorization code we are againg requesting Google for Access Token with the five parameters.”code,client_id,client_secret,redirect_uri,grant_type”. After obtaining the Access Token, Refresh Token,Expiration Time we are displayng it in TextView. You can use this Access Token to access Google APIs such as Maps,Translator etc..

MainActivity.java

package learn2crack.weboauth2; import org.json.JSONException; import org.json.JSONObject; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.app.Activity; import android.app.Dialog; import android.app.ProgressDialog; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Bitmap; import android.util.Log; import android.view.View; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { private static String CLIENT_ID = "842537427973-a381vrch0t5cgrgvtr02lik77a5bc8o7.apps.googleusercontent.com" ; //Use your own client id private static String CLIENT_SECRET = "EEOeMFHQpLtaHDU4Rr8k-l3N" ; //Use your own client secret private static String REDIRECT_URI= "http://localhost" ; private static String GRANT_TYPE= "authorization_code" ; private static String TOKEN_URL = "https://accounts.google.com/o/oauth2/token" ; private static String OAUTH_URL = "https://accounts.google.com/o/oauth2/auth" ; private static String OAUTH_SCOPE= "https://www.googleapis.com/auth/urlshortener" ; //Change the Scope as you need WebView web; Button auth; SharedPreferences pref; TextView Access; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); pref = getSharedPreferences( "AppPref" , MODE_PRIVATE); Access =(TextView)findViewById(R.id.Access); auth = (Button)findViewById(R.id.auth); auth.setOnClickListener( new View.OnClickListener() { Dialog auth_dialog; @Override public void onClick(View arg0) { // TODO Auto-generated method stub auth_dialog = new Dialog(MainActivity. this ); auth_dialog.setContentView(R.layout.auth_dialog); web = (WebView)auth_dialog.findViewById(R.id.webv); web.getSettings().setJavaScriptEnabled( true ); web.loadUrl(OAUTH_URL+ "?redirect_uri=" +REDIRECT_URI+ "&response_type=code&client_id=" +CLIENT_ID+ "&scope=" +OAUTH_SCOPE); web.setWebViewClient( new WebViewClient() { boolean authComplete = false ; Intent resultIntent = new Intent(); @Override public void onPageStarted(WebView view, String url, Bitmap favicon){ super .onPageStarted(view, url, favicon); } String authCode; @Override public void onPageFinished(WebView view, String url) { super .onPageFinished(view, url); if (url.contains( "?code=" ) && authComplete != true ) { Uri uri = Uri.parse(url); authCode = uri.getQueryParameter( "code" ); Log.i( "" , "CODE : " + authCode); authComplete = true ; resultIntent.putExtra( "code" , authCode); MainActivity. this .setResult(Activity.RESULT_OK, resultIntent); setResult(Activity.RESULT_CANCELED, resultIntent); SharedPreferences.Editor edit = pref.edit(); edit.putString( "Code" , authCode); edit.commit(); auth_dialog.dismiss(); new TokenGet().execute(); Toast.makeText(getApplicationContext(), "Authorization Code is: " +authCode, Toast.LENGTH_SHORT).show(); } else if (url.contains( "error=access_denied" )){ Log.i( "" , "ACCESS_DENIED_HERE" ); resultIntent.putExtra( "code" , authCode); authComplete = true ; setResult(Activity.RESULT_CANCELED, resultIntent); Toast.makeText(getApplicationContext(), "Error Occured" , Toast.LENGTH_SHORT).show(); auth_dialog.dismiss(); } } }); auth_dialog.show(); auth_dialog.setTitle( "Authorize Learn2Crack" ); auth_dialog.setCancelable( true ); } }); } private class TokenGet extends AsyncTask<String, String, JSONObject> { private ProgressDialog pDialog; String Code; @Override protected void onPreExecute() { super .onPreExecute(); pDialog = new ProgressDialog(MainActivity. this ); pDialog.setMessage( "Contacting Google ..." ); pDialog.setIndeterminate( false ); pDialog.setCancelable( true ); Code = pref.getString( "Code" , "" ); pDialog.show(); } @Override protected JSONObject doInBackground(String... args) { GetAccessToken jParser = new GetAccessToken(); JSONObject json = jParser.gettoken(TOKEN_URL,Code,CLIENT_ID,CLIENT_SECRET,REDIRECT_URI,GRANT_TYPE); return json; } @Override protected void onPostExecute(JSONObject json) { pDialog.dismiss(); if (json != null ){ try { String tok = json.getString( "access_token" ); String expire = json.getString( "expires_in" ); String refresh = json.getString( "refresh_token" ); Log.d( "Token Access" , tok); Log.d( "Expire" , expire); Log.d( "Refresh" , refresh); auth.setText( "Authenticated" ); Access.setText( "Access Token:" +tok+ "nExpires:" +expire+ "nRefresh Token:" +refresh); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else { Toast.makeText(getApplicationContext(), "Network Error" , Toast.LENGTH_SHORT).show(); pDialog.dismiss(); } } } }

Creating Manifest

We need the following permission for our Application.

android.permission.INTERNET

AndroidManifest.xml

<? xml version = "1.0" encoding = "utf-8" ?> < manifest xmlns:android = "http://schemas.android.com/apk/res/android" package = "learn2crack.weboauth2" android:versionCode = "1" android:versionName = "1.0" > < uses-sdk android:minSdkVersion = "8" android:targetSdkVersion = "17" /> < uses-permission android:name = "android.permission.INTERNET" /> < application android:allowBackup = "true" android:icon = "@drawable/ic_launcher" android:label = "@string/app_name" android:theme = "@style/AppTheme" > < activity android:name = "learn2crack.weboauth2.MainActivity" android:label = "@string/app_name" > < intent-filter > < action android:name = "android.intent.action.MAIN" /> < category android:name = "android.intent.category.LAUNCHER" /> </ intent-filter > </ activity > </ application > </ manifest >

Screenshots

Any questions comment here


更多相关文章

  1. Android(安卓)API Level 与SDK版本对照表
  2. 使用Retrofit Https请求
  3. Android(安卓)Lesson One: Getting Started
  4. 【Android】Fragment
  5. Android(安卓)Studio 报Error:(29, 17) Failed to resolve: juni
  6. RF Analyzer for Android(安卓)安卓平台连接HackRF的App
  7. Building, running, and debugging Android(安卓)source
  8. 关于android安装sdk时找不到jdk的解决办法
  9. Android与iPhone的对比(水木上看到的,不清楚原文来源)

随机推荐

  1. Android(安卓)存储选项之 SQLite 优化那
  2. Android面试系列文章2018之Android部分Fr
  3. android设置透明背景
  4. android:ellipsize的使用
  5. Hello, Android(安卓)深入(一)
  6. Android(安卓)入门前言之 --布局
  7. Android(安卓)之不要滥用 SharedPreferen
  8. Android架构组件- Room数据库的使用
  9. Android开发教程
  10. 使用myelipse配置android开发环境