{"id":20308727,"url":"https://github.com/mesadhan/google-drive-app","last_synced_at":"2025-04-11T15:40:25.788Z","repository":{"id":98750054,"uuid":"229913768","full_name":"mesadhan/google-drive-app","owner":"mesadhan","description":"Google Drive API with Android","archived":false,"fork":false,"pushed_at":"2020-10-02T12:58:31.000Z","size":172,"stargazers_count":88,"open_issues_count":10,"forks_count":41,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-03-25T11:49:20.439Z","etag":null,"topics":["android","googledrive","java"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mesadhan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-12-24T09:35:23.000Z","updated_at":"2025-02-10T03:31:15.000Z","dependencies_parsed_at":"2023-05-25T03:30:42.656Z","dependency_job_id":null,"html_url":"https://github.com/mesadhan/google-drive-app","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mesadhan%2Fgoogle-drive-app","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mesadhan%2Fgoogle-drive-app/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mesadhan%2Fgoogle-drive-app/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mesadhan%2Fgoogle-drive-app/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mesadhan","download_url":"https://codeload.github.com/mesadhan/google-drive-app/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248432866,"owners_count":21102457,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","googledrive","java"],"created_at":"2024-11-14T17:23:44.992Z","updated_at":"2025-04-11T15:40:25.779Z","avatar_url":"https://github.com/mesadhan.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Google Drive API with Android\n\nThere are many ways to upload images and files. Also, there are many places from which to uploads files: Dropbox, local storage on the device, Google Drive and other services. In this tutorial, we are going to take a look at how to upload and create a file in Google Drive. To do so we need to Google Drive SDK and Google Authentication Base on Google Drive Rest API we are going to do that.\n\nOkay, it's enough to talk about it 😎 Let's get into it,\n\n\n# Getting Started\n\nStart a new `Android Studio project` from the startup screen or `New Project` then select `Empty Activity' from the `Choose Project` box.\n\nEnter the name `drive-rest-sample` company domain and a project location. Make sure to Choose Language Java.\n\n![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/p199fkcab2nxcqjvjkak.png)\n\nAnd Click `Finish` .\n\n\n# Registering for Google Drive\n\nAs we discuss we need to Google Drive SDK, So in order to use it, we need to enable that API. Okay don't worry we will move forward step by step\n\n- Go to [Google Console](https://console.developers.google.com/projectselector/apis/dashboard).\n- Sign up for a developer account if We don't have or then sign in.\n- `Create` a project Or `Select` and click continue from below,\n\n![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/9tkmgg6z7s5fup0vxfxs.png)\n\n- After creating a project we have `Dashboard` like below,\n\n![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/yd30f54tv84u4zbbqwup.png)\n\n\n- Now, Select `Library` on the left-hand side to go to the Search screen\n- Type “Google Drive” and select Google Drive API.\n- Select Enable. Then It looks like below,\n\n![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/3jyyhw1qc16zdii50mye.png)\n\n- Back to Dashboard, from Dashboard left-hand side go to Credentials. Create `Credential` by selecting the `OAuth client ID` like below\n\n![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/985j2fol9qo84nd04gln.png)\n\nTt navigates to the `Create OAuth client ID` page. Select our Application Type `Android`.\n\n![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/uc5b0l55srkulmptlo6x.png)\n\n- Now we need your `SHA-1` `Signing-certificate fingerprint` key. Do so follow below steps\n- Copy the keytool text (press the Copy icon) and paste it into a terminal.\n- Change the path-to-debug-or-production-keystore to your default debug keystore location:\n- On Mac or Linux, `~/.android/debug.keystore` .\n- On Windows, `%USERPROFILE%/.android/debug.keystore` .\n- After you execute the command, you will be prompted to enter the keystore password. The password for the debug keystore is blank by default, so you can just press Return or Enter.\n\n\n\u003e Notes: If throwing error to generate singing key then it might be `keystore` not found. \n\nI used an alternative command for my machine `MAC OS`.\n\n```bash\nkeytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android\n```\n\n\nIf everything works correctly, you should see something like this:\n- Copy the `SHA1` value from the terminal into the text field and press Create. The Client ID dialog will appear. Press OK.\n\n![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/yeb93rnpvwwfspb7u6wc.png)\n\n- Finally, enter a name and the `package name` that we used to `create our app`. Although the hint refers to the package name in `AndroidManifest.xml`, it has to match the `applicationId` in `build.gradle` instead — otherwise, the login flow will fail.\n- We don't need to complete the form that appears, it's optional so press `Save` and move on.\n\n\u003e Optional, Now, In the Credentials page. Authorization on Android uses the `SHA1` fingerprint and `package name` to `identify your app`, so you `don’t have to download` any `JSON file or copy any API key` or secret to our project.\n\nIt about lots man, Don't worry! Now, are in the fun part 😎.\n\n# Let's Back to - Android Studio \n\n1.Add those permission in 'AndroidManifest.xml' file\n\n```xml\n    \u003c!-- Permissions required by GoogleAuthUtil --\u003e\n    \u003cuses-permission android:name=\"android.permission.GET_ACCOUNTS\" /\u003e\n    \u003cuses-permission android:name=\"android.permission.MANAGE_ACCOUNTS\" /\u003e\n    \u003cuses-permission android:name=\"android.permission.INTERNET\" /\u003e\n```\n\n2.update `build.gradle` file \n\n```yaml\napply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 29\n    buildToolsVersion \"29.0.2\"\n    defaultConfig {\n        applicationId \"io.github.mesadhan.drive_rest_sample\"\n        minSdkVersion 15\n        targetSdkVersion 29\n        versionCode 1\n        versionName \"1.0\"\n        testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n        }\n    }\n    packagingOptions {\n        exclude 'META-INF/DEPENDENCIES'\n        exclude 'META-INF/LICENSE'\n        exclude 'META-INF/LICENSE.txt'\n        exclude 'META-INF/license.txt'\n        exclude 'META-INF/NOTICE'\n        exclude 'META-INF/NOTICE.txt'\n        exclude 'META-INF/notice.txt'\n        exclude 'META-INF/ASL2.0'\n    }\n    compileOptions {\n        sourceCompatibility = 1.8\n        targetCompatibility = 1.8\n    }\n}\n\ndependencies {\n    implementation fileTree(dir: 'libs', include: ['*.jar'])\n    implementation 'androidx.appcompat:appcompat:1.1.0'\n    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'\n    testImplementation 'junit:junit:4.12'\n    androidTestImplementation 'androidx.test.ext:junit:1.1.1'\n    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'\n\n    // g drive libs\n    implementation 'com.google.android.gms:play-services-auth:17.0.0'\n    implementation 'com.google.http-client:google-http-client-gson:1.26.0'\n    implementation('com.google.api-client:google-api-client-android:1.26.0') {\n        exclude group: 'org.apache.httpcomponents'\n    }\n    implementation('com.google.apis:google-api-services-drive:v3-rev136-1.25.0') {\n        exclude group: 'org.apache.httpcomponents'\n    }\n}\n```\n\n3.create 'DriveServiceHelper.java' helper class\n\n```java\n\npackage io.github.mesadhan.gdrive_app;\n\n\nimport android.content.ContentResolver;\nimport android.content.Intent;\nimport android.database.Cursor;\nimport android.net.Uri;\nimport android.provider.OpenableColumns;\nimport android.util.Pair;\n\nimport com.google.android.gms.tasks.Task;\nimport com.google.android.gms.tasks.Tasks;\nimport com.google.api.client.http.ByteArrayContent;\nimport com.google.api.services.drive.Drive;\nimport com.google.api.services.drive.model.File;\nimport com.google.api.services.drive.model.FileList;\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.util.Collections;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.Executors;\n\n/**\n * A utility for performing read/write operations on Drive files via the REST API and opening a\n * file picker UI via Storage Access Framework.\n */\npublic class DriveServiceHelper {\n    private final Executor mExecutor = Executors.newSingleThreadExecutor();\n    private final Drive mDriveService;\n\n    public DriveServiceHelper(Drive driveService) {\n        mDriveService = driveService;\n    }\n\n    /**\n     * Creates a text file in the user's My Drive folder and returns its file ID.\n     */\n    public Task\u003cString\u003e createFile() {\n        return Tasks.call(mExecutor, () -\u003e {\n            File metadata = new File()\n                    .setParents(Collections.singletonList(\"root\"))\n                    .setMimeType(\"text/plain\")\n                    .setName(\"Untitled file\");\n\n            File googleFile = mDriveService.files().create(metadata).execute();\n            if (googleFile == null) {\n                throw new IOException(\"Null result when requesting file creation.\");\n            }\n\n            return googleFile.getId();\n        });\n    }\n\n    /**\n     * Opens the file identified by {@code fileId} and returns a {@link Pair} of its name and\n     * contents.\n     */\n    public Task\u003cPair\u003cString, String\u003e\u003e readFile(String fileId) {\n        return Tasks.call(mExecutor, () -\u003e {\n            // Retrieve the metadata as a File object.\n            File metadata = mDriveService.files().get(fileId).execute();\n            String name = metadata.getName();\n\n            // Stream the file contents to a String.\n            try (InputStream is = mDriveService.files().get(fileId).executeMediaAsInputStream();\n                 BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {\n                StringBuilder stringBuilder = new StringBuilder();\n                String line;\n\n                while ((line = reader.readLine()) != null) {\n                    stringBuilder.append(line);\n                }\n                String contents = stringBuilder.toString();\n\n                return Pair.create(name, contents);\n            }\n        });\n    }\n\n    /**\n     * Updates the file identified by {@code fileId} with the given {@code name} and {@code\n     * content}.\n     */\n    public Task\u003cVoid\u003e saveFile(String fileId, String name, String content) {\n        return Tasks.call(mExecutor, () -\u003e {\n            // Create a File containing any metadata changes.\n            File metadata = new File().setName(name);\n\n            // Convert content to an AbstractInputStreamContent instance.\n            ByteArrayContent contentStream = ByteArrayContent.fromString(\"text/plain\", content);\n\n            // Update the metadata and contents.\n            mDriveService.files().update(fileId, metadata, contentStream).execute();\n            return null;\n        });\n    }\n\n    /**\n     * Returns a {@link FileList} containing all the visible files in the user's My Drive.\n     *\n     * \u003cp\u003eThe returned list will only contain files visible to this app, i.e. those which were\n     * created by this app. To perform operations on files not created by the app, the project must\n     * request Drive Full Scope in the \u003ca href=\"https://play.google.com/apps/publish\"\u003eGoogle\n     * Developer's Console\u003c/a\u003e and be submitted to Google for verification.\u003c/p\u003e\n     */\n    public Task\u003cFileList\u003e queryFiles() {\n        return Tasks.call(mExecutor, new Callable\u003cFileList\u003e() {\n            @Override\n            public FileList call() throws Exception {\n                return mDriveService.files().list().setSpaces(\"drive\").execute();\n            }\n        });\n    }\n\n    /**\n     * Returns an {@link Intent} for opening the Storage Access Framework file picker.\n     */\n    public Intent createFilePickerIntent() {\n        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);\n        intent.addCategory(Intent.CATEGORY_OPENABLE);\n        intent.setType(\"text/plain\");\n\n        return intent;\n    }\n\n    /**\n     * Opens the file at the {@code uri} returned by a Storage Access Framework {@link Intent}\n     * created by {@link #createFilePickerIntent()} using the given {@code contentResolver}.\n     */\n    public Task\u003cPair\u003cString, String\u003e\u003e openFileUsingStorageAccessFramework(\n            ContentResolver contentResolver, Uri uri) {\n        return Tasks.call(mExecutor, () -\u003e {\n            // Retrieve the document's display name from its metadata.\n            String name;\n            try (Cursor cursor = contentResolver.query(uri, null, null, null, null)) {\n                if (cursor != null \u0026\u0026 cursor.moveToFirst()) {\n                    int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);\n                    name = cursor.getString(nameIndex);\n                } else {\n                    throw new IOException(\"Empty cursor returned for file.\");\n                }\n            }\n\n            // Read the document's contents as a String.\n            String content;\n            try (InputStream is = contentResolver.openInputStream(uri);\n                 BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {\n                StringBuilder stringBuilder = new StringBuilder();\n                String line;\n                while ((line = reader.readLine()) != null) {\n                    stringBuilder.append(line);\n                }\n                content = stringBuilder.toString();\n            }\n\n            return Pair.create(name, content);\n        });\n    }\n}\n```\n\n4.Open `MainActivity.java`\n\n\n```java\npackage io.github.mesadhan.gdrive_app;\n\nimport androidx.appcompat.app.AppCompatActivity;\n\nimport android.os.Bundle;\n\nimport com.google.android.gms.auth.api.signin.GoogleSignIn;\nimport com.google.android.gms.auth.api.signin.GoogleSignInClient;\nimport com.google.android.gms.auth.api.signin.GoogleSignInOptions;\nimport com.google.android.gms.common.api.Scope;\nimport com.google.api.client.extensions.android.http.AndroidHttp;\nimport com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;\nimport com.google.api.client.json.gson.GsonFactory;\nimport com.google.api.services.drive.Drive;\nimport com.google.api.services.drive.DriveScopes;\nimport com.google.api.services.drive.model.File;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android.net.Uri;\nimport android.util.Log;\nimport android.widget.EditText;\n\nimport java.util.Collections;\n\n\npublic class MainActivity extends AppCompatActivity {\n    private static final String TAG = \"MainActivity\";\n\n    private static final int REQUEST_CODE_SIGN_IN = 1;\n    private static final int REQUEST_CODE_OPEN_DOCUMENT = 2;\n\n    private DriveServiceHelper mDriveServiceHelper;\n    private String mOpenFileId;\n\n    private EditText mFileTitleEditText;\n    private EditText mDocContentEditText;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n\n        // Store the EditText boxes to be updated when files are opened/created/modified.\n        mFileTitleEditText = findViewById(R.id.file_title_edittext);\n        mDocContentEditText = findViewById(R.id.doc_content_edittext);\n\n        // Set the onClick listeners for the button bar.\n        findViewById(R.id.open_btn).setOnClickListener(view -\u003e openFilePicker());\n        findViewById(R.id.create_btn).setOnClickListener(view -\u003e createFile());\n        findViewById(R.id.save_btn).setOnClickListener(view -\u003e saveFile());\n        findViewById(R.id.query_btn).setOnClickListener(view -\u003e query());\n\n        // Authenticate the user. For most apps, this should be done when the user performs an\n        // action that requires Drive access rather than in onCreate.\n        requestSignIn();\n    }\n\n    @Override\n    public void onActivityResult(int requestCode, int resultCode, Intent resultData) {\n        switch (requestCode) {\n            case REQUEST_CODE_SIGN_IN:\n                if (resultCode == Activity.RESULT_OK \u0026\u0026 resultData != null) {\n                    handleSignInResult(resultData);\n                }\n                break;\n\n            case REQUEST_CODE_OPEN_DOCUMENT:\n                if (resultCode == Activity.RESULT_OK \u0026\u0026 resultData != null) {\n                    Uri uri = resultData.getData();\n                    if (uri != null) {\n                        openFileFromFilePicker(uri);\n                    }\n                }\n                break;\n        }\n\n        super.onActivityResult(requestCode, resultCode, resultData);\n    }\n\n    /**\n     * Starts a sign-in activity using {@link #REQUEST_CODE_SIGN_IN}.\n     */\n    private void requestSignIn() {\n        Log.d(TAG, \"Requesting sign-in\");\n\n        GoogleSignInOptions signInOptions =\n                new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)\n                        .requestEmail()\n                        .requestScopes(new Scope(DriveScopes.DRIVE_FILE))\n                        .build();\n        GoogleSignInClient client = GoogleSignIn.getClient(this, signInOptions);\n\n        // The result of the sign-in Intent is handled in onActivityResult.\n        startActivityForResult(client.getSignInIntent(), REQUEST_CODE_SIGN_IN);\n    }\n\n    /**\n     * Handles the {@code result} of a completed sign-in activity initiated from {@link\n     * #requestSignIn()}.\n     */\n    private void handleSignInResult(Intent result) {\n        GoogleSignIn.getSignedInAccountFromIntent(result)\n                .addOnSuccessListener(googleAccount -\u003e {\n                    Log.d(TAG, \"Signed in as \" + googleAccount.getEmail());\n\n                    // Use the authenticated account to sign in to the Drive service.\n                    GoogleAccountCredential credential =\n                            GoogleAccountCredential.usingOAuth2(\n                                    this, Collections.singleton(DriveScopes.DRIVE_FILE));\n                    credential.setSelectedAccount(googleAccount.getAccount());\n                    Drive googleDriveService =\n                            new Drive.Builder(\n                                    AndroidHttp.newCompatibleTransport(),\n                                    new GsonFactory(),\n                                    credential)\n                                    .setApplicationName(\"Drive API Migration\")\n                                    .build();\n\n                    // The DriveServiceHelper encapsulates all REST API and SAF functionality.\n                    // Its instantiation is required before handling any onClick actions.\n                    mDriveServiceHelper = new DriveServiceHelper(googleDriveService);\n                })\n                .addOnFailureListener(exception -\u003e Log.e(TAG, \"Unable to sign in.\", exception));\n    }\n\n    /**\n     * Opens the Storage Access Framework file picker using {@link #REQUEST_CODE_OPEN_DOCUMENT}.\n     */\n    private void openFilePicker() {\n        if (mDriveServiceHelper != null) {\n            Log.d(TAG, \"Opening file picker.\");\n\n            Intent pickerIntent = mDriveServiceHelper.createFilePickerIntent();\n\n            // The result of the SAF Intent is handled in onActivityResult.\n            startActivityForResult(pickerIntent, REQUEST_CODE_OPEN_DOCUMENT);\n        }\n    }\n\n    /**\n     * Opens a file from its {@code uri} returned from the Storage Access Framework file picker\n     * initiated by {@link #openFilePicker()}.\n     */\n    private void openFileFromFilePicker(Uri uri) {\n        if (mDriveServiceHelper != null) {\n            Log.d(TAG, \"Opening \" + uri.getPath());\n\n            mDriveServiceHelper.openFileUsingStorageAccessFramework(getContentResolver(), uri)\n                    .addOnSuccessListener(nameAndContent -\u003e {\n                        String name = nameAndContent.first;\n                        String content = nameAndContent.second;\n\n                        mFileTitleEditText.setText(name);\n                        mDocContentEditText.setText(content);\n\n                        // Files opened through SAF cannot be modified.\n                        setReadOnlyMode();\n                    })\n                    .addOnFailureListener(exception -\u003e\n                            Log.e(TAG, \"Unable to open file from picker.\", exception));\n        }\n    }\n\n    /**\n     * Creates a new file via the Drive REST API.\n     */\n    private void createFile() {\n        if (mDriveServiceHelper != null) {\n            Log.d(TAG, \"Creating a file.\");\n\n            mDriveServiceHelper.createFile()\n                    .addOnSuccessListener(fileId -\u003e readFile(fileId))\n                    .addOnFailureListener(exception -\u003e\n                            Log.e(TAG, \"Couldn't create file.\", exception));\n        }\n    }\n\n    /**\n     * Retrieves the title and content of a file identified by {@code fileId} and populates the UI.\n     */\n    private void readFile(String fileId) {\n        if (mDriveServiceHelper != null) {\n            Log.d(TAG, \"Reading file \" + fileId);\n\n            mDriveServiceHelper.readFile(fileId)\n                    .addOnSuccessListener(nameAndContent -\u003e {\n                        String name = nameAndContent.first;\n                        String content = nameAndContent.second;\n\n                        mFileTitleEditText.setText(name);\n                        mDocContentEditText.setText(content);\n\n                        setReadWriteMode(fileId);\n                    })\n                    .addOnFailureListener(exception -\u003e\n                            Log.e(TAG, \"Couldn't read file.\", exception));\n        }\n    }\n\n    /**\n     * Saves the currently opened file created via {@link #createFile()} if one exists.\n     */\n    private void saveFile() {\n        if (mDriveServiceHelper != null \u0026\u0026 mOpenFileId != null) {\n            Log.d(TAG, \"Saving \" + mOpenFileId);\n\n            String fileName = mFileTitleEditText.getText().toString();\n            String fileContent = mDocContentEditText.getText().toString();\n\n            mDriveServiceHelper.saveFile(mOpenFileId, fileName, fileContent)\n                    .addOnFailureListener(exception -\u003e\n                            Log.e(TAG, \"Unable to save file via REST.\", exception));\n        }\n    }\n\n    /**\n     * Queries the Drive REST API for files visible to this app and lists them in the content view.\n     */\n    private void query() {\n        if (mDriveServiceHelper != null) {\n            Log.d(TAG, \"Querying for files.\");\n\n            mDriveServiceHelper.queryFiles()\n                    .addOnSuccessListener(fileList -\u003e {\n                        StringBuilder builder = new StringBuilder();\n                        for (File file : fileList.getFiles()) {\n                            builder.append(file.getName()).append(\"\\n\");\n                        }\n                        String fileNames = builder.toString();\n\n                        mFileTitleEditText.setText(\"File List\");\n                        mDocContentEditText.setText(fileNames);\n\n                        setReadOnlyMode();\n                    })\n                    .addOnFailureListener(exception -\u003e Log.e(TAG, \"Unable to query files.\", exception));\n        }\n    }\n\n    /**\n     * Updates the UI to read-only mode.\n     */\n    private void setReadOnlyMode() {\n        mFileTitleEditText.setEnabled(false);\n        mDocContentEditText.setEnabled(false);\n        mOpenFileId = null;\n    }\n\n    /**\n     * Updates the UI to read/write mode on the document identified by {@code fileId}.\n     */\n    private void setReadWriteMode(String fileId) {\n        mFileTitleEditText.setEnabled(true);\n        mDocContentEditText.setEnabled(true);\n        mOpenFileId = fileId;\n    }\n}\n```\n\n4. Now open up 'activity_main.xml' file\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003candroidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".MainActivity\"\u003e\n\n    \u003cRelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:padding=\"8dp\"\n        tools:context=\".MainActivity\"\u003e\n\n        \u003cEditText\n            android:id=\"@+id/file_title_edittext\"\n            android:layout_height=\"48dp\"\n            android:layout_width=\"match_parent\"\n            android:layout_alignParentTop=\"true\" /\u003e\n\n        \u003cEditText\n            android:id=\"@+id/doc_content_edittext\"\n            android:layout_height=\"wrap_content\"\n            android:layout_width=\"match_parent\"\n            android:layout_below=\"@id/file_title_edittext\"\n            android:layout_above=\"@id/btn_layout\" /\u003e\n\n        \u003cLinearLayout\n            android:id=\"@+id/btn_layout\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"48dp\"\n            android:orientation=\"horizontal\"\n            android:layout_alignParentBottom=\"true\"\u003e\n\n            \u003cButton\n                android:id=\"@+id/open_btn\"\n                android:layout_height=\"match_parent\"\n                android:layout_width=\"0dp\"\n                android:layout_weight=\"1\"\n                android:text=\"Open\"\n                style=\"?attr/buttonBarButtonStyle\" /\u003e\n\n            \u003cButton\n                android:id=\"@+id/create_btn\"\n                android:layout_height=\"match_parent\"\n                android:layout_width=\"0dp\"\n                android:layout_weight=\"1\"\n                android:text=\"Create\"\n                style=\"?attr/buttonBarButtonStyle\" /\u003e\n\n            \u003cButton\n                android:id=\"@+id/save_btn\"\n                android:layout_height=\"match_parent\"\n                android:layout_width=\"0dp\"\n                android:layout_weight=\"1\"\n                android:text=\"Save\"\n                style=\"?attr/buttonBarButtonStyle\" /\u003e\n\n            \u003cButton\n                android:id=\"@+id/query_btn\"\n                android:layout_height=\"match_parent\"\n                android:layout_width=\"0dp\"\n                android:layout_weight=\"1\"\n                android:text=\"Query\"\n                style=\"?attr/buttonBarButtonStyle\" /\u003e\n\n        \u003c/LinearLayout\u003e\n\n    \u003c/RelativeLayout\u003e\n\u003c/androidx.constraintlayout.widget.ConstraintLayout\u003e\n```\n\n👌 Congratulations!. \u0026 Thank You!\nIf you have any issues and queries,Feel Free To Comment.\n\n### References:\n- https://developers.google.com/drive/android/examples\n- https://developers.google.com/drive/android/deprecation\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmesadhan%2Fgoogle-drive-app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmesadhan%2Fgoogle-drive-app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmesadhan%2Fgoogle-drive-app/lists"}