Интеграция Google Диска в Android

  1. Начиная
  2. Регистрация на Google Диске
  3. Сборка вашего приложения для Android
  4. Обновление файла Gradle
  5. Изменение манифеста Android
  6. Создание провайдера файлов
  7. Добавление строк
  8. Обновление интерфейса
  9. Создание интерфейса ServiceListener
  10. Создание класса данных: GoogleDriveConfig
  11. Создание GoogleDriveService
  12. Обработка результатов деятельности
  13. Открытие диалога с выбранным файлом
  14. Вход и выход
  15. Обновление MainActivity
  16. Обработка метода OnActivityResult
  17. Куда пойти отсюда?

Есть моменты, когда пользователь должен выбрать файл для загрузки в приложение. Существует множество мест для загрузки файлов: локальное хранилище на устройстве, Dropbox, Google Drive и другие сервисы. В этом руководстве вы создадите приложение, которое аутентифицирует пользователя с помощью Google, запустит Google Drive и позволит пользователю выбрать файл. Как только пользователь выберет файл, приложение загрузит и откроет его.

Google Drive SDK используется для подключения к файлам Google Drive пользователя. В этом руководстве основное внимание будет уделено предоставлению пользователю возможности выбрать существующий файл, загрузить его и отобразить в приложении. Вы будете использовать встроенный инструмент выбора файлов Google Диска, который позволит нам выбрать любой файл, который находится на диске Google пользователя.

Примечание

. Если вы новичок в разработке под Android или на языке Kotlin, настоятельно рекомендуется начать с Начало разработки Android с Kotlin освоить основные инструменты и концепции.

Начиная

Убедитесь, что у вас есть Android Studio и плагин Kotlin, прежде чем начать. Для установки Android Studio перейдите на developer.android.com , Для запуска приложения вашему телефону или эмулятору потребуются новейшие сервисы Google Play на устройстве.

Поскольку ваш пользовательский интерфейс будет пустым, откройте Android Studio 3.1.1 или более позднюю версию и создайте новый проект. В Android Studio выберите « Начать новый проект Android Studio» на начальном экране или « Новый проект» в меню « Файл» .

В Android Studio выберите « Начать новый проект Android Studio» на начальном экране или « Новый проект» в меню « Файл»

Введите имя GoogleDriveDemo , домен вашей компании (или example.com, если хотите) и местоположение проекта. Убедитесь, что выбрана поддержка Kotlin, а затем нажмите Далее .

Убедитесь, что выбрана поддержка Kotlin, а затем нажмите Далее

Вам не нужно ничего менять на этом экране. Просто нажмите Далее .

Просто нажмите Далее

Выберите Empty Activity и нажмите Next .

Выберите Empty Activity и нажмите Next

Нажмите Готово .

Регистрация на Google Диске

Чтобы использовать Google Drive SDK, вам нужно включить API в своем приложении.

Прогулка по ступеням:

Сборка вашего приложения для Android

Вернитесь в приложение Android, и вы сможете начать добавлять настройки и код.

Обновление файла Gradle

Сначала вы обновите файл build.gradle в папке приложения . Добавьте две переменные для версии сервисов Google Play и библиотек поддержки Android после того, как операторы применения плагина находятся вверху:

ext {play_services_version = "15.0.1" support_version = "27.1.1"}

Это позволит вам повторно использовать переменные и легко менять версии. Замените версию com.android.support:appcompat-v7 на переменную и добавьте библиотеку поддержки проекта, обе в блоке зависимостей:

реализация "com.android.support:appcompat-v7:$support_version" реализация "com.android.support:design:$support_version"

Библиотека appcompat содержит все классы совместимости, которые помогут вам написать код, который работает во многих версиях ОС Android. Библиотека поддержки дизайна используется в этом руководстве для отображения сообщения Snackbar.

Затем добавьте библиотеки для Google Drive SDK и библиотеку Okio из Square для загрузки файлов.

// Реализация Google Диска "com.google.android.gms: play-services-auth: $ play_services_version" Реализация "com.google.android.gms: play-services-drive: $ play_services_version" Реализация "com.squareup.okio: Окио: 1.14.0'

Теперь синхронизируйте файлы Gradle проекта (Файл ▸ Синхронизировать проект с файлами Gradle)

Изменение манифеста Android

Далее вы измените AndroidManifest.xml . Откройте файл и добавьте интернет-права прямо над тегом:

<использует-разрешение android: name = "android.permission.INTERNET" />

Добавьте следующий код, чтобы указать версию служб Google Play в качестве первого подэлемента в теге:

<meta-data android: name = "com.google.android.gms.version" android: value = "@ integer / google_play_services_version" />

Если вы нажмете командным нажатием (или Ctrl-клик на ПК) на @ integer / google_play_services_version, вы увидите, что он перенаправит вас в файл значений Play Services, который даст Google Play SDK знать, какую версию вы используете.

Создание провайдера файлов

Далее вы создадите FileProvider . Это требуется для Android 8.0 Oreo и выше для доступа к локальным файлам.

Сначала создайте новый каталог, щелкнув правой кнопкой мыши по каталогу app / res и выбрав New Directory Android Resource Directory . Назовите это xml . Щелкните правой кнопкой мыши каталог xml и выберите « Создать» ▸ «Файл» ; назовите это provider_paths .

Это необходимо, поскольку Android Oreo не поддерживает совместное использование файла: // urls. Откройте новый файл и вставьте следующее:

<? xml version = "1.0" encoding = "utf-8"?> <paths xmlns: android = "http://schemas.android.com/apk/res/android"> <external-path name = "external_files" path = "." /> </ paths>

Теперь в файле манифеста Android после недавно добавленного тега метаданных добавьте:

<provider android: name = "android.support.v4.content.FileProvider" android: members = "$ {applicationId} .provider" android: exported = "false" android: grantUriPermissions = "true"> <метаданные android: name = "android.support.FILE_PROVIDER_PATHS" android: resource = "@ xml / provider_paths" />

Это настраивает ваше приложение на использование класса Android FileProvider для обработки локальных файлов в виде URL-адресов, а не файлов. Это ограничение безопасности, введенное Google.

Добавление строк

Теперь вы добавите строки, которые вам понадобятся для пользовательского интерфейса. Откройте файл strings.xml и добавьте:

<string name = "source_google_drive"> Google Диск </ string> <string name = "start_drive"> Запустить Google Drive </ string> <string name = "login"> Войти </ string> <string name = "logout" > Выйти из системы </ string> <string name = "status_logged_out"> Выйти из системы </ string> <string name = "status_logged_in"> Войти в систему </ string> <string name = "status_user_cancelled"> Пользователь отменен </ string> < string name = "status_error"> Мы обнаружили проблему:% 1 $ s </ string> <string name = "not_open_file"> Не удалось открыть файл </ string>

Первая строка предназначена для заголовка активности на Google Диске, а остальные - для пользовательского интерфейса.

Обновление интерфейса

Далее вы обновите пользовательский интерфейс. Для этого вы просто создадите три кнопки для входа в систему , выхода из системы и открытия Google Диска , а также TextView для отображения статуса входа в систему. Откройте файл activity_main.xml и замените содержимое следующим:

<? xml version = "1.0" encoding = "utf-8"?> <android.support.constraint.ConstraintLayout xmlns: android = "http://schemas.android.com/apk/res/android" xmlns: app = "http://schemas.android.com/apk/res-auto" xmlns: tools = "http://schemas.android.com/tools" android: id = "@ + id / main_layout" android: layout_width = " match_parent "android: layout_height =" match_parent "tools: context =". MainActivity "> <Кнопка android: id =" @ + id / login "android: layout_width =" wrap_content "android: layout_height =" wrap_content "android: text =" @ string / login "app: layout_constraintBottom_toTopOf =" @ + id / start "app: layout_constraintEnd_toEndOf =" родительское "приложение: layout_constraintHor Horizontal_bias =" 0.5 " id = "@ + id / start" android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: text = "@ string / start_drive" app: layout_constraintBottom_toTopOf = "@ + id / logout" app: layout_constraintEnd_toEndOf = "parent "app: layout_constraintHorizont_b ias = "0.5" app: layout_constraintStart_toStartOf = "родительское" приложение: layout_constraintTop_toBottomOf = "@ + id / login" /> <Кнопка android: id = "@ + id / logout" android: layout_width = "wrap_content" android: layout_height = " wrap_content "android: text =" @ string / logout "app: layout_constraintBottom_toBottomOf =" parent "app: layout_constraintEnd_toEndOf =" parent " "/> <TextView android: id =" @ + id / status "android: layout_width =" 0dp "android: layout_height =" wrap_content "android: layout_marginBottom =" 8dp "android: gravity =" center_hor Horizontal "android: text =" @ string / status_logged_out "app: layout_constraintBottom_toBottomOf =" родительский "app: layout_constraintEnd_toEndOf =" родительский "app: layout_constraintStart_toStartOf =" parent "/> </android.support.constraint.ConstraintLayout>

Запустите приложение и убедитесь, что интерфейс отображается правильно:

Если все работает правильно, у вас должен быть базовый интерфейс с тремя кнопками и сообщением о состоянии внизу. Если проект не компилируется или что-то не так во время работы, сравните вашу работу с каждым из шагов, описанных выше.

Создание интерфейса ServiceListener

Поскольку существует всего несколько классов, вы поместите все их в корневую исходную папку. Начните с интерфейса, который должен реализовать слушатель вашего сервиса. Создайте новый интерфейс Kotlin с именем ServiceListener :

interface ServiceListener {fun loggedIn () // 1 забавный fileDownloaded (file: File) // 2 забавных отмененных () // 3 забавных handleError (исключение: исключение) // 4}

Вам может потребоваться выбрать Option + Return в macOS Alt + Enter на ПК, чтобы выполнить импорт для класса File.

Эти методы уведомляют слушателя, когда:

  1. loggedIn (): пользователь успешно аутентифицирован.
  2. fileDownloaded (file: File): файл выбран и успешно загружен.
  3. cancelled (): вход в систему или выбор файла отменяются.
  4. handleError (исключение: исключение): есть любая ошибка.

Этот интерфейс будет реализован MainActivity и используется службой как способ сообщить пользователю службы, когда что-то произошло.

Создание класса данных: GoogleDriveConfig

Затем создайте простой класс данных для хранения информации, которая нужна службе. Создайте новый класс данных с именем GoogleDriveConfig :

класс данных GoogleDriveConfig (val activityTitle: String? = null, val mimeTypes: List <String>? = null)

Этот класс содержит заголовок, который Google Drive назначит в качестве заголовка действия, и mimeTypes, который определяет, какие типы файлов следует отображать.

Создание GoogleDriveService

Далее вы создадите реальный сервис. Создайте новый класс с именем GoogleDriveService :

класс GoogleDriveService (частная операция val: активность, частная конфигурация val: GoogleDriveConfig) {}

Класс не является службой Android, но вместо этого действует как служба для MainActivity. Вы будете добавлять следующий код по порядку.

Сначала добавьте сопутствующий объект:

сопутствующий объект {private val SCOPES = setOf <Scope> (Drive.SCOPE_FILE, Drive.SCOPE_APPFOLDER) val documentMimeTypes = arrayListOf ("application / pdf", "application / msword", "application / vnd.openxmlformats-officedocument.wordprocessingml.document" ) const val REQUEST_CODE_OPEN_ITEM = 100 const val REQUEST_CODE_SIGN_IN = 101 const val TAG = "GoogleDriveService"}

Области действия - это набор разрешений Google Диска. Поэтому, предоставляя область действия файла и папки приложения, вы указываете Google Диску, чтобы вы могли обрабатывать файлы и папки.

Типы mime предназначены для типов файлов, которые вы хотите разрешить пользователю выбирать. Если вы хотите, чтобы пользователь выбирал изображения, вы должны использовать image / *. Здесь вы выбираете файлы .pdf и .doc / .docx .

У вас также есть два кода запроса для обработки результатов входа в систему и выбора файла. Константа TAG используется для регистрации.

После раздела сопутствующего объекта добавьте следующие переменные:

var serviceListener: ServiceListener? = null // 1 приватная переменная driveClient: DriveClient? = null // 2 private var driveResourceClient: DriveResourceClient? = null // 3 закрытая переменная signInAccount: GoogleSignInAccount? = ноль // 4

Это:

  1. serviceListener - слушатель вашего сервиса.
  2. driveClient обрабатывает функции диска высокого уровня, такие как «Создать файл», «Открыть файл» и «Синхронизация».
  3. driveResourceClient обрабатывает доступ к ресурсам и / или файлам диска.
  4. signInAccount отслеживает текущую учетную запись.

Теперь добавьте свойство GoogleSignInClient , которое инициализируется лениво:

private val googleSignInClient: GoogleSignInClient от lazy {val builder = GoogleSignInOptions.Builder (GoogleSignInOptions.DEFAULT_SIGN_IN) для (области видимости в SCOPES) {builder.requestScopes (scope)} val signInOptions = builder.build () GoogleSignInOgnisionInliGlient.lig.info.get

googleSignInClient создается при необходимости и включает области, определенные ранее. Последний оператор возвращает GoogleSignInClient.

Обработка результатов деятельности

Вы должны иметь возможность обрабатывать результаты от пользователя, который входит в систему и выбирает файл в MainActivity . Создайте метод с именем onActivityResult, который будет вызываться внутри onActivityResult из MainActivity :

fun onActivityResult (requestCode: Int, resultCode: Int, data: Intent?) {when (requestCode) {REQUEST_CODE_SIGN_IN -> {if (data! = null) {handleSignIn (data)} else {serviceListener? .cancelled ()}} REQUEST_CODE_OPEN_ITEM -> {if (data! = null) {openItem (data)} else {serviceListener? .cancelled ()}}}}

В методе вы вызываете вспомогательные методы или serviceListener в зависимости от requestCode. Вы можете проверить результат на наличие данных вместо resultCode. Если данные не возвращаются, это означает, что пользователь отменил действие.

Теперь добавьте вспомогательный метод для обработки входа с другим методом для инициализации клиента диска:

личное веселье handleSignIn (data: Intent) {val getAccountTask = GoogleSignIn.getSignedInAccountFromIntent (data) if (getAccountTask.isSuccessful) {initializeDriveClient (getAccountTask.result)} else {serviceListener? .handleErk, get-in-error (Exception) failed .exception))}} частное развлечение initializeDriveClient (signInAccount: GoogleSignInAccount) {driveClient = Drive.getDriveClient (activity.applicationContext, signInAccount) driveResourceClient = Drive.getDriveResourceClient (Activity.applicationContext, serviceInisten)?).

Как только пользователь вошел в систему, вы обрабатываете результат в initializeDriveClient (). Это создаст ваши диски клиентов. Он также уведомляет слушателя, что пользователь успешно вошел в систему.

После того, как пользователь выбрал файл, вы получите намерение действия и передадите его в openItem (), поэтому добавьте этот вспомогательный метод сейчас:

личное развлечение openItem (data: Intent) {val driveId = data.getParcelableExtra <DriveId> (OpenFileActivityOptions.EXTRA_RESPONSE_DRIVE_ID) downloadFile (driveId)}

Эта функция получает идентификатор диска из опций намерений и передает этот идентификатор другому вспомогательному методу downloadFile ().

Ключевым аспектом всего сервиса является загрузка выбранного файла. Для этого вам необходимо получить входной поток в файл и сохранить его в локальном файле. Вы будете использовать библиотеку Square Okio, чтобы легко взять этот поток и сохранить его в файл.

Добавьте метод downloadFile () сейчас:

личное удовольствие downloadFile (data: DriveId?) {if (data == null) {Log.e (TAG, "downloadFile data is null") return} val drive = data.asDriveFile () var fileName = "test" driveResourceClient ?. getMetadata (диск) ?. addOnSuccessListener {fileName = it.originalFilename} val openFileTask = driveResourceClient? .openFile (диск, DriveFile.MODE_READ_ONLY) openFileTask? .continueWithTask {task -> search. // Это каталог загрузки приложения, а не телефоны. Val storageDir = activity.getExternalFilesDir (Environment.DIRECTORY_DOWNLOADS) val tempFile = File (storageDir, fileName) tempFile.createNewFile () val sink = Okio.buffer (Okio.sink (tempFile) ) sink.writeAll (Okio.source (it)) sink.close () serviceListener? .fileDownloaded (tempFile)} catch (e: IOException) {Log.e (TAG, «Проблемы с сохранением файла», e) serviceListener? .handleError (e)}} driveResourceClient? .discardContents (content)} ?. addOnFailureListener {e -> // Обработка сбоя Log.e (TAG, "Невозможно прочитать content ", e) serviceListener? .handleError (e)}}

В этом методе много чего происходит. Обратите внимание на вызов getMetaData (). Это необходимо для получения имени выбранного файла. Затем вы сохраняете файл во внутренней папке загрузки вашего приложения (которая не видна пользователю), затем предупреждаете слушателя о загруженном файле и о том, где его найти.

Открытие диалога с выбранным файлом

Вы создали методы для обработки результатов входа и выбора файла, но у вас еще нет метода для инициирования этих действий. Создайте метод с именем pickFiles (), чтобы открыть диалоговое окно pick-file:

/ ** * Предлагает пользователю выбрать текстовый файл, используя OpenFileActivity. * * @return Задача, которая решается с помощью идентификатора выбранного элемента. * / fun pickFiles (driveId: DriveId?) {val builder = OpenFileActivityOptions.Builder () if (config.mimeTypes! = null) {builder.setMimeType (config.mimeTypes)}} {builder.setMimeType (documentMimeTypes)}} если (config .activityTitle! = null && config.activityTitle.isNotEmpty ()) {builder.setActivityTitle (config.activityTitle)} if (driveId! = null) {builder.setActivityStartFolder (driveId)} val openOptions = builder.build () pickItem (openOptions )}

Вы устанавливаете тип MIME и заголовок, а затем задаете начальную папку, если указан идентификатор диска. Затем вызовите pickItem с этими опциями.

Затем добавьте метод pickItem:

частное развлечение , ноль) } } }

Это запустит операцию выбора файлов на Google Диске, которая вызовет ваш onActivityResult с ответом пользователя.

Вход и выход

Затем вы добавляете метод, который может извлечь любую учетную запись, которая была авторизована с предыдущих запусков:

fun checkLoginStatus () {val requiredScopes = HashSet <Scope> (2) requiredScopes.add (Drive.SCOPE_FILE) requiredScopes.add (Drive.SCOPE_APPFOLDER) signInAccount = GoogleSignIn.getLastSignedInAccount (активность) val containsSccope? sign. requiredScopes) val account = signInAccount if (account! = null && содержитScope == true) {initializeDriveClient (account)}}

Если зарегистрированный аккаунт найден и область действия не изменилась, вы вызываете initializeDriveClient (), который вы создали ранее для обработки входа. Добавьте следующий метод, чтобы открыть диалоговое окно аутентификации:

fun auth () {activity.startActivityForResult (googleSignInClient.signInIntent, REQUEST_CODE_SIGN_IN)}

Наконец, добавьте метод, позволяющий пользователю выйти из системы.

веселый выход из системы () {googleSignInClient.signOut () signInAccount = null}

Обновление MainActivity

Теперь вы снова переключитесь на MainActivity .
Над функцией onCreate () создайте простое перечисление для отслеживания состояния кнопок:

enum class ButtonState {LOGGED_OUT, LOGGED_IN}

Как упоминалось ранее, действие должно быть установлено как serviceListener, чтобы оно могло отвечать на сервис. Реализуйте интерфейс ServiceListener в MainActivity :

Класс MainActivity: AppCompatActivity (), ServiceListener {

И добавьте методы интерфейса:

переопределить забаву loggedIn () {} переопределить забаву fileDownloaded (file: File) {} переопределить забаву отменен () {} переопределить забаву handleError (исключение: исключение) {}

Добавьте свойства для сервиса и состояние кнопки:

частный латинит var googleDriveService: GoogleDriveService приватный статус var = ButtonState.LOGGED_OUT

Вам необходимо изменить состояние кнопок в зависимости от вашего состояния входа или выхода. Следовательно, вы создаете функцию с именем setButtons:

приватное развлечение setButtons () {when (state) {ButtonState.LOGGED_OUT -> {status.text = getString (R.string.status_logged_out) start.isEnabled = false logout.isEnabled = false login.isEnabled = true} else -> {status .text = getString (R.string.status_logged_in) start.isEnabled = true logout.isEnabled = true login.isEnabled = false}}}

status, start, logout и login являются идентификаторами представлений, созданных вами в activity_main.xml . Вы должны иметь возможность импортировать их, используя Option + Return на macOS. Alt + Enter на ПК, если у вас есть подключаемый модуль: «kotlin-android-extensions» в модуле приложения build.gradle , который новые проекты делают по умолчанию.

Обновление onCreate () должно быть:

переопределить веселье onCreate (saveInstanceState: Bundle?) {super. , config) // 2 googleDriveService.serviceListener = this // 3 googleDriveService.checkLoginStatus () // 4 login.setOnClickListener {googleDriveService.auth ()} start.setOnClickListener {googleDriveService.pickFrixtServiceService.serviceService.service null) (null) () state = ButtonState.LOGGED_OUT setButtons ()} // 5 setButtons ()}

Вот что делает вышеперечисленное:

  1. Создает сервис с вашим названием и типами пантомимы документа.
  2. Устанавливает MainActivity в качестве слушателя.
  3. Изменяет состояние на зарегистрированный, если есть какая-либо зарегистрированная учетная запись.
  4. Устанавливает слушателей нажатия кнопки. Есть три кнопки: Войти, Выбрать файл и Выйти.
  5. Обновляет представления в зависимости от текущего состояния.

Обработка метода OnActivityResult

Добавьте метод onActivityResult () и передайте результат службе:

переопределить fun onActivityResult (requestCode: Int, resultCode: Int, data: Intent?) {googleDriveService.onActivityResult (requestCode, resultCode, data)}

Теперь добавьте реализации для методов слушателя:

переопределить fun loggedIn () {state = ButtonState.LOGGED_IN setButtons ()} переопределить fun fileDownloaded (file: File) {val intent = Intent (Intent.ACTION_VIEW) val apkURI = FileProvider.getUriForFile (this, applicationContext.packageName + ".provider" , файл) val uri = Uri.fromFile (файл) расширение val = MimeTypeMap.getFileExtensionFromUrl (uri.toString ()) val mimeType = MimeTypeMap.getSingleton (). getMimeTypeFromExtension (расширение) intent.setDataAndType = intent.ypeT =) FLAG_GRANT_READ_URI_PERMISSION if (intent.resolveActivity (packageManager)! = Null) {startActivity (intent)} else {Snackbar.make (main_layout, R.string.not_open_file, Snackbar.LENGTH_LONG) .shock ()}} .make (main_layout, R.string.status_user_cancelled, Snackbar.LENGTH_LONG) .show ()} переопределить весело handleError (исключение: исключение) {val errorMessage = getString (R.string.status_error, exception.message) Snackbar.make (main_layout, main errorMessage, Snackbar.LENGTH_LONG) .show ()}

Код внутри loggedIn (), cancelled () и handleError () довольно прост. Они обновляют интерфейс и / или отображают сообщения с помощью Snackbar.

В fileDownloaded () файл получен; впоследствии вы хотите, чтобы система открыла файл. Именно здесь поступает информация FileProvider, которую вы помещаете в файл AndroidManifest.xml .

В Android 8.0 Oreo и выше вы больше не можете открывать файл: // url, поэтому для этого вам нужно предоставить свой собственный FileProvider . Вам не нужен какой-либо другой код, кроме этого. MimeTypeMap - это системный класс, который имеет несколько вспомогательных методов, которые можно использовать для получения расширения файла и типа mime из URL-адреса. Вы создаете намерение и убедитесь, что система может обработать его, прежде чем начать действие - в противном случае приложение завершится сбоем.

Время попробовать! Создайте и запустите приложение.

Сначала попробуйте войти в систему:

Сначала вам будет представлен выбор аккаунта. После того, как вы выбрали учетную запись, вам нужно дать приложению разрешения на доступ к вашему Google Диску.

Затем нажмите кнопку «Запустить Google Диск», и вы увидите ваши файлы примерно так:

Затем нажмите кнопку «Запустить Google Диск», и вы увидите ваши файлы примерно так:

После выбора файла и нажатия кнопки «Выбор» начнется процесс загрузки. После завершения загрузки вы должны увидеть выбранный файл, автоматически открываемый в программе просмотра системы.

Куда пойти отсюда?

Из этого руководства вы узнали, как интегрировать свое приложение с Google Drive и как загрузить файл. Поздравляем с успешной загрузкой файлов с вашего Google Диска!

Вы можете загрузить окончательный проект, используя кнопку загрузки в верхней или нижней части этого руководства.

Вы можете сделать намного больше с Google Drive. Попробуйте, например, добавить больше возможностей в ваше приложение, например, создать файл или удалить файл. Проверьте документация о других функциях Google Drive SDK для Android.

Если у вас есть какие-либо комментарии или вопросы по поводу этого руководства или Google Drive SDK, присоединяйтесь к обсуждению на форуме ниже!

Похожие

Серверы Ultimate: запуск веб-серверов с вашего устройства Android [Android 2.1+]
Реклама Запуск ваших собственных серверов имеет свои преимущества. Вы можете запускать свои собственные веб-сайты, свои собственные адреса электронной почты, свой файловый хостинг, свои календари и многое другое. Чтобы оставаться максимально гибкими, владея вашими данными, а не присматривать за ними какую-то другую компанию, лучше использовать собственные серверы. Поскольку все больше и больше энергосберегающих устройств работают под управлением Android, необходимо иметь возможность
Google хочет выбросить URL-адреса из Chrome
URL были с нами с самого начала Интернета. С тех пор они почти не изменились. Ничто также не обещает измениться. Однако Google, по-видимому, планирует избавиться от них, хотя бы частично. Последнее обновление браузера Chrome в канарской версии, предназначенное для программистов и любителей новинок, представило интересную функцию в программе. Что ж, в адресной строке браузера вы не можете видеть весь URL, только имя
10 лучших криптовалютных приложений для Android! (Обновлено 2019)
Криптовалюта покорила мир штурмом. Во всем мире есть люди, добывающие биткойны, монеты Дожей, Этериум и различные другие виды валюты. Они начинают приносить реальную ценность в реальном мире, а в некоторых местах даже принимают криптовалюту в качестве оплаты за товары и услуги. В этом обзоре мы рассмотрим лучшие криптовалютные приложения
Android: это 5 лучших антивирусных приложений для вашего смартфона
... Android теперь обязательно. Поэтому пользователи не должны стесняться устанавливать правильное приложение на свой смартфон. Чтобы оценить эффективность защиты, независимый институт AV-Test тестирует различные антивирусные решения. Это 5 лучших антивирусных сканеров для вашего смартфона на Android. Хороший сканер вирусов для Android защищает вас от интернет-угроз. (Источник: Netzwelt) содержание
Google Maps имеет новую функцию, когда вы встречаете друзей
... обновление Карт Google позволяет пользователям создавать списки опросов, например, с несколькими ресторанами. Затем участники опроса могут проголосовать за желаемый вариант или сделать свое собственное предложение. Если вы хотите создать список с приложением Google Maps, вам нужно создать соответствующий Дольше размещать на карте держать
3 простых способа доступа к загруженным приложениям на Android TV
Реклама По мере того, как Android TV продолжает расти, все больше и больше людей начинают использовать платформу. Существует большое разнообразие телевизионных приставок, работающих под управлением операционной системы. Некоторые, такие как Nvidia Shield, стоят много денег и мечта кусачек 7 причин, по
Недавно Google запустил новую форму ремаркетинга в кампаниях в Польше AdWords на основе адресов электро...
Недавно Google запустил новую форму ремаркетинга в кампаниях в Польше AdWords на основе адресов электронной почты ваших пользователей или клиентов, собранных рекламодателями, и нацеленных на маркетинговые сообщения в сетях Search, YouTube и Gmail. Напомним, что более полутора лет рекламодатели могут использовать эту функцию. в фейсбуке где Таможенная
Ваш отель глазами гостя. Вы ориентированы на гостя?
Ориентированный на гостя подход - «войти в туфлю гостя», смотреть глазами, думать головой, чувствовать пальцы. Не только во время пребывания в отеле, потому что путешествие начинается с самой идеи, с поиска вдохновения для путешествия и выбора предложения. С чего начать? Как и в классическом маркетинге, сначала необходимо определить наиболее важные группы наших гостей. Для кого наш отель? Они приходят издалека или рядом? Сами, с семьей, с группой друзей, с коллегами? Вам нужен мир
Сайт недоступен
Global Hostinger Платформа веб-хостинга мирового класса. Наше видение заключается в том, чтобы позволить миллионам людей во всем мире раскрыть возможности Интернета и дать им возможность учиться, творить и расти. Выберите свой план веб-хостинга Единый веб-хостинг 1 веб-сайт 1 учетная запись электронной почты Пропускная способность 100 ГБ 1X вычислительная мощность и память
Сайт недоступен
Hostinger по всему миру Платформа веб-хостинга мирового класса. Наше видение заключается в том, чтобы позволить миллионам людей во всем мире раскрыть возможности Интернета и дать им возможность учиться, творить и расти. Выберите свой план веб-хостинга 1 веб-сайт 1 учетная запись электронной почты Пропускная способность 100 ГБ 1X вычислительная мощность и память Неограниченное
Сайт недоступен
Hostinger по всему миру Платформа веб-хостинга мирового класса. Наше видение заключается в том, чтобы позволить миллионам людей во всем мире раскрыть возможности Интернета и дать им возможность учиться, творить и расти. Выберите свой план веб-хостинга 1 веб-сайт 1 учетная запись электронной почты Пропускная способность 100 ГБ 1X вычислительная мощность и память Неограниченное

Комментарии

Зачем вам загружать приложения на Android TV?
Зачем вам загружать приложения на Android TV? Несмотря на все плюсы Android TV, операционная система все еще имеет один существенный недостаток: некоторые приложения не совместимы с Android TV. Вы не найдете их в магазине Google Play на вашем устройстве. Есть обходной путь! Вместо этого вы можете использовать веб-версию магазина для загрузки и установки приложений. Но даже тогда некоторые приложения недоступны. Решение? Загрузите контент, который вы хотите.
Но что, если ПК работает на заводском оборудовании или лежит в основе приложений для регистрации данных, обеспечения безопасности или медицинских приложений?
Но что, если ПК работает на заводском оборудовании или лежит в основе приложений для регистрации данных, обеспечения безопасности или медицинских приложений? Данные могут быть потеряны, чувствительное оборудование может быть повреждено, а время потеряно. Источником бесперебойного питания (ИБП) является решение, но что, если из-за пространственных факторов или факторов окружающей среды (пыль и т. Д.) Традиционные внешние ИБП нецелесообразны? ИБП
Нет класса для окон меньшего размера?
Нет класса для окон меньшего размера? Ты помнишь, что мы говорили в первой части этой серии? Bootstrap - это первая мобильная платформа, и это означает, что ее классы сетки работают от начальной точки останова и выше. «Ну, но никаких классов вообще !?» Ага. Нет классов для более узких размеров, так как наша компоновка начинается со 100% ширины, и так все равно ведут себя блочные элементы. Тем не менее, в строке 14 у нас есть класс, определяющий диапазон
Где вы берете эти файлы и куда их помещать, чтобы приложение правильно запускалось?
Где вы берете эти файлы и куда их помещать, чтобы приложение правильно запускалось? Эти файлы связаны с распространяемым пакетом Visual C ++, который после установки должен автоматически размещать необходимые библиотеки в нужных местах. Оба файла очень часто необходимы для запуска отдельных приложений на компьютере или в играх.
На этот вопрос нет простого ответа, потому что он связан с определением - является ли основной профиль деятельности или услуг флориста?
На этот вопрос нет простого ответа, потому что он связан с определением - является ли основной профиль деятельности или услуг флориста? Ну, я ответил на вопрос вопросом ... но один за другим. Рождественские дни В 2016 году торговый запрет на 13 дней, включая 4 дня в мае: 1 января - Новый год, 6 января - Богоявление, 27 и 28 марта - Пасха, 1 мая День труда, 3 мая - Национальный день третьего мая, 15 мая
Google Pay?
Google Pay? Present! Android 9 пирог? Кроме того. Надо признать, что это очень приятно. Небольшая эволюция фото Самым большим слабым местом OnePlus 6, когда он был выпущен, была, несомненно, фотография. Это не было ужасно, но мы чувствовали себя хорошо здесь разница в цене с Galaxy S9 или P20 Pro, например. Большая часть качества фотографий на мобильных устройствах, в конце концов, является алгоритмом обработки и может быть улучшена путем обновления программного обеспечения.
Google просто перестает подвергать их чрезмерной критике, потому что, в основном, что дает нам тот факт, что в адресной строке мы видим весь URL?
Google просто перестает подвергать их чрезмерной критике, потому что, в основном, что дает нам тот факт, что в адресной строке мы видим весь URL? Практически ничего. Однако я надеюсь, что функция показа полного адреса после наведения на ссылку не исчезнет. Уже после самого URL можно многое сделать о странице, на которую мы должны попасть, и иногда, основываясь на самом адресе, мы решаем, нажимать или нет ссылку. Chrome Canary - это своего рода бета-версия, в которой Google
Если Epic основан на Chrome, отправляет ли он данные в Google?
Если Epic основан на Chrome, отправляет ли он данные в Google? Hidden Reflex, создатель браузера, говорит нет. «Epic по умолчанию удаляет все сервисы Google из Chromium, чтобы ваш просмотр не проходил через серверы Google», - говорится в часто задаваемых вопросах браузера. С практической точки зрения это означает, что сервисы, которые опираются на серверы Google, включая автоматическое предложение в адресной строке и языковой перевод, либо обрабатываются Epic локально,

Encoding = "utf-8"?
Encoding = "utf-8"?
Val activityTitle: String?
Null, val mimeTypes: List <String>?
Null // 1 приватная переменная driveClient: DriveClient?
Null // 2 private var driveResourceClient: DriveResourceClient?
Null // 3 закрытая переменная signInAccount: GoogleSignInAccount?
Cancelled ()}} REQUEST_CODE_OPEN_ITEM -> {if (data! = null) {openItem (data)} else {serviceListener?
GetSignedInAccountFromIntent (data) if (getAccountTask.isSuccessful) {initializeDriveClient (getAccountTask.result)} else {serviceListener?
GetDriveResourceClient (Activity.applicationContext, serviceInisten)?