如何使用Android链接从Google云端硬盘下载文件?

时间:2018-02-08 05:50:15

标签: android android-fragments google-drive-api

我想从google驱动器下载文件,我使用compile 'com.google.android.gms:play-services:8.4.0'依赖关系,并使用此功能我可以从下面的示例中获取元数据的链接。

mFileId = (DriveId) data.getParcelableExtra(
                        OpenFileActivityBuilder.EXTRA_RESPONSE_DRIVE_ID);


                final DriveFile file = Drive.DriveApi.getFile(mGoogleApiClient, mFileId);


                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        // DO your work here
                        DriveResource.MetadataResult mdRslt = file.getMetadata(mGoogleApiClient).await();
                        if (mdRslt != null && mdRslt.getStatus().isSuccess()) {
                           String  link = mdRslt.getMetadata().getWebContentLink();
                            String name=mdRslt.getMetadata().getTitle();
                            Log.d("LINK", link);
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && getApplication().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
                            {
                                requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
                            }
                            else
                            {

                              new  get_download_data(link,name).execute();
                            }
                        }
                    }
                }).start();
                }

从Google云端硬盘获取链接后,我正在调用异步任务从链接下载该文件。所以我的问题是当我下载文件时,它没有打开。检查和调试后,我发现我的文件没有正确下载。

例如,我的文件名为abc.pdf,大小为400kb。我在我的SD卡上下载但abc.pdf仅为56 kb。我使用下面的代码下载。我不知道我做错了什么。请帮忙。谢谢。

 public class get_download_data extends AsyncTask<Void,Void,String>
{
    File apkStorage = null;
    File outputFile = null;
    String link1="";
    String name1="";

    public get_database_data(String link, String name) {
        this.link1=link;
        this.name1=name;
    }
    protected void onPreExecute() {
        super.onPreExecute();



    }
    @Override
    protected String doInBackground(Void... params) {

        try {

            URL url = new URL(link1);//Create Download URl

            HttpURLConnection c = (HttpURLConnection) url.openConnection();//Open Url Connection
            c.setRequestMethod("GET");//Set Request Method to "GET" since we are grtting data


            c.setDoInput(true);

            c.connect();//connect the URL Connection

            //If Connection response is not OK then show Logs
            if (c.getResponseCode() != HttpURLConnection.HTTP_OK) {
                Log.e(TAG, "Server returned HTTP " + c.getResponseCode()
                        + " " + c.getResponseMessage());

            }else{
                Log.e(TAG, "Server returned HTTP " + c.getResponseCode()
                        + " " + c.getResponseMessage());
            }


            //Get File if SD card is present
            if (new CheckForSDCard().isSDCardPresent()) {

                apkStorage = new File(
                        Environment.getExternalStorageDirectory() + "/"
                                + "checkdb");
            } else
                Toast.makeText(getApplication(), "Oops!! There is no SD Card.", Toast.LENGTH_SHORT).show();

            //If File is not present create directory
            if (!apkStorage.exists()) {
                apkStorage.mkdir();
                Log.e(TAG, "Directory Created.");
            }

            outputFile = new File(apkStorage, name1);//Create Output file in Main File

            //Create New File if not present
            if (!outputFile.exists()) {
                outputFile.createNewFile();
                Log.e(TAG, "File Created");
            }

            OutputStream fos = new FileOutputStream(outputFile);//Get OutputStream for NewFile Location

            InputStream is = c.getInputStream();//Get InputStream for connection
            BufferedInputStream inStream = new BufferedInputStream(is, 1024);

            byte[] buffer = new byte[1024];//Set buffer type
            int len1 = 0;//init length
            while ((len1 = inStream.read(buffer)) != -1) {
                fos.write(buffer, 0, len1);//Write new file
            }

            //Close all connection after doing task
            fos.flush();
            fos.close();
            is.close();

        } catch (Exception e) {

            //Read exception if something went wrong
            e.printStackTrace();
            outputFile = null;
            Log.e(TAG, "Download Error Exception " + e.getMessage());
        }
        return null;
    }

    @Override
    protected void onPostExecute(String result_1) {
        super.onPostExecute(result_1);
        String downlodepath = Environment.getExternalStorageState()+"/"+name1;
        Log.e("Sdpath",""+imagePath);
        Toast.makeText(getApplication(), "download"+downlodepath, Toast.LENGTH_SHORT).show();

    }
}

我找到了这个链接here,但有些我怎么也不知道如何实现这个。请让我知道我哪里错了。感谢。

4 个答案:

答案 0 :(得分:5)

经过一番努力并尝试了很多例子后,我找到了答案。 以下是我在项目中添加的依赖项:

compile 'com.google.android.gms:play-services-auth:11.8.0'
compile 'com.google.android.gms:play-services-drive:11.8.0'

这是我的清单文件:

<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

<application
    android:allowBackup="false"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="@string/google_api_key" />

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

</manifest>

这是我的MainActivity:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

private ActivityMainBinding binding;

private static final String TAG = "Google drive";
private static final String SIGN_IN = "Sign In";
private static final String DOWNLOAD_FILE = "Download file";

private static final int REQUEST_CODE_SIGN_IN = 0;
private static final int REQUEST_CODE_OPEN_ITEM = 1;
private static final int REQUEST_WRITE_STORAGE = 112;


private GoogleSignInAccount signInAccount;
private Set<Scope> requiredScopes;
private DriveClient mDriveClient;
private DriveResourceClient mDriveResourceClient;

private OpenFileActivityOptions openOptions;
private TaskCompletionSource<DriveId> mOpenItemTaskSource;
private File storageDir;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

    initialize();
    requestPermission();
    signInAccount = GoogleSignIn.getLastSignedInAccount(this);

    binding.btnSubmit.setOnClickListener(this);
    if (signInAccount != null && signInAccount.getGrantedScopes().containsAll(requiredScopes)) {
        initializeDriveClient(signInAccount);
        binding.btnSubmit.setText(DOWNLOAD_FILE);
    } else {
        binding.btnSubmit.setText(SIGN_IN);
    }

}

private void showMessage(String message) {
    Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case REQUEST_CODE_SIGN_IN:
            if (resultCode == RESULT_OK) {
                Task<GoogleSignInAccount> getAccountTask = GoogleSignIn.getSignedInAccountFromIntent(data);
                if (getAccountTask.isSuccessful()) {
                    initializeDriveClient(getAccountTask.getResult());
                    showMessage("Sign in successfully.");
                    binding.btnSubmit.setText(DOWNLOAD_FILE);
                } else {
                    showMessage("Sign in failed.");
                }
            } else {
                showMessage("Sign in failed.");
            }
            break;
        case REQUEST_CODE_OPEN_ITEM:
            if (resultCode == RESULT_OK) {
                DriveId driveId = data.getParcelableExtra(OpenFileActivityOptions.EXTRA_RESPONSE_DRIVE_ID);
                mOpenItemTaskSource.setResult(driveId);
            } else {
                mOpenItemTaskSource.setException(new RuntimeException("Unable to open file"));
            }
            break;
    }
}


private void initialize() {

    requiredScopes = new HashSet<>(2);
    requiredScopes.add(Drive.SCOPE_FILE);
    requiredScopes.add(Drive.SCOPE_APPFOLDER);

    openOptions = new OpenFileActivityOptions.Builder()
            .setSelectionFilter(Filters.eq(SearchableField.MIME_TYPE, "application/pdf"))
            .setActivityTitle("Select file")
            .build();
}

private void initializeDriveClient(GoogleSignInAccount signInAccount) {
    mDriveClient = Drive.getDriveClient(getApplicationContext(), signInAccount);
    mDriveResourceClient = Drive.getDriveResourceClient(getApplicationContext(), signInAccount);
}

@Override
public void onClick(View view) {
    if (view.getId() == R.id.btnSubmit) {
        String text = (String) ((Button) view).getText();
        if (text.equals(SIGN_IN)) {
            signIn();
        } else {
            onDriveClientReady();
        }
    }
}

private void signIn() {
    GoogleSignInOptions signInOptions = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestScopes(Drive.SCOPE_FILE)
            .requestScopes(Drive.SCOPE_APPFOLDER)
            .build();
    GoogleSignInClient googleSignInClient = GoogleSignIn.getClient(this, signInOptions);
    startActivityForResult(googleSignInClient.getSignInIntent(), REQUEST_CODE_SIGN_IN);
}

private void onDriveClientReady() {
    mOpenItemTaskSource = new TaskCompletionSource<>();
    mDriveClient.newOpenFileActivityIntentSender(openOptions)
            .continueWith(new Continuation<IntentSender, Void>() {
                @Override
                public Void then(@NonNull Task<IntentSender> task) throws Exception {
                    startIntentSenderForResult(
                            task.getResult(), REQUEST_CODE_OPEN_ITEM, null, 0, 0, 0);
                    return null;
                }
            });

    Task<DriveId> tasks = mOpenItemTaskSource.getTask();
    tasks.addOnSuccessListener(this,
            new OnSuccessListener<DriveId>() {
                @Override
                public void onSuccess(DriveId driveId) {
                    retrieveContents(driveId.asDriveFile());
                }
            })
            .addOnFailureListener(this, new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    showMessage("File not selected.");
                }
            });
}

private void retrieveContents(final DriveFile file) {
    // [START open_file]
    final Task<DriveContents> openFileTask = mDriveResourceClient.openFile(file, DriveFile.MODE_READ_ONLY);
    // [END open_file]
    // [START read_contents]
    openFileTask.continueWithTask(new Continuation<DriveContents, Task<Void>>() {
        @Override
        public Task<Void> then(@NonNull Task<DriveContents> task) throws Exception {
            DriveContents contents = task.getResult();

            Log.v(TAG, "File name : " + contents.toString());
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
                InputStream input = contents.getInputStream();

                try {
                    File file = new File(getExternalFilesDir(null), "umesh.pdf");
                    Log.v(TAG, storageDir + "");
                    OutputStream output = new FileOutputStream(file);
                    try {
                        try {
                            byte[] buffer = new byte[4 * 1024]; // or other buffer size
                            int read;

                            while ((read = input.read(buffer)) != -1) {
                                output.write(buffer, 0, read);
                            }
                            output.flush();
                        } finally {
                            output.close();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        input.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            showMessage("Download file successfully.");
            return mDriveResourceClient.discardContents(contents);
        }
    })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    showMessage("Unable to download file.");
                }
            });
    // [END read_contents]
}

private void requestPermission() {
    String dirPath = getFilesDir().getAbsolutePath() + File.separator + "PDF";
    storageDir = new File(dirPath);
    if (!storageDir.exists())
        storageDir.mkdirs();}}

这是API密钥的字符串文件:

<resources>
    <string name="app_name">GoogleDriveDemo</string>

    <string name="google_api_key">"your-key"</string>
</resources>

答案 1 :(得分:0)

在Drive API中下载文件时使用webContentLink的方法是在Javascript中打开一个新的浏览器窗口。

var webcontentlink = 'https://docs.google.com/a/google.com/uc?id='+fileId+'&export=download'
window.open( webcontentlink);

我建议您在Android中执行此操作,如post中提到的那样:

Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(webcontentlink));
startActivity(browserIntent);

答案 2 :(得分:0)

对于仍然陷在此问题中的人。 在driveResourceClient.createFile()

之后无法以某种方式返回下载URL
driveResourceClient?.createFile(appFolder, metadataChangeSet, contents)
            }?.addOnSuccessListener(this
            ) { driverFile -> //we cannot get webContentLink here }

目前,我们只能获取文件名(可能已经定义了该文件名)

对于我来说,上传后我并不需要URL,而是当用户单击复制URL按钮时

driveResourceClient?.query(Query.Builder()
                .addFilter(Filters.eq(SearchableField.TITLE, sharedFileName))
                .build())
                ?.addOnSuccessListener {
                    url = it.first().webContentLink
                }
                ?.{
                }

我已经成功了。

答案 3 :(得分:0)

您可以使用chrome自定义标签轻松地做到这一点,只需将网址粘贴到自定义标签中,它将显示驱动器网站,并且可以下载文件 请参阅此官方文档以获取chrome自定义标签https://developer.chrome.com/multidevice/android/customtabs,这是一项非常出色的功能,也是Webview的最佳替代方法