如何从我的 Android 应用程序访问新的 Gmail API?
Posted
技术标签:
【中文标题】如何从我的 Android 应用程序访问新的 Gmail API?【英文标题】:How to access the new Gmail API from my Android app? 【发布时间】:2014-09-01 10:10:26 【问题描述】:我正在尝试从我的 android 应用程序访问新的Gmail API(2014 年 6 月 6 日宣布),以便返回某个用户帐户中的所有电子邮件。我正在使用 ADT 插件在 Eclipse 中开发应用程序。 到目前为止我做了什么:
我在 Google Developers Console 中注册了应用程序 (链接:console.developers.google.com/project)。
我已经实现了 Google+ 登录按钮(链接:developers.google.com/+/mobile/android/sign-in)。 Google+ 登录按钮可对用户进行身份验证并管理 OAuth 2.0 流程,从而简化您与 Google API 的集成。
我将附加范围“https://www.googleapis.com/auth/gmail.readonly”添加到 Google+ 授权中,用于访问 Gmail API,如 (链接:developers.google.com/gmail/api/v1/reference/users/threads/list)。
此时我有一个初始化的 GoogleApiClient 对象。
GoogleApiClient 对象将 ServiceConnection(链接:developer.android.com/reference/android/content/ServiceConnection.html)包装到 Google Play 服务。 GoogleApiClient 对象用于与 Google+ API 进行通信,并在与服务建立异步连接后生效,表明:
设备上正在运行 Google Play 服务,并且应用 Activity 已成功绑定服务连接, 用户选择了他们希望在应用中使用的帐户,并且 用户帐户已授予应用请求的权限。我如何从这里着手获取带有此 httprequest 的所有消息? 此时我尝试访问 Gmail API,但收到身份验证错误 401:需要登录,即使 Google+ 登录成功,我也成功返回了用户圈子列表。
编辑:SecondActivity.java
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.GooglePlayServicesAvailabilityException;
import com.google.android.gms.auth.UserRecoverableAuthException;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.SignInButton;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Scope;
import com.google.android.gms.plus.People;
import com.google.android.gms.plus.People.LoadPeopleResult;
import com.google.android.gms.plus.Plus;
import com.google.android.gms.plus.model.people.Person;
import com.google.android.gms.plus.model.people.PersonBuffer;
import com.google.api.services.gmail.Gmail;
import com.google.api.services.gmail.Gmail.Users;
import com.google.api.services.gmail.Gmail.Users.Messages.GmailImport;
import com.google.api.services.gmail.GmailRequest;
import com.google.api.services.gmail.GmailRequestInitializer;
import com.google.api.services.gmail.GmailScopes;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.PendingIntent;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import mk.ukim.feit.recognizer.application.PeopleAdapter;
import mk.ukim.feit.recognizer.interfaces.GetMessages;
import mk.ukim.feit.recognizer.tasks.GetMessagesTask;
import mk.ukim.feit.recognizer.util.MyClass;
import mk.ukim.feit.recognizer.util.exception.FaceClientException;
import mk.ukim.feit.recognizer.util.model.Face;
import mk.ukim.feit.recognizer.util.model.Guess;
import mk.ukim.feit.recognizer.util.model.Photo;
import mk.ukim.feit.recognizer.util.response.PhotoResponse;
import mk.ukim.feit.recognizer.util.response.PhotoResponseImpl;
import java.io.IOException;
import java.util.ArrayList;
public class SecondActivity extends FragmentActivity implements
GetMessages, ConnectionCallbacks, OnConnectionFailedListener,
ResultCallback<People.LoadPeopleResult>, View.OnClickListener
private static final String TAG = "android-plus-quickstart";
private static final int STATE_DEFAULT = 0;
private static final int STATE_SIGN_IN = 1;
private static final int STATE_IN_PROGRESS = 2;
private static final int RC_SIGN_IN = 0;
private static final int MY_ACTIVITYS_AUTH_REQUEST_CODE=045;
private static final int DIALOG_PLAY_SERVICES_ERROR = 0;
private static final String SAVED_PROGRESS = "sign_in_progress";
private GoogleApiClient mGoogleApiClient;
String name;
private PendingIntent mSignInIntent;
private int mSignInError;
private SignInButton mSignInButton;
private Button mSignOutButton;
private Button mRevokeButton;
private TextView mStatus;
private ListView mCirclesListView;
private ArrayAdapter<String> mCirclesAdapter;
private ArrayList<String> mCirclesList;
public Scope gmail=new Scope("https://www.googleapis.com/auth/gmail.readonly");
String scope="https://www.googleapis.com/auth/gmail.readonly";
String email="email@gmail.com";
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Intent intent = getIntent();
name="Team";
mSignInButton = (SignInButton) findViewById(R.id.sign_in_button);
mSignOutButton = (Button) findViewById(R.id.sign_out_button);
mRevokeButton = (Button) findViewById(R.id.revoke_access_button);
mStatus = (TextView) findViewById(R.id.sign_in_status);
mCirclesListView = (ListView) findViewById(R.id.circles_list);
mSignInButton.setOnClickListener(this);
mSignOutButton.setOnClickListener(this);
mRevokeButton.setOnClickListener(this);
mCirclesList = new ArrayList<String>();
mCirclesAdapter = new ArrayAdapter<String>(
this, R.layout.circle_member, mCirclesList);
mCirclesListView.setAdapter(mCirclesAdapter);
if (savedInstanceState != null)
mSignInProgress = savedInstanceState
.getInt(SAVED_PROGRESS, STATE_DEFAULT);
mGoogleApiClient = buildGoogleApiClient();
private GoogleApiClient buildGoogleApiClient()
return new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API, Plus.PlusOptions.builder().build())
.addScope(Plus.SCOPE_PLUS_LOGIN)
.addScope(gmail)
.build();
@Override
protected void onStart()
super.onStart();
mGoogleApiClient.connect();
getAndUseAuthTokenInAsyncTask();
@Override
protected void onStop()
super.onStop();
if (mGoogleApiClient.isConnected())
mGoogleApiClient.disconnect();
@Override
protected void onSaveInstanceState(Bundle outState)
super.onSaveInstanceState(outState);
outState.putInt(SAVED_PROGRESS, mSignInProgress);
@Override
public void onClick(View v)
if (!mGoogleApiClient.isConnecting())
switch (v.getId())
case R.id.sign_in_button:
mStatus.setText(R.string.status_signing_in);
resolveSignInError();
break;
case R.id.sign_out_button:
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
break;
case R.id.revoke_access_button:
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
Plus.AccountApi.revokeAccessAndDisconnect(mGoogleApiClient);
mGoogleApiClient = buildGoogleApiClient();
mGoogleApiClient.connect();
break;
@Override
public void onConnected(Bundle connectionHint)
Log.i(TAG, "onConnected");
getAndUseAuthTokenInAsyncTask();
mSignInButton.setEnabled(false);
mSignOutButton.setEnabled(true);
mRevokeButton.setEnabled(true);
// Retrieve some profile information. This is OK
Person currentUser = Plus.PeopleApi.getCurrentPerson(mGoogleApiClient);
String klient=mGoogleApiClient.toString();
mStatus.setText(String.format(
getResources().getString(R.string.signed_in_as),
currentUser.getDisplayName()));
Plus.PeopleApi.loadVisible(mGoogleApiClient, null)
.setResultCallback(this);
GetMessagesTask task = new GetMessagesTask(
SecondActivity.this, name, mGoogleApiClient);
task.setDelegate(SecondActivity.this);
task.execute();
// Indicate that the sign in process is complete.
mSignInProgress = STATE_DEFAULT;
@Override
public void onConnectionFailed(ConnectionResult result)
// Refer to the javadoc for ConnectionResult to see what error codes might
// be returned in onConnectionFailed.
Log.i(TAG, "onConnectionFailed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
if (mSignInProgress != STATE_IN_PROGRESS)
mSignInIntent = result.getResolution();
mSignInError = result.getErrorCode();
if (mSignInProgress == STATE_SIGN_IN)
// STATE_SIGN_IN indicates the user already clicked the sign in button
// so we should continue processing errors until the user is signed in
// or they click cancel.
resolveSignInError();
onSignedOut();
private void resolveSignInError()
if (mSignInIntent != null)
try
mSignInProgress = STATE_IN_PROGRESS;
startIntentSenderForResult(mSignInIntent.getIntentSender(),
RC_SIGN_IN, null, 0, 0, 0);
catch (SendIntentException e)
Log.i(TAG, "Sign in intent could not be sent: "
+ e.getLocalizedMessage());
// The intent was canceled before it was sent. Attempt to connect to
// get an updated ConnectionResult.
mSignInProgress = STATE_SIGN_IN;
mGoogleApiClient.connect();
else
// Google Play services wasn't able to provide an intent for some
// error types, so we show the default Google Play services error
// dialog which may still start an intent if the
// user can resolve the issue.
showDialog(DIALOG_PLAY_SERVICES_ERROR);
@Override
public void onResult(LoadPeopleResult peopleData)
if (peopleData.getStatus().getStatusCode() == CommonStatusCodes.SUCCESS)
mCirclesList.clear();
PersonBuffer personBuffer = peopleData.getPersonBuffer();
try
int count = personBuffer.getCount();
for (int i = 0; i < count; i++)
mCirclesList.add(personBuffer.get(i).getDisplayName());
finally
personBuffer.close();
mCirclesAdapter.notifyDataSetChanged();
else
Log.e(TAG, "Error requesting visible circles: " + peopleData.getStatus());
private void onSignedOut()
// Update the UI to reflect that the user is signed out.
mSignInButton.setEnabled(true);
mSignOutButton.setEnabled(false);
mRevokeButton.setEnabled(false);
mStatus.setText(R.string.status_signed_out);
mCirclesList.clear();
mCirclesAdapter.notifyDataSetChanged();
@Override
public void onConnectionSuspended(int cause)
// The connection to Google Play services was lost for some reason.
// We call connect() to attempt to re-establish the connection or get a
// ConnectionResult that we can attempt to resolve.
mGoogleApiClient.connect();
@Override
protected Dialog onCreateDialog(int id)
switch(id)
case DIALOG_PLAY_SERVICES_ERROR:
if (GooglePlayServicesUtil.isUserRecoverableError(mSignInError))
return GooglePlayServicesUtil.getErrorDialog(
mSignInError,
this,
RC_SIGN_IN,
new DialogInterface.OnCancelListener()
@Override
public void onCancel(DialogInterface dialog)
Log.e(TAG, "Google Play services resolution cancelled");
mSignInProgress = STATE_DEFAULT;
mStatus.setText(R.string.status_signed_out);
);
else
return new AlertDialog.Builder(this)
.setMessage(R.string.play_services_error)
.setPositiveButton(R.string.close,
new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface dialog, int which)
Log.e(TAG, "Google Play services error could not be "
+ "resolved: " + mSignInError);
mSignInProgress = STATE_DEFAULT;
mStatus.setText(R.string.status_signed_out);
).create();
default:
return super.onCreateDialog(id);
protected void onActivityResult(int requestCode, int resultCode, Intent data)
if (requestCode == MY_ACTIVITYS_AUTH_REQUEST_CODE)
if (resultCode == RESULT_OK)
getAndUseAuthTokenInAsyncTask();
public void getAndUseAuthTokenBlocking() throws UserRecoverableAuthException, IOException, GoogleAuthException
final String token = GoogleAuthUtil.getToken(this, email, scope);
String fff="";
public void getAndUseAuthTokenInAsyncTask()
AsyncTask<Void, Void, Void> task = new AsyncTask<Void,Void, Void>()
@Override
protected Void doInBackground(Void... params)
// TODO Auto-generated method stub
try
getAndUseAuthTokenBlocking();
catch (UserRecoverableAuthException e)
// TODO Auto-generated catch block
e.printStackTrace();
catch (IOException e)
// TODO Auto-generated catch block
e.printStackTrace();
catch (GoogleAuthException e)
// TODO Auto-generated catch block
e.printStackTrace();
return null;
;
task.execute((Void)null);
编辑 2:LogCat
07-16 06:44:27.300: E/AndroidRuntime(11875): FATAL EXCEPTION: AsyncTask #2
07-16 06:44:27.300: E/AndroidRuntime(11875): java.lang.RuntimeException: An error occured while executing doInBackground()
07-16 06:44:27.300: E/AndroidRuntime(11875): at android.os.AsyncTask$3.done(AsyncTask.java:299)
07-16 06:44:27.300: E/AndroidRuntime(11875): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
07-16 06:44:27.300: E/AndroidRuntime(11875): at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
07-16 06:44:27.300: E/AndroidRuntime(11875): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
07-16 06:44:27.300: E/AndroidRuntime(11875): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
07-16 06:44:27.300: E/AndroidRuntime(11875): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
07-16 06:44:27.300: E/AndroidRuntime(11875): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
07-16 06:44:27.300: E/AndroidRuntime(11875): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
07-16 06:44:27.300: E/AndroidRuntime(11875): at java.lang.Thread.run(Thread.java:856)
07-16 06:44:27.300: E/AndroidRuntime(11875): Caused by: java.lang.NoClassDefFoundError: com.google.api.client.googleapis.auth.oauth2.GoogleCredential
07-16 06:44:27.300: E/AndroidRuntime(11875): at mk.ukim.feit.recognizer.GmailLinkGrabberService$getAuthToken.doInBackground(GmailLinkGrabberService.java:104)
07-16 06:44:27.300: E/AndroidRuntime(11875): at mk.ukim.feit.recognizer.GmailLinkGrabberService$getAuthToken.doInBackground(GmailLinkGrabberService.java:1)
07-16 06:44:27.300: E/AndroidRuntime(11875): at android.os.AsyncTask$2.call(AsyncTask.java:287)
07-16 06:44:27.300: E/AndroidRuntime(11875): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
07-16 06:44:27.300: E/AndroidRuntime(11875): ... 5 more
【问题讨论】:
我已经在我的安卓应用中成功实现了 Gmail API。如果您提供代码,我可以帮助您调试。 返回 Google+ 圈子后,我不知道如何访问已登录用户的 gmail 帐户。有什么帮助吗? @gitter 这段代码实现了同样的事情:raw.githubusercontent.com/gitanshu/privly-android/gmail-rest/… 另外,范围应该是“oauth2:googleapis.com/auth/gmail.readonly” @Jakob 查看此线程的第四条评论。我提供了我的代码的链接。当我有时间时,我会尝试向它添加更多文档。但我相信这很容易理解。 你还有这个问题吗?也许您可以在此处粘贴出现错误的代码? @TalMihr 【参考方案1】:(2017 年 2 月)Gmail API(v1 launched 2014 年 6 月)是将 Gmail 功能集成到您的应用程序中的最佳方式(优于 POP/IMAP 和 SMTP)。为了在 Android 中使用此 API 和大多数其他 Google API,您需要获取 the Google APIs Client Library for Android(或者对于更通用的 Java,the Google APIs Client Library for Java)。
现在是一些工作示例:这里是Android quickstart 和更通用的Java quickstart。将Gmail API JavaDocs reference 放在身边也不是一个坏主意。 OAuth2 现在是执行身份验证的首选方式,这意味着您需要看起来像这样的代码,加上正确的scope:
// Sheets RO scope
private static final String[] SCOPES = GmailScopes.GMAIL_READONLY;
:
// Initialize credentials and service object
mCredential = GoogleAccountCredential.usingOAuth2(
getApplicationContext(), Arrays.asList(SCOPES))
.setBackOff(new ExponentialBackOff());
除了这个“设置”之外,OP 还拥有让某些东西正常工作所需的大部分东西:
-
在developers console 中有一个项目并启用了带有 SHA1 哈希的 Gmail API(如上文 Android 快速入门中所述)
使用正确的范围实施 OAuth2
将the call 转换为
ListThreadsResponse listResponse = mService.users().threads().list(user).execute();
-- 快速入门使用labels()
,因此您只需更改为threads()
要了解有关 API 的更多信息,以下是 3 个视频,这是 API 发布时的第一个介绍。如果您对 Python 没有“过敏”,我使用 Gmail API 制作了另一对简短但更“真实”的示例(虽然非移动设备):
Introducing the Gmail API Revolutionizing Email Access with the Gmail API(代码深潜post) Modifying your signature with the Gmail API(代码深潜post)标题中没有提到它,但上面的第二个视频提供了一个使用 Gmail API 访问线程和消息的代码示例。
【讨论】:
【参考方案2】:使用此代码:
public class MainActivity extends Activity implements OnClickListener,
ConnectionCallbacks, OnConnectionFailedListener
private static final int RC_SIGN_IN = 0;
// Logcat tag
private static final String TAG = "MainActivity";
// Profile pic image size in pixels
private static final int PROFILE_PIC_SIZE = 400;
// Google client to interact with Google API
private GoogleApiClient mGoogleApiClient;
/**
* A flag indicating that a PendingIntent is in progress and prevents us
* from starting further intents.
*/
private boolean mIntentInProgress;
private boolean mSignInClicked;
private ConnectionResult mConnectionResult;
private SignInButton btnSignIn;
private Button btnSignOut, btnRevokeAccess;
private ImageView imgProfilePic;
private TextView txtName, txtEmail;
private LinearLayout llProfileLayout;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnSignIn = (SignInButton) findViewById(R.id.btn_sign_in);
btnSignOut = (Button) findViewById(R.id.btn_sign_out);
btnRevokeAccess = (Button) findViewById(R.id.btn_revoke_access);
imgProfilePic = (ImageView) findViewById(R.id.imgProfilePic);
txtName = (TextView) findViewById(R.id.txtName);
txtEmail = (TextView) findViewById(R.id.txtEmail);
llProfileLayout = (LinearLayout) findViewById(R.id.llProfile);
// Button click listeners
btnSignIn.setOnClickListener(this);
btnSignOut.setOnClickListener(this);
btnRevokeAccess.setOnClickListener(this);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).addApi(Plus.API, null)
.addScope(Plus.SCOPE_PLUS_LOGIN).build();
protected void onStart()
super.onStart();
mGoogleApiClient.connect();
protected void onStop()
super.onStop();
if (mGoogleApiClient.isConnected())
mGoogleApiClient.disconnect();
/**
* Method to resolve any signin errors
* */
private void resolveSignInError()
if (mConnectionResult.hasResolution())
try
mIntentInProgress = true;
mConnectionResult.startResolutionForResult(this, RC_SIGN_IN);
catch (SendIntentException e)
mIntentInProgress = false;
mGoogleApiClient.connect();
@Override
public void onConnectionFailed(ConnectionResult result)
if (!result.hasResolution())
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), this,
0).show();
return;
if (!mIntentInProgress)
// Store the ConnectionResult for later usage
mConnectionResult = result;
if (mSignInClicked)
// The user has already clicked 'sign-in' so we attempt to
// resolve all
// errors until the user is signed in, or they cancel.
resolveSignInError();
@Override
protected void onActivityResult(int requestCode, int responseCode,
Intent intent)
if (requestCode == RC_SIGN_IN)
if (responseCode != RESULT_OK)
mSignInClicked = false;
mIntentInProgress = false;
if (!mGoogleApiClient.isConnecting())
mGoogleApiClient.connect();
@Override
public void onConnected(Bundle arg0)
mSignInClicked = false;
Toast.makeText(this, "User is connected!", Toast.LENGTH_LONG).show();
// Get user's information
getProfileInformation();
// Update the UI after signin
updateUI(true);
/**
* Updating the UI, showing/hiding buttons and profile layout
* */
private void updateUI(boolean isSignedIn)
if (isSignedIn)
btnSignIn.setVisibility(View.GONE);
btnSignOut.setVisibility(View.VISIBLE);
btnRevokeAccess.setVisibility(View.VISIBLE);
llProfileLayout.setVisibility(View.VISIBLE);
else
btnSignIn.setVisibility(View.VISIBLE);
btnSignOut.setVisibility(View.GONE);
btnRevokeAccess.setVisibility(View.GONE);
llProfileLayout.setVisibility(View.GONE);
/**
* Fetching user's information name, email, profile pic
* */
private void getProfileInformation()
try
if (Plus.PeopleApi.getCurrentPerson(mGoogleApiClient) != null)
Person currentPerson = Plus.PeopleApi
.getCurrentPerson(mGoogleApiClient);
String personName = currentPerson.getDisplayName();
String personPhotoUrl = currentPerson.getImage().getUrl();
String personGooglePlusProfile = currentPerson.getUrl();
String email = Plus.AccountApi.getAccountName(mGoogleApiClient);
Log.e(TAG, "Name: " + personName + ", plusProfile: "
+ personGooglePlusProfile + ", email: " + email
+ ", Image: " + personPhotoUrl);
txtName.setText(personName);
txtEmail.setText(email);
// by default the profile url gives 50x50 px image only
// we can replace the value with whatever dimension we want by
// replacing sz=X
personPhotoUrl = personPhotoUrl.substring(0,
personPhotoUrl.length() - 2)
+ PROFILE_PIC_SIZE;
new LoadProfileImage(imgProfilePic).execute(personPhotoUrl);
else
Toast.makeText(getApplicationContext(),
"Person information is null", Toast.LENGTH_LONG).show();
catch (Exception e)
e.printStackTrace();
@Override
public void onConnectionSuspended(int arg0)
mGoogleApiClient.connect();
updateUI(false);
@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;
/**
* Button on click listener
* */
@Override
public void onClick(View v)
switch (v.getId())
case R.id.btn_sign_in:
// Signin button clicked
signInWithGplus();
break;
case R.id.btn_sign_out:
// Signout button clicked
signOutFromGplus();
break;
case R.id.btn_revoke_access:
// Revoke access button clicked
revokeGplusAccess();
break;
/**
* Sign-in into google
* */
private void signInWithGplus()
if (!mGoogleApiClient.isConnecting())
mSignInClicked = true;
resolveSignInError();
/**
* Sign-out from google
* */
private void signOutFromGplus()
if (mGoogleApiClient.isConnected())
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
updateUI(false);
/**
* Revoking access from google
* */
private void revokeGplusAccess()
if (mGoogleApiClient.isConnected())
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
Plus.AccountApi.revokeAccessAndDisconnect(mGoogleApiClient)
.setResultCallback(new ResultCallback<Status>()
@Override
public void onResult(Status arg0)
Log.e(TAG, "User access revoked!");
mGoogleApiClient.connect();
updateUI(false);
);
/**
* Background Async task to load user profile picture from url
* */
private class LoadProfileImage extends AsyncTask<String, Void, Bitmap>
ImageView bmImage;
public LoadProfileImage(ImageView bmImage)
this.bmImage = bmImage;
protected Bitmap doInBackground(String... urls)
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
catch (Exception e)
Log.e("Error", e.getMessage());
e.printStackTrace();
return mIcon11;
protected void onPostExecute(Bitmap result)
bmImage.setImageBitmap(result);
希望这会有所帮助
【讨论】:
【参考方案3】:我使用 t 访问 gmail api 的类 -
public class GMail extends javax.mail.Authenticator
private Multipart attachements;
private String fromAddress = "";
private String accountEmail = "";
private String accountPassword = "";
private String smtpHost = "smtp.gmail.com";
private String smtpPort = "465"; // 465,587
private String toAddresses = "";
private String mailSubject = "";
private String mailBody = "";
public GMail()
attachements = new MimeMultipart();
public GMail(String user, String pass)
this();
accountEmail = user;
accountPassword = pass;
public boolean send() throws Exception
Properties props = new Properties();
// props.put("mail.smtp.user", d_email);
props.put("mail.smtp.host", smtpHost);
props.put("mail.smtp.port", smtpPort);
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.debug", "true");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.socketFactory.port", smtpPort);
props.put("mail.smtp.socketFactory.class",
"javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.fallback", "false");
try
Session session = Session.getInstance(props, this);
session.setDebug(true);
MimeMessage msg = new MimeMessage(session);
// create the message part
MimeBodyPart messageBodyPart = new MimeBodyPart();
// fill message
messageBodyPart.setText(mailBody);
// add to multipart
attachements.addBodyPart(messageBodyPart);
// msg.setText(mailBody);
msg.setSubject(mailSubject);
msg.setFrom(new InternetAddress(fromAddress));
msg.addRecipients(Message.RecipientType.TO,
InternetAddress.parse(toAddresses));
msg.setContent(attachements);
Transport transport = session.getTransport("smtps");
transport.connect(smtpHost, 465, accountEmail, accountPassword);
transport.sendMessage(msg, msg.getAllRecipients());
transport.close();
return true;
catch (Exception e)
return false;
public void addAttachment(String filename) throws Exception
BodyPart messageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(filename);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName("Victim");
attachements.addBodyPart(messageBodyPart);
// private String getFormattedDate(Date date)
// SimpleDateFormat sdf = new SimpleDateFormat(
// "EEE, dd-MMM-yyyy hh:mm:ss a");
// return sdf.format(date);
//
@Override
public PasswordAuthentication getPasswordAuthentication()
return new PasswordAuthentication(accountEmail, accountPassword);
/**
* Gets the fromAddress.
*
* @return <tt> the fromAddress.</tt>
*/
public String getFromAddress()
return fromAddress;
/**
* Sets the fromAddress.
*
* @param fromAddress
* <tt> the fromAddress to set.</tt>
*/
public void setFromAddress(String fromAddress)
this.fromAddress = fromAddress;
/**
* Gets the toAddresses.
*
* @return <tt> the toAddresses.</tt>
*/
public String getToAddresses()
return toAddresses;
/**
* Sets the toAddresses.
*
* @param toAddresses
* <tt> the toAddresses to set.</tt>
*/
public void setToAddresses(String toAddresses)
this.toAddresses = toAddresses;
/**
* Gets the mailSubject.
*
* @return <tt> the mailSubject.</tt>
*/
public String getMailSubject()
return mailSubject;
/**
* Sets the mailSubject.
*
* @param mailSubject
* <tt> the mailSubject to set.</tt>
*/
public void setMailSubject(String mailSubject)
this.mailSubject = mailSubject;
/**
* Gets the mailBody.
*
* @return <tt> the mailBody.</tt>
*/
public String getMailBody()
return mailBody;
/**
* Sets the mailBody.
*
* @param mailBody
* <tt> the mailBody to set.</tt>
*/
public void setMailBody(String mailBody)
this.mailBody = mailBody;
使用这个类 -
GMail m = new GMail(context.getResources().getString(
R.string.emailId), context.getResources().getString(
R.string.pas));
m.setToAddresses("some@example.com,another@some.com");
m.setFromAddress("yourid@gmail.com");
m.setMailSubject(subjectText);
m.setMailBody(bodyText);
【讨论】:
OP 正在尝试访问新的 Gmail API(2014 年 6 月 25 日宣布),这看起来像一般的 SMTP 电子邮件访问。 正确。 Gmail API (http://) 现在是访问 Gmail 服务的首选方式,而不是 POP/IMAP 或 SMTP。我对这个问题的回答中有更多内容。 这是虚假广告。它使用普通的旧 SMTP 而不是 API。【参考方案4】:根据NoClassDefFoundError: com/google/api/client/util/Lists when setting up oauth2 on app engine,
你的
java.lang.NoClassDefFoundError: com.google.api.client.googleapis.auth.oauth2.GoogleCredential
错误意味着您的类路径中缺少依赖项。
但另一方面,您的身份验证错误可能只是服务器错误,因为您的令牌是旧的,您只需要重新提交一个新的。看看this 是否对您有帮助。它有点陈旧(写于 2013 年),但也许一些 cmets 可以提供帮助。
【讨论】:
以上是关于如何从我的 Android 应用程序访问新的 Gmail API?的主要内容,如果未能解决你的问题,请参考以下文章
如何从我在 Android 的服务中运行的 switch case 开始新的活动?
如何从我的 android 设备访问我的本地 REST api?