Đâ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é!
Nội dung chính của bài viết
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
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:
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!
Bình luận. Cùng nhau thảo luận nhé!