今天进入另一个路障,在我编写用于记录用户项目时间的桌面Chrome应用程序的道路上。
我想要做的(并且失败)是使用Apps Script API访问一个google工作表,该工作表保留了我想在Chrome App UI中填充下拉列表的信息(项目编号)。
更新 我已经重新阐述了这一点,以便明确我的问题。
我似乎无法实现从我的Chrome应用程序调用Apps脚本功能。我已经阅读了这个Execution API,但似乎仍然无法进行着色。由于某些原因,我不断得到"未捕获的ReferenceError:gapi未定义"在我的控制台中。
我设法做的是在开发者控制台中使用相同项目名称的Apps脚本和Chrome应用程序。不知道是否需要,但认为它可能只有1 Oauth2请求。
我的头部缺少什么东西?
非常感谢任何帮助或想法。
这是我的manifest.json
{
"manifest_version": 2,
"name": "TimeSheet",
"description": "Small and easy desktop app for entering time spent on project files",
"version": "0.1.0",
"icons": {
"128": "icon_128.png"
},
"app": {
"background": {
"scripts": ["background.js"]
}
},
"permissions": [
"identity",
"app.window.alwaysOnTop"
],
"oauth2": {
"client_id": "clientid.apps.googleusercontent.com",
"scopes": [
"https://www.googleapis.com/auth/drive",
"https://www.googleapis.com/auth/spreadsheets"
]
},
"key": "very long string"
}
这是在我的main.js
中运行的Oauth2代码//This code confirms Oauth2 for access to google drive and related files
window.onload = function(){
document.querySelector("#Oauth2").addEventListener("click", function(){
chrome.identity.getAuthToken({"interactive": true}, function(token){
console.log(token);
});
});
};
// ID of the script to call. Acquire this from the Apps Script editor,
// under Publish > Deploy as API executable.
var scriptId = "blah";
// Create execution request.
var request = {
'function': 'getProjectNumbers',
};
// Make the request.
var op = gapi.client.request({
'root': 'https://script.googleapis.com',
'path': 'v1/scripts/' + scriptId + ':run',
'method': 'POST',
'body': request
});
// Log the results of the request.
op.execute(function(resp) {
if (resp.error && resp.error.status) {
// The API encountered a problem before the script started executing.
console.log('Error calling API: ' + JSON.stringify(resp, null, 2));
} else if (resp.error) {
// The API executed, but the script returned an error.
var error = resp.error.details[0];
console.log('Script error! Message: ' + error.errorMessage);
if (error.scriptStackTraceElements) {
// There may not be a stacktrace if the script didn't start executing.
console.log('Script error stacktrace:');
for (var i = 0; i < error.scriptStackTraceElements.length; i++) {
var trace = error.scriptStackTraceElements[i];
console.log('\t' + trace.function + ':' + trace.lineNumber);
}
}
} else {
// Here, the function returns an array of strings.
var projectNumbers = resp.response.result;
console.log('Project numbers in spreadsheet:');
projectNumbers.forEach(function(name){
console.log(name);
});
}
});
这是应用程序脚本代码:
var projectDatabaseKey = 'blah'; //Project Database Sheet spreadsheet key
var pprojectDatabaseSheet = 'Project Database'; //Project Database Sheet spreadsheet sheet
//Function to revieve data of project numbers for drop down list
function getProjectNumbers() {
return SpreadsheetApp
.openById(projectDatabaseKey).getSheetByName(projectDatabaseSheet)
.getRange("A2:A" + (SpreadsheetApp.openById(projectDatabaseKey).getSheetByName(projectDatabaseSheet).getLastRow()))
.getValues();
}
我真的不确定如何使用Oauth2令牌以及如何将其应用于apps脚本。
更新
好的,我曾尝试在不同的庄园中调用应用程序脚本,今天我正在尝试使用gapi-chrome-apps.js库来执行oauth2工作。
现在我的问题是我得到了这个错误,这可能是我猜的一系列事情:
POST https://www.googleapis.com/v1/scripts/blahblah:run 404()
gapi.client.request @ VM80 gapi-chrome-apps.js:105
getSheetsList @ gapiCallback.js:17
(匿名函数)@ gapiCallback.js:49
callbackWrapper @ VM80 gapi-chrome-apps.js:68
target。(匿名函数)@ extensions :: SafeBuiltins:19
safeCallbackApply @ extensions :: sendRequest:21
handleResponse @ extensions :: sendRequest:72
这个错误,来自gapi-chrome-apps.js脚本:
Uncaught SyntaxError:位于0的JSON中的意外标记N
真的不确定导致这种情况的原因,这是我的更新代码:
//get listof sheets in spreadsheet
function getSheetsList(){
var scriptId = "blahblah";
// Initialize parameters for function call.
var sheetId = "blahblah";
// Create execution request.
var requests = {
'function': 'getSheetNames',
'parameters': [sheetId],
'devMode': true // Optional.
};
// Make the request.
gapi.client.request({
'root': 'https://script.googleapis.com',
'path': 'v1/scripts/' + scriptId + ':run',
'method': 'POST',
'body': requests,
'callback': printSheetsList
});
}
// Log the results of the request.
function printSheetsList(resp) {
if (resp.error && resp.error.status) {
// The API encountered a problem before the script started executing.
console.log('Error calling API: ' + JSON.stringify(resp, null, 2));
} else if (resp.error) {
// The API executed, but the script returned an error.
var error = resp.error.details[0];
console.log('Script error! Message: ' + error.errorMessage);
} else {
// Here, the function returns an array of strings.
var sheetNames = resp.response.result;
console.log('Sheet names in spreadsheet:');
sheetNames.forEach(function(name){
console.log(name);
});
}
}
//Prompts the user for authorization and then proceeds to
function authorize(params, callback) {
gapi.auth.authorize(params, function(accessToken) {
if (!accessToken) {
console.log("Error getting authorization");
} else {
callback();
}
});
}
function gapiIsLoaded() {
var params = { 'immediate': true };
if (!(chrome && chrome.app && chrome.app.runtime)) {
params.scope = "https://www.googleapis.com/auth/drive";
params.client_id = "blahblah";
gapi.auth.init(authorize.bind(null, params, getSheetsList));
} else {
authorize(params, getSheetsList);
}
}
答案 0 :(得分:2)
使用传统的GAPI无法运行,因为它会动态加载更多外部脚本和应用are not allowed to do that。
一种可能的解决方案是在sandboxed page中运行GAPI代码,这可以克服远程代码限制。但是,这很麻烦,因为您需要使用postMessage
来回传递数据。
另一种方法是尝试使用Google提供的库gapi-chrome-apps.js,该库适用于Chrome应用(并使用chrome.identity
管理OAuth) - 但请注意此评论:
如果没有其他修改,此库可能不适合使用。
答案 1 :(得分:0)
根据您的帖子,您只是没有定义gapi
。你可以像这样加载它
jQuery.getScript( "https://apis.google.com/js/api.js", onApiLoad );
其中onApiLoad
是您在加载gapi
时要调用的函数。
对于你的代码,我会将以下代码包装在这样的函数中:
function onApiLoad() {
// Make the request.
var op = gapi.client.request({
'root': 'https://script.googleapis.com',
'path': 'v1/scripts/' + scriptId + ':run',
'method': 'POST',
'body': request
});
// Log the results of the request.
op.execute(function(resp) {
if (resp.error && resp.error.status) {
// The API encountered a problem before the script started executing.
console.log('Error calling API: ' + JSON.stringify(resp, null, 2));
} else if (resp.error) {
// The API executed, but the script returned an error.
var error = resp.error.details[0];
console.log('Script error! Message: ' + error.errorMessage);
if (error.scriptStackTraceElements) {
// There may not be a stacktrace if the script didn't start executing.
console.log('Script error stacktrace:');
for (var i = 0; i < error.scriptStackTraceElements.length; i++) {
var trace = error.scriptStackTraceElements[i];
console.log('\t' + trace.function + ':' + trace.lineNumber);
}
}
} else {
// Here, the function returns an array of strings.
var projectNumbers = resp.response.result;
console.log('Project numbers in spreadsheet:');
projectNumbers.forEach(function(name){
console.log(name);
});
}
});
}
感谢the second answer in this post,下面的代码是$ .getScript()的纯JS实现。它包含一个回调,所以下面的代码片段应该可以工作,假设你将代码包装在一个函数中,如上所述。
function getScript(source, callback) {
var script = document.createElement('script');
var prior = document.getElementsByTagName('script')[0];
script.async = 1;
prior.parentNode.insertBefore(script, prior);
script.onload = script.onreadystatechange = function( _, isAbort ) {
if(isAbort || !script.readyState || /loaded|complete/.test(script.readyState) ) {
script.onload = script.onreadystatechange = null;
script = undefined;
if(!isAbort) { if(callback) callback(); }
}
};
script.src = source;
}
getScript("https://apis.google.com/js/api.js", onApiLoad);