Ранее сегодня IBM объявила о новом партнерстве с Box. Box — поставщик облачных хранилищ, очень похожий на Dropbox, OneDrive и другие сервисы, но также предоставляет некоторые довольно интересные функции рабочего процесса. Пока еще рано, скоро вы увидите несколько интересных взаимодействий между IBM и Box. Я решил посмотреть, насколько легко будет интегрировать Box в гибридное мобильное приложение, используя как Ionic, так и IBM MobileFirst . Это просто простое доказательство концепции, но оно демонстрирует, как вы можете использовать все эти разные части вместе в одном приложении.
Прежде чем углубиться в код, давайте посмотрим на несколько скриншотов приложения в действии. При загрузке приложения вы увидите кнопку, предлагающую войти в систему с помощью Box.
Нажатие на эту кнопку начнет процесс аутентификации. Вы должны иметь учетную запись на Box.com, конечно.
После входа в систему вы должны разрешить приложению доступ к вашим данным:
После того, как вы разрешили приложению доступ к вашей учетной записи Box, вы можете приступить к работе с вашими данными. Для демонстрации я просто позволил приложению загружать изображения с устройства в учетную запись Box. (Вы можете изменить код, чтобы новые снимки можно было делать с помощью камеры. Поскольку я проводил тестирование на симуляторе, я ограничил его существующими снимками.)
После выбора изображения я отображаю эскиз и затем загружаю его.
Если ваша учетная запись Box открыта в браузере (у них также есть настольный клиент), вы можете увидеть изображение.
Вот и все. Box API обеспечивает полный доступ к содержимому Box, а не только загрузку. Вы даже можете использовать специальный API просмотра для отображения воспроизведения содержимого Box. Это довольно хороший API, и я призываю вас прочитать больше об этом на их сайте разработчика . Итак — поговорим о коде.
Чтобы справиться с OAuth, я использовал замечательную библиотеку от Nic Raboy под названием ng-cordova-oauth . Он обеспечивает поддержку OAuth для различных задач, в том числе Box. Насколько это просто? Вот код позади кнопки, которую вы видели на снимке экрана выше.
$scope.doAuth = function() {
Logger.log("Beginning to auth against Box");
$cordovaOauth.box(clientId, clientSecret,state).then(function(result) {
Logger.log("Successful log to Box");
token = result.access_token;
$scope.noAuth = false;
}, function(error) {
console.log('Error',error);
});
}
Да, вот и все. Тогда использовать сам API довольно просто. Сначала я написал некоторый код, чтобы просто протестировать использование API, в моем случае запрашивая папки в корне учетной записи. Вот как я это сделал, используя $ http-сервис Angular:
$scope.getFolders = function() {
console.log("attempting to get folders");
$http.defaults.headers.common.Authorization = 'Bearer '+token;
$http.get("https://api.box.com/2.0/folders/0").success(function(data, status, headers, config) {
console.log('succcess');
console.dir(data);
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
console.log('error');
console.dir(arguments);
});
}
Единственная интересная часть здесь — это установка токена OAuth в заголовке. Вы можете видеть, что это одна простая строка до получения. Технически мне нужно сделать это только один раз и установить это после входа в систему — но, как я уже сказал, я написал это просто как тест API. Загрузка файлов была немного более сложной. Вместо $ http я использовал плагин Cordova FileTransfer. Это позволило мне загрузить файл изображения, выбранный пользователем. Вот вся операция, включая выбор камеры и загрузку.
$scope.doPicture = function() {
navigator.camera.getPicture(function(uri) {
$scope.selectedImage = uri;
$scope.status.message = "Uploading bits to Box...";
$scope.$apply();
Logger.log("Going to send a file to Box");
var win = function (r) {
console.log("Code = " + r.responseCode);
console.log("Response = " + r.response);
console.log("Sent = " + r.bytesSent);
$scope.status.message = "Sent to box!";
Logger.log("Sent a file to box!");
$scope.$apply();
}
var fail = function (error) {
alert("An error has occurred: Code = " + error.code);
console.log("upload error source " + error.source);
console.log("upload error target " + error.target);
Logger.log("Failed to send to Box");
}
var options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = uri.substr(uri.lastIndexOf('/') + 1);
options.mimeType = "image/jpeg";
var headers={'Authorization':'Bearer '+token};
options.headers = headers;
var params = {};
params.attributes = '{"name":"'+options.fileName+'", "parent":{"id":"0"}}';
options.params = params;
var ft = new FileTransfer();
ft.upload(uri, encodeURI("https://upload.box.com/api/2.0/files/content"), win, fail, options);
}, function(err) {
console.log("Camera error", err);
}, {
quality:25,
destinationType:Camera.DestinationType.FILE_URI,
sourceType:Camera.PictureSourceType.PHOTOLIBRARY
});
}
And that’s it. I then mixed in MobileFirst – specifically the logging service. I blogged about this a few months back (). It is a rather simple API I can make available via a service in my app:
}).factory('Logger', function() {
var logger = WL.Logger.create({autoSendLogs:true});
return {
log:function(s) {
logger.log('log', s);
console.log(s);
}
}
})
Then when I inject Logger
into my controllers, I can just do Logger.log("some message")
. There were a few examples of that above. Then when my application is out in the wild, I can look at my analytics in my MobileFirst server:
Want to see all of the code? You can see all the code here: https://github.com/cfjedimaster/Cordova-Examples/tree/master/boxdemo_mfp. Note that I ran into two small issues with Nic’s OAuth plugin. The first is that after authenticating with Box, you will see a 404 error temporarily. Nic already has a fix for this in the dev branch of his library. It is harmless and can be ignored. The second issue was specifically involving his code running in MobileFirst. Plugins act a bit differently there and his code to check for the InAppBrowser didn’t work. (To be clear, that one is absolutely not his fault.) The workaround was a quick mod to his code and is in the GitHub repo. You can see a video of the app in action below.