访问 google 任务 api 时出现 403 禁止错误
403 forbidden error on while accessing google task api
我正在尝试与 google 任务同步。我从默认列表中获取了任务列表。现在我想在默认列表中插入一个任务。
我遵循了文档。
https://developers.google.com/google-apps/tasks/v1/reference/tasks/insert
此外,我已将任务 api 设置为已启用。我也生成了客户端 ID。
OAuth 2.0 客户端 ID
名称创建日期类型客户 ID
Android 客户 1 2016 年 3 月 19 日 Android 256433535354-h653umd5mddo5t139moof3cvd56asnec.apps.googleusercontent.com
当我尝试插入任务时,我仍然收到 403 forbidden 错误,错误消息是:权限不足。
我还设置了 OAuth 2.0 范围来管理您的所有任务。来自这里:
https://developers.google.com/apis-explorer/?hl=en_US#p/tasks/v1/
我仍然无法插入任务。
我不明白出了什么问题..请帮忙..
依赖关系:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.google.android.gms:play-services-identity:7.8.0'
compile('com.google.api-client:google-api-client-android:1.20.0') {
exclude group: 'org.apache.httpcomponents'
}
compile('com.google.apis:google-api-services-tasks:v1-rev41-1.20.0') {
exclude group: 'org.apache.httpcomponents'
}
}
代码:
public class MainActivity extends AppCompatActivity {
GoogleAccountCredential mCredential;
private TextView mOutputText;
ProgressDialog mProgress;
static final int REQUEST_ACCOUNT_PICKER = 1000;
static final int REQUEST_AUTHORIZATION = 1001;
static final int REQUEST_GOOGLE_PLAY_SERVICES = 1002;
private static final String PREF_ACCOUNT_NAME = "accountName";
private static final String[] SCOPES = { TasksScopes.TASKS_READONLY };
ListView listView;
ArrayAdapter<String> adapter;
List<String> result1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout activityLayout = new LinearLayout(this);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
activityLayout.setLayoutParams(lp);
activityLayout.setOrientation(LinearLayout.VERTICAL);
activityLayout.setPadding(16, 16, 16, 16);
ViewGroup.LayoutParams tlp = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
mOutputText = new TextView(this);
mOutputText.setLayoutParams(tlp);
mOutputText.setPadding(16, 16, 16, 16);
mOutputText.setVerticalScrollBarEnabled(true);
mOutputText.setMovementMethod(new ScrollingMovementMethod());
activityLayout.addView(mOutputText);
mProgress = new ProgressDialog(this);
mProgress.setMessage("Calling Google Tasks API ...");
listView = (ListView) findViewById(R.id.list);
setContentView(activityLayout);
// Initialize credentials and service object.
SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
mCredential = GoogleAccountCredential.usingOAuth2(
getApplicationContext(), Arrays.asList(SCOPES))
.setBackOff(new ExponentialBackOff())
.setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, null));
}
/**
* Called whenever this activity is pushed to the foreground, such as after
* a call to onCreate().
*/
@Override
protected void onResume() {
super.onResume();
if (isGooglePlayServicesAvailable()) {
refreshResults();
} else {
mOutputText.setText("Google Play Services required: " +
"after installing, close and relaunch this app.");
}
}
/**
* Called when an activity launched here (specifically, AccountPicker
* and authorization) exits, giving you the requestCode you started it with,
* the resultCode it returned, and any additional data from it.
* @param requestCode code indicating which activity result is incoming.
* @param resultCode code indicating the result of the incoming
* activity result.
* @param data Intent (containing result data) returned by incoming
* activity result.
*/
@Override
protected void onActivityResult(
int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case REQUEST_GOOGLE_PLAY_SERVICES:
if (resultCode != RESULT_OK) {
isGooglePlayServicesAvailable();
}
break;
case REQUEST_ACCOUNT_PICKER:
if (resultCode == RESULT_OK && data != null &&
data.getExtras() != null) {
String accountName =
data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
if (accountName != null) {
mCredential.setSelectedAccountName(accountName);
SharedPreferences settings =
getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putString(PREF_ACCOUNT_NAME, accountName);
editor.apply();
}
} else if (resultCode == RESULT_CANCELED) {
mOutputText.setText("Account unspecified.");
}
break;
case REQUEST_AUTHORIZATION:
if (resultCode != RESULT_OK) {
chooseAccount();
}
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
/**
* Attempt to get a set of data from the Google Tasks API to display. If the
* email address isn't known yet, then call chooseAccount() method so the
* user can pick an account.
*/
private void refreshResults() {
if (mCredential.getSelectedAccountName() == null) {
chooseAccount();
} else {
if (isDeviceOnline()) {
new MakeRequestTask(mCredential).execute();
} else {
mOutputText.setText("No network connection available.");
}
}
}
/**
* Starts an activity in Google Play Services so the user can pick an
* account.
*/
private void chooseAccount() {
startActivityForResult(
mCredential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
}
/**
* Checks whether the device currently has a network connection.
* @return true if the device has a network connection, false otherwise.
*/
private boolean isDeviceOnline() {
ConnectivityManager connMgr =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnected());
}
/**
* Check that Google Play services APK is installed and up to date. Will
* launch an error dialog for the user to update Google Play Services if
* possible.
* @return true if Google Play Services is available and up to
* date on this device; false otherwise.
*/
private boolean isGooglePlayServicesAvailable() {
final int connectionStatusCode =
GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (GooglePlayServicesUtil.isUserRecoverableError(connectionStatusCode)) {
showGooglePlayServicesAvailabilityErrorDialog(connectionStatusCode);
return false;
} else if (connectionStatusCode != ConnectionResult.SUCCESS ) {
return false;
}
return true;
}
/**
* Display an error dialog showing that Google Play Services is missing
* or out of date.
* @param connectionStatusCode code describing the presence (or lack of)
* Google Play Services on this device.
*/
void showGooglePlayServicesAvailabilityErrorDialog(
final int connectionStatusCode) {
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(
connectionStatusCode,
MainActivity.this,
REQUEST_GOOGLE_PLAY_SERVICES);
dialog.show();
}
/**
* An asynchronous task that handles the Google Tasks API call.
* Placing the API calls in their own task ensures the UI stays responsive.
*/
private class MakeRequestTask extends AsyncTask<Void, Void, List<String>> {
private com.google.api.services.tasks.Tasks mService = null;
private Exception mLastError = null;
public MakeRequestTask(GoogleAccountCredential credential) {
HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
mService = new com.google.api.services.tasks.Tasks.Builder(
transport, jsonFactory, credential)
.setApplicationName("Google Tasks API Android Quickstart")
.build();
}
/**
* Background task to call Google Tasks API.
* @param params no parameters needed for this task.
*/
@Override
protected List<String> doInBackground(Void... params) {
try {
//getTasks();
insertTask();
return getTasks();
} catch (Exception e) {
mLastError = e;
cancel(true);
return null;
}
}
/**
* Fetch a list of the first 10 task lists.
* @return List of Strings describing task lists, or an empty list if
* there are no task lists found.
* @throws IOException
*/
private List<String> getTasks() throws IOException{
List<String> result1 = new ArrayList<String>();
List<Task> tasks =
mService.tasks().list("@default").setFields("items/title").execute().getItems();
if (tasks != null) {
for (Task task : tasks) {
result1.add(task.getTitle());
}
} else {
result1.add("No tasks.");
}
adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, result1);
listView.setAdapter(adapter);
return result1;
}
private void insertTask() throws IOException
{
Task task = new Task();
task.setTitle("New Task");
task.setNotes("Please complete me");
Task result = mService.tasks().insert("@default", task).execute();
System.out.println(result.getTitle());
}
private List<String> getDataFromApi() throws IOException {
// List up to 10 task lists.
List<String> taskListInfo = new ArrayList<String>();
TaskLists result = mService.tasklists().list()
.setMaxResults(Long.valueOf(10))
.execute();
List<TaskList> tasklists = result.getItems();
if (tasklists != null) {
for (TaskList tasklist : tasklists) {
taskListInfo.add(String.format("%s (%s)\n",
tasklist.getTitle(),
tasklist.getId()));
}
}
return taskListInfo;
}
@Override
protected void onPreExecute() {
mOutputText.setText("");
mProgress.show();
}
@Override
protected void onPostExecute(List<String> output) {
mProgress.hide();
if (output == null || output.size() == 0) {
mOutputText.setText("No results returned.");
} else {
output.add(0, "Data retrieved using the Google Tasks API:");
mOutputText.setText(TextUtils.join("\n", output));
}
}
@Override
protected void onCancelled() {
mProgress.hide();
if (mLastError != null) {
if (mLastError instanceof GooglePlayServicesAvailabilityIOException) {
showGooglePlayServicesAvailabilityErrorDialog(
((GooglePlayServicesAvailabilityIOException) mLastError)
.getConnectionStatusCode());
} else if (mLastError instanceof UserRecoverableAuthIOException) {
startActivityForResult(
((UserRecoverableAuthIOException) mLastError).getIntent(),
MainActivity.REQUEST_AUTHORIZATION);
} else {
mOutputText.setText("The following error occurred:\n"
+ mLastError.getMessage());
}
} else {
mOutputText.setText("Request cancelled.");
}
}
}
谢谢你..
您的 SCOPES
有一个值 TASKS_READONLY
,您真的无法插入具有这种范围的任何内容。将其更改为 TASKS
或其他可用常量(应该是 read/write 访问)。有关授权的更多信息,请参阅任务 API 文档的 Authorize Requests 页面。
如果您想查看 Android 任务示例,可以按照他们的 Google API samples page
中的说明进行操作
我正在尝试与 google 任务同步。我从默认列表中获取了任务列表。现在我想在默认列表中插入一个任务。
我遵循了文档。
https://developers.google.com/google-apps/tasks/v1/reference/tasks/insert
此外,我已将任务 api 设置为已启用。我也生成了客户端 ID。
OAuth 2.0 客户端 ID
名称创建日期类型客户 ID
Android 客户 1 2016 年 3 月 19 日 Android 256433535354-h653umd5mddo5t139moof3cvd56asnec.apps.googleusercontent.com
当我尝试插入任务时,我仍然收到 403 forbidden 错误,错误消息是:权限不足。
我还设置了 OAuth 2.0 范围来管理您的所有任务。来自这里:
https://developers.google.com/apis-explorer/?hl=en_US#p/tasks/v1/
我仍然无法插入任务。
我不明白出了什么问题..请帮忙..
依赖关系:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.google.android.gms:play-services-identity:7.8.0'
compile('com.google.api-client:google-api-client-android:1.20.0') {
exclude group: 'org.apache.httpcomponents'
}
compile('com.google.apis:google-api-services-tasks:v1-rev41-1.20.0') {
exclude group: 'org.apache.httpcomponents'
}
}
代码:
public class MainActivity extends AppCompatActivity {
GoogleAccountCredential mCredential;
private TextView mOutputText;
ProgressDialog mProgress;
static final int REQUEST_ACCOUNT_PICKER = 1000;
static final int REQUEST_AUTHORIZATION = 1001;
static final int REQUEST_GOOGLE_PLAY_SERVICES = 1002;
private static final String PREF_ACCOUNT_NAME = "accountName";
private static final String[] SCOPES = { TasksScopes.TASKS_READONLY };
ListView listView;
ArrayAdapter<String> adapter;
List<String> result1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout activityLayout = new LinearLayout(this);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
activityLayout.setLayoutParams(lp);
activityLayout.setOrientation(LinearLayout.VERTICAL);
activityLayout.setPadding(16, 16, 16, 16);
ViewGroup.LayoutParams tlp = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
mOutputText = new TextView(this);
mOutputText.setLayoutParams(tlp);
mOutputText.setPadding(16, 16, 16, 16);
mOutputText.setVerticalScrollBarEnabled(true);
mOutputText.setMovementMethod(new ScrollingMovementMethod());
activityLayout.addView(mOutputText);
mProgress = new ProgressDialog(this);
mProgress.setMessage("Calling Google Tasks API ...");
listView = (ListView) findViewById(R.id.list);
setContentView(activityLayout);
// Initialize credentials and service object.
SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
mCredential = GoogleAccountCredential.usingOAuth2(
getApplicationContext(), Arrays.asList(SCOPES))
.setBackOff(new ExponentialBackOff())
.setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, null));
}
/**
* Called whenever this activity is pushed to the foreground, such as after
* a call to onCreate().
*/
@Override
protected void onResume() {
super.onResume();
if (isGooglePlayServicesAvailable()) {
refreshResults();
} else {
mOutputText.setText("Google Play Services required: " +
"after installing, close and relaunch this app.");
}
}
/**
* Called when an activity launched here (specifically, AccountPicker
* and authorization) exits, giving you the requestCode you started it with,
* the resultCode it returned, and any additional data from it.
* @param requestCode code indicating which activity result is incoming.
* @param resultCode code indicating the result of the incoming
* activity result.
* @param data Intent (containing result data) returned by incoming
* activity result.
*/
@Override
protected void onActivityResult(
int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case REQUEST_GOOGLE_PLAY_SERVICES:
if (resultCode != RESULT_OK) {
isGooglePlayServicesAvailable();
}
break;
case REQUEST_ACCOUNT_PICKER:
if (resultCode == RESULT_OK && data != null &&
data.getExtras() != null) {
String accountName =
data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
if (accountName != null) {
mCredential.setSelectedAccountName(accountName);
SharedPreferences settings =
getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putString(PREF_ACCOUNT_NAME, accountName);
editor.apply();
}
} else if (resultCode == RESULT_CANCELED) {
mOutputText.setText("Account unspecified.");
}
break;
case REQUEST_AUTHORIZATION:
if (resultCode != RESULT_OK) {
chooseAccount();
}
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
/**
* Attempt to get a set of data from the Google Tasks API to display. If the
* email address isn't known yet, then call chooseAccount() method so the
* user can pick an account.
*/
private void refreshResults() {
if (mCredential.getSelectedAccountName() == null) {
chooseAccount();
} else {
if (isDeviceOnline()) {
new MakeRequestTask(mCredential).execute();
} else {
mOutputText.setText("No network connection available.");
}
}
}
/**
* Starts an activity in Google Play Services so the user can pick an
* account.
*/
private void chooseAccount() {
startActivityForResult(
mCredential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
}
/**
* Checks whether the device currently has a network connection.
* @return true if the device has a network connection, false otherwise.
*/
private boolean isDeviceOnline() {
ConnectivityManager connMgr =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnected());
}
/**
* Check that Google Play services APK is installed and up to date. Will
* launch an error dialog for the user to update Google Play Services if
* possible.
* @return true if Google Play Services is available and up to
* date on this device; false otherwise.
*/
private boolean isGooglePlayServicesAvailable() {
final int connectionStatusCode =
GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (GooglePlayServicesUtil.isUserRecoverableError(connectionStatusCode)) {
showGooglePlayServicesAvailabilityErrorDialog(connectionStatusCode);
return false;
} else if (connectionStatusCode != ConnectionResult.SUCCESS ) {
return false;
}
return true;
}
/**
* Display an error dialog showing that Google Play Services is missing
* or out of date.
* @param connectionStatusCode code describing the presence (or lack of)
* Google Play Services on this device.
*/
void showGooglePlayServicesAvailabilityErrorDialog(
final int connectionStatusCode) {
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(
connectionStatusCode,
MainActivity.this,
REQUEST_GOOGLE_PLAY_SERVICES);
dialog.show();
}
/**
* An asynchronous task that handles the Google Tasks API call.
* Placing the API calls in their own task ensures the UI stays responsive.
*/
private class MakeRequestTask extends AsyncTask<Void, Void, List<String>> {
private com.google.api.services.tasks.Tasks mService = null;
private Exception mLastError = null;
public MakeRequestTask(GoogleAccountCredential credential) {
HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
mService = new com.google.api.services.tasks.Tasks.Builder(
transport, jsonFactory, credential)
.setApplicationName("Google Tasks API Android Quickstart")
.build();
}
/**
* Background task to call Google Tasks API.
* @param params no parameters needed for this task.
*/
@Override
protected List<String> doInBackground(Void... params) {
try {
//getTasks();
insertTask();
return getTasks();
} catch (Exception e) {
mLastError = e;
cancel(true);
return null;
}
}
/**
* Fetch a list of the first 10 task lists.
* @return List of Strings describing task lists, or an empty list if
* there are no task lists found.
* @throws IOException
*/
private List<String> getTasks() throws IOException{
List<String> result1 = new ArrayList<String>();
List<Task> tasks =
mService.tasks().list("@default").setFields("items/title").execute().getItems();
if (tasks != null) {
for (Task task : tasks) {
result1.add(task.getTitle());
}
} else {
result1.add("No tasks.");
}
adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, result1);
listView.setAdapter(adapter);
return result1;
}
private void insertTask() throws IOException
{
Task task = new Task();
task.setTitle("New Task");
task.setNotes("Please complete me");
Task result = mService.tasks().insert("@default", task).execute();
System.out.println(result.getTitle());
}
private List<String> getDataFromApi() throws IOException {
// List up to 10 task lists.
List<String> taskListInfo = new ArrayList<String>();
TaskLists result = mService.tasklists().list()
.setMaxResults(Long.valueOf(10))
.execute();
List<TaskList> tasklists = result.getItems();
if (tasklists != null) {
for (TaskList tasklist : tasklists) {
taskListInfo.add(String.format("%s (%s)\n",
tasklist.getTitle(),
tasklist.getId()));
}
}
return taskListInfo;
}
@Override
protected void onPreExecute() {
mOutputText.setText("");
mProgress.show();
}
@Override
protected void onPostExecute(List<String> output) {
mProgress.hide();
if (output == null || output.size() == 0) {
mOutputText.setText("No results returned.");
} else {
output.add(0, "Data retrieved using the Google Tasks API:");
mOutputText.setText(TextUtils.join("\n", output));
}
}
@Override
protected void onCancelled() {
mProgress.hide();
if (mLastError != null) {
if (mLastError instanceof GooglePlayServicesAvailabilityIOException) {
showGooglePlayServicesAvailabilityErrorDialog(
((GooglePlayServicesAvailabilityIOException) mLastError)
.getConnectionStatusCode());
} else if (mLastError instanceof UserRecoverableAuthIOException) {
startActivityForResult(
((UserRecoverableAuthIOException) mLastError).getIntent(),
MainActivity.REQUEST_AUTHORIZATION);
} else {
mOutputText.setText("The following error occurred:\n"
+ mLastError.getMessage());
}
} else {
mOutputText.setText("Request cancelled.");
}
}
}
谢谢你..
您的 SCOPES
有一个值 TASKS_READONLY
,您真的无法插入具有这种范围的任何内容。将其更改为 TASKS
或其他可用常量(应该是 read/write 访问)。有关授权的更多信息,请参阅任务 API 文档的 Authorize Requests 页面。
如果您想查看 Android 任务示例,可以按照他们的 Google API samples page
中的说明进行操作