Hướng dẫn tích hợp Google Drive vào ứng dụng từ A-Z – Phần 3

0
Dịch vụ dạy kèm gia sư lập trình
Bài này thuộc phần 3 của 3 phần trong series Hướng dẫn tích hợp Google Drive vào Android app

Đây là phần cuối cùng trong series hướng dẫn tích hợp Google Drive SDK vào ứng dụng Android. Ở 2 phần trước, mình đã hướng dẫn các bạn đăng kí với Google Drive và bắt đầu cấu hình trên ứng dụng.

Ở phần 2, chúng ta đã code được một phần cho tính năng download tệp từ tài khoản Google Drive của người dùng.  Phần 3 này, chúng ta sẽ tiếp tục hoàn thành nốt tính năng:

  • Lựa chọn tệp trong Google Drive để người dùng tải về.
  • Xử lý khi người dùng đăng nhập và đăng xuất.

Chúng ta tiếp tục nhé!

Hướng dẫn tích hợp Google Drive vào ứng dụng Android

Có khá nhiều bước trong phần này, khi theo dõi có phần nào thắc mắc hoặc có góp ý thì hãy bên dưới nhé. Dưới đây là hướng dẫn tích hợp google drive SDK.

#1. Tạo hội thoại để chọn tệp tải về (Picker Dialog)

Để làm được điều này, chúng ta sử dụng OpenFileActivityOptions API có sẵn của Google Drive SDK.

/**
 * Prompts the user to select a text file using OpenFileActivity.
 *
 * @return Task that resolves with the selected item's ID.
 */
fun pickFiles(driveId: DriveId?) {
  val builder = OpenFileActivityOptions.Builder()
  if (config.mimeTypes != null) {
    builder.setMimeType(config.mimeTypes)
  } else {
    builder.setMimeType(documentMimeTypes)
  }
  if (config.activityTitle != null && config.activityTitle.isNotEmpty()) {
    builder.setActivityTitle(config.activityTitle)
  }
  if (driveId != null) {
    builder.setActivityStartFolder(driveId)
  }
  val openOptions = builder.build()
  pickItem(openOptions)
}

Phần cấu hình cho Picker Dialog này, chúng ta cần truyền 3 tham số:

  • mimeType
  • Tiêu đề của Dialog
  • Thư mục mặc định.

Tiếp đến, đến phần lựa chọn tệp, chính là hàm pickItem(), chúng ta làm như sau:

private fun pickItem(openOptions: OpenFileActivityOptions) {
  val openTask = driveClient?.newOpenFileActivityIntentSender(openOptions)
  openTask?.let {
    openTask.continueWith { task ->
      ActivityCompat.startIntentSenderForResult(activity, task.result, REQUEST_CODE_OPEN_ITEM,
          null, 0, 0, 0, null)
    }
  }
}

Phần chọn tệp thì phía ứng dụng không làm mà sẽ đẩy việc đó cho Google Drive SDK thông qua hàm: startIntentSenderForResult(). Sau khi chọn xong thì trả lại kết quả tại hàm onActivityResult()

🥳 Bạn đã đọc phần 1 của tích hợp Google drive SDK chưa?

#2. Xử lý khi người dùng đăng nhập/đăng xuất khỏi tài khoản Google Drive

Bạn cần viết một hàm để kiểm tra xem người dùng đã đăng nhập vào Google Drive rồi hay chưa. Mỗi lần khởi động ứng dụng đều phải gọi hàm này để kiểm tra

fun checkLoginStatus() {
  val requiredScopes = HashSet<Scope>(2)
  requiredScopes.add(Drive.SCOPE_FILE)
  requiredScopes.add(Drive.SCOPE_APPFOLDER)
  signInAccount = GoogleSignIn.getLastSignedInAccount(activity)
  val containsScope = signInAccount?.grantedScopes?.containsAll(requiredScopes)
  val account = signInAccount
  if (account != null && containsScope == true) {
    initializeDriveClient(account)
  }
}

Nếu người dùng đã đăng nhập trước đó, bạn gọi hàm initializeDriveClient() để người dùng có thể sử dụng được luôn mà không cần đăng nhập lại.

Trường hợp nếu người dùng chưa đăng nhập hoặc đã đăng xuất trước đó thì cần phải yêu cầu người dùng đăng nhập lại.

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

Cuối cùng là hàm để người dùng có thể đăng xuất

fun logout() {
  googleSignInClient.signOut()
  signInAccount = null
}

🥳 Đừng bỏ lỡ: Tự học lập trình Android

#3. Cập nhật trạng thái đăng nhập trên giao diện ứng dụng

Các bạn mở lại MainActivity nhé

Phía trên hàm onCreate(), chúng ta tạo một enum đơn giản để theo dõi trạng thái của Button:

enum class ButtonState {
  LOGGED_OUT,
  LOGGED_IN
}

Như ở phần 2, chúng ta đã tạo sẵn Interface có tên là serviceListener và tại MainActivity chúng ta sẽ implement nó.

Để implement serviceListener trong MainActivity, ta làm như sau:

class MainActivity : AppCompatActivity(), ServiceListener {

Và bắt buộc phải override các hàm bên dưới

override fun loggedIn() {
}

override fun fileDownloaded(file: File) {
}

override fun cancelled() {
}

override fun handleError(exception: Exception) {
}

Khởi tạo thêm thuộc tính cho GoogleDriveService và trạng thái của Button:

private lateinit var googleDriveService: GoogleDriveService
private var state = ButtonState.LOGGED_OUT

Như mình nói, chúng ta cần thay đổi trạng thái của các button dựa trên trạng thái đăng nhập hoặc đăng xuất.

private fun 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,  và login là ID của các views bạn đã tạo trong activity_main.xml.

Sau đó update lại hàm onCreate():

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  setContentView(R.layout.activity_main)

  //1
  val config = GoogleDriveConfig(
      getString(R.string.source_google_drive),
      GoogleDriveService.documentMimeTypes
  )
  googleDriveService = GoogleDriveService(this, config)

  //2
  googleDriveService.serviceListener = this

  //3
  googleDriveService.checkLoginStatus()

  //4
  login.setOnClickListener {
    googleDriveService.auth()
  }
  start.setOnClickListener {
    googleDriveService.pickFiles(null)
  }
  logout.setOnClickListener {
    googleDriveService.logout()
    state = ButtonState.LOGGED_OUT
    setButtons()
  }

  //5
  setButtons()
}

#4.  Xử lý tệp nhận từ Google Drive

Thêm hàm onActivityResult()và kết quả như sau:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
 googleDriveService.onActivityResult(requestCode, resultCode, data)
}

Sau đó thì hoàn thành xử lý logic cho các hàm mà chúng ta override từ serviceListener

override fun loggedIn() {
  state = ButtonState.LOGGED_IN
  setButtons()
}

override fun fileDownloaded(file: File) {
  val intent = Intent(Intent.ACTION_VIEW)
  val apkURI = FileProvider.getUriForFile(
      this,
      applicationContext.packageName + ".provider",
      file)
  val uri = Uri.fromFile(file)
  val extension = MimeTypeMap.getFileExtensionFromUrl(uri.toString())
  val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
  intent.setDataAndType(apkURI, mimeType)
  intent.flags = 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).show()
  }
}

override fun cancelled() {
  Snackbar.make(main_layout, R.string.status_user_cancelled, Snackbar.LENGTH_LONG).show()
  }

override fun handleError(exception: Exception) {
  val errorMessage = getString(R.string.status_error, exception.message)
  Snackbar.make(main_layout, errorMessage, Snackbar.LENGTH_LONG).show()
}

Logic bên trong các hàm loggedIn(), cancelled(), và handleError() đơn giản là chúng ta cập nhập giao diện khi sự kiện đó xảy ra thôi.

Trong fileDownloaded() – bạn nhận được một tệp từ Google drive để hệ thống có thể mở tệp đó ra.

Ở đây, có một chỗ mình lưu ý với các bạn đó là: FileProvider.getUriForFile(). Từ Android 8.0 Oreo trở lên, bạn không thể sử dụng file://. Thay vào đó phải sử dụng content://, vì vậy bạn cần cung cấp FileProvider của riêng bạn để mở chúng.

OK, về cơ bản là đã xong rồi đấy. Chạy thử ứng dụng thôi.

Đầu tiên là yêu cầu đăng nhập

Tích hợp Google Drive SDK vào ứng dụng Android

Trình chọn tài khoản hiện ra. Sau khi đã chọn một tài khoản, bạn sẽ cần cấp quyền truy cập Google Drive của mình.

Tiếp theo, nhấn nút “Bắt đầu Google Drive” và bạn sẽ thấy các tệp của mình như sau:

Tích hợp Google Drive vào ứng dụng

Khi bạn chọn một tệp và nhấn Select, quá trình tải xuống sẽ bắt đầu. Khi tải xong, bạn sẽ thấy tệp đó xuất hiện trong trình quản lý file của hệ thống.

Quá tuyệt phải không?

Tổng kết

Sau rất nhiều cố gắng, cuối cùng mình đã hoàn thành bài hướng dẫn tích hợp Google Drive vào ứng dụng Android. Để các bạn có thể hiểu bản chất và biết cách thực hiện nên mình đã cố gắng viết chi tiết hết mức. Hi vọng các bạn sẽ thích cách viết này.

Toàn bộ source code của bài hướng dẫn này, các bạn download tại đây nhé.

Nếu bạn có bất kì ý tưởng hay thắc mắc thì đừng ngần ngại để lại comment bên dưới nhé. Mình luôn luôn chào đón!

Xem tiếp các bài trong Series
Phần trước: Tích hợp Google Drive SDK vào ứng dụng Android từ A-Z – Phần 2
Dịch vụ phát triển ứng dụng mobile giá rẻ - chất lượng
Bài trướcTích hợp Google Drive SDK vào ứng dụng Android từ A-Z – Phần 2
Bài tiếp theoTất tần tật về Broadcast Receiver trong Android
Dám và thử thách là những trận chiến. Nếu bạn thua một lần, hai lần hoặc nhiều lần nữa, bạn hãy giao chiến lại rồi sẽ được lúc bạn toàn thắng.

Bình luận. Cùng nhau thảo luận nhé!

avatar
  Theo dõi bình luận  
Thông báo