android应用程序的跨客户端google oauth2.0,带有用于脱机访问的后端服务器
我正在开发一个android应用程序,它可以从用户的youtube帐户获取数据,并且还需要在脱机模式下这样做。为此,我应该实现google的oauth2.0跨客户端身份验证()机制。 我能够获取IdToken,但对于一次exchange token(),它返回null。 请帮我解决这个问题。 先谢谢你。。。 这是我的密码android应用程序的跨客户端google oauth2.0,带有用于脱机访问的后端服务器,android,oauth-2.0,google-oauth,access-token,Android,Oauth 2.0,Google Oauth,Access Token,我正在开发一个android应用程序,它可以从用户的youtube帐户获取数据,并且还需要在脱机模式下这样做。为此,我应该实现google的oauth2.0跨客户端身份验证()机制。 我能够获取IdToken,但对于一次exchange token(),它返回null。 请帮我解决这个问题。 先谢谢你。。。 这是我的密码 package com.example.sampleapp; import java.util.Arrays; import java.util.List; import
package com.example.sampleapp;
import java.util.Arrays;
import java.util.List;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.UserRecoverableAuthException;
import com.google.android.gms.common.AccountPicker;
import android.support.v7.app.ActionBarActivity;
import android.text.TextUtils;
import android.accounts.AccountManager;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
final private String CLIENT_ID = "12345----.apps.googleusercontent.com";
static final int REQUEST_CODE_PICK_ACCOUNT = 1000;
private String mEmail;
//private static final String SCOPE =
// "oauth2:https://www.googleapis.com/auth/userinfo.profile";
final private List<String> SCOPES = Arrays.asList(new String[]{
"https://www.googleapis.com/auth/plus.login",
"https://www.googleapis.com/auth/youtube"});
private EditText mExchangeCodeEditText;
private EditText mIdTokenEditText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mExchangeCodeEditText = (EditText) findViewById(R.id.editTextExchangeCode);
mIdTokenEditText = (EditText) findViewById(R.id.editTextIdToken);
Button b1=(Button) findViewById(R.id.button1);
b1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
// static final int REQUEST_CODE_PICK_ACCOUNT = 1000;
String[] accountTypes = new String[]{"com.google"};
Intent intent = AccountPicker.newChooseAccountIntent(null, null,
accountTypes, false, null, null, null, null);
startActivityForResult(intent, REQUEST_CODE_PICK_ACCOUNT);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_PICK_ACCOUNT) {
// Receiving a result from the AccountPicker
if (resultCode == RESULT_OK) {
mEmail = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
// With the account name acquired, go get the auth token
// getUsername();
Log.v("MY_UNAME",mEmail);
new RetrieveJwtAsyncTask().execute();
new RetrieveExchangeCodeAsyncTask().execute();
} else if (resultCode == RESULT_CANCELED) {
// The account picker dialog closed without selecting an account.
// Notify users that they must pick an account to proceed.
Toast.makeText(this, R.string.pick_account, Toast.LENGTH_SHORT).show();
}
}
// Later, more code will go here to handle the result from some exceptions...
}
public class RetrieveJwtAsyncTask
extends AsyncTask<Void, Boolean, String> {
@Override
protected String doInBackground(Void... params) {
String scope = "audience:server:client_id:" + CLIENT_ID;
try {
return GoogleAuthUtil.getToken(
MainActivity.this, mEmail, scope);
} catch (Exception e) {
e.printStackTrace(); // TODO: handle the exception
}
return null;
}
@Override
protected void onPostExecute(String idToken) {
// exchange encrypted idToken with server-side to identify the user
mIdTokenEditText.setText(idToken);
Log.v("Second One"," "+ idToken);
}
}
public class RetrieveExchangeCodeAsyncTask
extends AsyncTask<Void, Boolean, String> {
@Override
protected String doInBackground(Void... params) {
String scope = String.format("oauth2:server:client_id:%s:api_scope:%s",
CLIENT_ID, TextUtils.join(" ", SCOPES));
try {
return GoogleAuthUtil.getToken(
MainActivity.this, mEmail, scope);
} catch (Exception e) {
e.printStackTrace(); // TODO: handle the exception
}
return null;
}
@Override
protected void onPostExecute(String code) {
// exchange code with server-side to retrieve an additional
// access token on the server-side.
Log.v("first One","1"+ code);
mExchangeCodeEditText.setText(code);
}
}
}
package com.example.sampleapp;
导入java.util.array;
导入java.util.List;
导入com.google.android.gms.auth.GoogleAuthUtil;
导入com.google.android.gms.auth.UserRecoverableAuthException;
导入com.google.android.gms.common.AccountPicker;
导入android.support.v7.app.ActionBarActivity;
导入android.text.TextUtils;
导入android.accounts.AccountManager;
导入android.content.Intent;
导入android.os.AsyncTask;
导入android.os.Bundle;
导入android.util.Log;
导入android.view.Menu;
导入android.view.MenuItem;
导入android.view.view;
导入android.widget.Button;
导入android.widget.EditText;
导入android.widget.Toast;
公共类MainActivity扩展了ActionBarActivity{
最终私有字符串客户端\u ID=“12345---.apps.googleusercontent.com”;
静态最终整数请求\代码\选择\帐户=1000;
私有字符串mEmail;
//私有静态最终字符串作用域=
//“oauth2:https://www.googleapis.com/auth/userinfo.profile";
最终私有列表范围=Arrays.asList(新字符串[]){
"https://www.googleapis.com/auth/plus.login",
"https://www.googleapis.com/auth/youtube"});
私有EditText mExchangeCodeEditText;
私有EditText中间标记EditText;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mExchangeCodeEditText=(EditText)findViewById(R.id.editTextExchangeCode);
mIdTokenEditText=(EditText)findViewById(R.id.editTextIdToken);
按钮b1=(按钮)findViewById(R.id.button1);
b1.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图v){
//TODO自动生成的方法存根
//静态最终整数请求\代码\选择\帐户=1000;
String[]accountTypes=新字符串[]{“com.google”};
Intent Intent=AccountPicker.newchooseAccountContent(null,null,
accountTypes,false,null,null,null,null);
startActivityForResult(意向、请求、代码、选择账户);
}
});
}
@凌驾
公共布尔onCreateOptions菜单(菜单){
//为菜单充气;这会将项目添加到操作栏(如果存在)。
getMenuInflater().充气(R.menu.main,menu);
返回true;
}
@覆盖公共布尔值OnOptions项Selected(MenuItem项){
//处理操作栏项目单击此处。操作栏将
//自动处理Home/Up按钮上的点击,只要
//在AndroidManifest.xml中指定父活动时。
int id=item.getItemId();
if(id==R.id.action\u设置){
返回true;
}
返回super.onOptionsItemSelected(项目);
}
@凌驾
受保护的void onActivityResult(int请求代码、int结果代码、意图数据){
if(requestCode==请求\代码\选择\帐户){
//从AccountPicker接收结果
if(resultCode==RESULT\u OK){
mEmail=data.getStringExtra(AccountManager.KEY\u ACCOUNT\u NAME);
//获取帐户名后,获取身份验证令牌
//getUsername();
Log.v(“MY_UNAME”,mEmail);
新建RetrieveJwtAsyncTask().execute();
新建RetrieveExchangeCodeAsyncTask().execute();
}else if(resultCode==RESULT\u取消){
//帐户选择器对话框关闭,但未选择帐户。
//通知用户必须选择一个帐户才能继续。
Toast.makeText(this,R.string.pick_account,Toast.LENGTH_SHORT).show();
}
}
//稍后,更多代码将转到此处处理某些异常的结果。。。
}
公共类RetrieveJwtAsyncTask
扩展异步任务{
@凌驾
受保护字符串doInBackground(无效…参数){
String scope=“受众:服务器:客户机id:+客户机id;
试一试{
返回GoogleAuthUtil.getToken(
MainActivity.this、mEmail、scope);
}捕获(例外e){
e、 printStackTrace();//TODO:处理异常
}
返回null;
}
@凌驾
受保护的void onPostExecute(字符串idToken){
//与服务器端交换加密的idToken以标识用户
mIdTokenEditText.setText(idToken);
Log.v(“第二个”,即“+idToken”);
}
}
公共类RetrieveExchangeCodeAsyncTask
扩展异步任务{
@凌驾
受保护字符串doInBackground(无效…参数){
String scope=String.format(“oauth2:server:client\u id:%s:api\u scope:%s”,
CLIENT_ID,TextUtils.join(“,SCOPES));
试一试{
返回GoogleAuthUtil.getToken(
MainActivity.this、mEmail、scope);
}捕获(例外e){
e、 printStackTrace();//TODO:处理异常
}
返回null;
}
@凌驾
受保护的void onPostExecute(字符串代码){
//与服务器端交换代码以检索其他
//服务器端的访问令牌。
Log.v(“第一个”,“1”+代码);
mExchangeCodeEditText.setText(代码);
}
}
}
类RetrieveJwtAsyncTask运行正常,但类RetrieveExchangeCodeAsyncTask返回null,而不是在上述代码段中引用为“代码”的一次性访问代码。我没有在开发人员控制台中正确注册我的应用程序。修复后,我的问题解决了,上面的代码正常工作。您可以将其作为答案提交并接受。