原文 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 tutorial Android Google OAuth2 using AccountManager and making API calls
Enable Google API for making Request
1. Go to Google 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 select CREATE 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 as MainActivity.java and Main layout asactivity_main.xml. Here my applicaion name is WebOAuth2 and my package name islearn2crack.weboauth2.
Download Complete Project
Creating Layout
The layout has a single button widget to start the WebView dialog.
activity_main.xml
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"
?>
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 a GetAccessToken class which makes http request with the authorization code to get the Access Token, Time, Refresh Token in JSON format. 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 use WebViewClient to 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 GRANT_TYPE=
"authorization_code"
;
//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"
?>
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