使用OneDrive SDK在AsyncTask中下载文件会引发NetworkOnMainThreadException

时间:2016-08-02 09:41:03

标签: android

我是Android开发的新手。如果有任何更多细节,请告诉我。

据我所知,AsyncTask正在使用工作线程,所以它不应该导致NetworkOnMainThreadException。有什么我做错了吗?感谢。

我已经暗示了OneDrive's Explorer例子的结构。 我创建了一个扩展Application的baseApplication,其中包含IOneDriveClient的实例。

/**
 * Base application
 */
public class OneDriveBaseApplication extends Application {
    public static final String Log_Tag = "MyDebug";

    /**
     * The service instance
     */
    private final AtomicReference<IOneDriveClient> mClient = new AtomicReference<>();

    /**
     * Create the client configuration
     * @return the newly created configuration
     */
    private IClientConfig createConfig() {
        final MSAAuthenticator msaAuthenticator = new MSAAuthenticator() {
            @Override
            public String getClientId() {
                SharedPreferences onedrivePref = getApplicationContext().getSharedPreferences(getString(R.string.onedrive_pref_key), Context.MODE_PRIVATE);
                String msa_client_id = onedrivePref.getString(getString(R.string.onedrive_pref_app_key), "");
                Log.v(Log_Tag, msa_client_id);
                return msa_client_id;
            }

            @Override
            public String[] getScopes() {
                return new String[]{"onedrive.appfolder offline_access"};
            }
        };

        final IClientConfig config = DefaultClientConfig.createWithAuthenticator(msaAuthenticator);
        config.getLogger().setLoggingLevel(LoggerLevel.Debug);
        return config;
    }
    /**
     * Used to setup the Services
     *
     * @param activity       the current activity
     * @param serviceCreated the callback
     */
    synchronized void createOneDriveClient(final Activity activity, final ICallback<Void> serviceCreated) {
        final DefaultCallback<IOneDriveClient> callback = new DefaultCallback<IOneDriveClient>(activity) {
            @Override
            public void success(final IOneDriveClient result) {
                mClient.set(result);
                serviceCreated.success(null);
            }

            @Override
            public void failure(final ClientException error) {
                serviceCreated.failure(error);
            }
        };
        new OneDriveClient
                .Builder()
                .fromConfig(createConfig())
                .loginAndBuildClient(activity, callback);
    }

    /**
     * Get an instance of the service
     *
     * @return The Service
     */
    synchronized IOneDriveClient getOneDriveClient() {
        if (mClient.get() == null) {
            throw new UnsupportedOperationException("Unable to generate a new service object");
        }
        return mClient.get();
    }
}

在我的片段中,我创建了一个asynctask类来下载文件。

private class DownloadTask extends AsyncTask<Void, Void, Void> {
    @Override
    protected Void doInBackground(Void... params) {

        final OneDriveBaseApplication app = (OneDriveBaseApplication)getActivity().getApplication();
        try {
            app.getOneDriveClient()
                    .getDrive()
                    .getSpecial("approot")
                    .getChildren()
                    .buildRequest()
                    .get(new DefaultCallback<IItemCollectionPage>(getActivity()) {
                        @Override
                        public void success(final IItemCollectionPage result) {
                            Log.v(OneDriveBaseApplication.Log_Tag, "get children success");
                            if (result != null) {
                                for (final Item childItem : result.getCurrentPage()) {
                                    try {
                                        final String itemId = childItem.id;
                                        final String itemName = childItem.name;
                                        byte[] buffer = new byte[1024];
                                        int len = 0;
                                        Log.v(OneDriveBaseApplication.Log_Tag, "name " + itemName + " id " + itemId);
                                        final File firDownloadDir = new File(Environment.getExternalStorageDirectory() + File.separator + "downloaded_files");
                                        firDownloadDir.mkdir();
                                        final File file = new File(firDownloadDir, itemName);
                                        Log.v(OneDriveBaseApplication.Log_Tag, "File path " + file.getPath());
                                        FileOutputStream out = new FileOutputStream(file);
                                        Log.v(OneDriveBaseApplication.Log_Tag, "FileOutputStream Established");

                                    /* Get the file from OneDrive*/
                                        Log.v(OneDriveBaseApplication.Log_Tag, "To get the file from OneDrive");
                                        InputStream in = app.getOneDriveClient()
                                                .getDrive()
                                                .getItems(itemId)
                                                .getContent()
                                                .buildRequest()
                                                .get();
                                        Log.v(OneDriveBaseApplication.Log_Tag, "Get the file from OneDrive succesfully");
                                        while ((len = in.read(buffer)) != -1) {
                                            out.write(buffer, 0, len);
                                        }
                                        Log.v(OneDriveBaseApplication.Log_Tag, "Write successfully: " + childItem.name);
                                    } catch (FileNotFoundException ex) {
                                        Log.v(OneDriveBaseApplication.Log_Tag, "File not found when downloading: " + childItem.name);
                                    } catch (IOException ex) {
                                        Log.v(OneDriveBaseApplication.Log_Tag, "IOException when writing/reading: " + childItem.name);
                                    }
                                }
                            }
                        }

                        @Override
                        public void failure(ClientException ex) {
                            Log.v(OneDriveBaseApplication.Log_Tag, "ClientException");
                        }
                    });
        } catch (UnsupportedOperationException ex) {
            Log.v(OneDriveBaseApplication.Log_Tag, "UnsupportedOperationException");
        } catch (Error error) {
            Log.v(OneDriveBaseApplication.Log_Tag, "Error for whatsoever");
        }
        return null;
    }
}

执行
DownloadTask downloadTask = new DownloadTask();
downloadTask.execute();

但是,它在发送GET请求时会导致NetworkOnMainThreadException。

202: Starting to send request, URL https://api.onedrive.com/v1.0/drive/items/AB76E7297xxxxxxx!110/content
206: Request Method GET
312: Error during http request
                  com.onedrive.sdk.core.ClientException: Error during http request
                    at com.onedrive.sdk.http.DefaultHttpProvider.sendRequestInternal(DefaultHttpProvider.java:309)
                    at com.onedrive.sdk.http.DefaultHttpProvider.send(DefaultHttpProvider.java:165)
                    at com.onedrive.sdk.http.BaseStreamRequest.send(BaseStreamRequest.java:76)
                    at com.onedrive.sdk.generated.BaseItemStreamRequest.get(BaseItemStreamRequest.java:60)
                    at tw.com.www.onedrivedemo.PlaceholderFragment$DownloadTask$1.success(PlaceholderFragment.java:159)
                    at tw.com.www.onedrivedemo.PlaceholderFragment$DownloadTask$1.success(PlaceholderFragment.java:133)
                    at com.onedrive.sdk.concurrency.DefaultExecutors$1.run(DefaultExecutors.java:88)
                    at com.onedrive.sdk.concurrency.SynchronousExecutor$1.onPostExecute(SynchronousExecutor.java:54)
                    at com.onedrive.sdk.concurrency.SynchronousExecutor$1.onPostExecute(SynchronousExecutor.java:46)
                    at android.os.AsyncTask.finish(AsyncTask.java:660)
                    at android.os.AsyncTask.-wrap1(AsyncTask.java)
                    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:677)
                    at android.os.Handler.dispatchMessage(Handler.java:102)
                    at android.os.Looper.loop(Looper.java:154)
                    at android.app.ActivityThread.main(ActivityThread.java:6077)
                    at java.lang.reflect.Method.invoke(Native Method)
                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
                  Caused by: android.os.NetworkOnMainThreadException
                    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
                    at com.android.org.conscrypt.Platform.blockGuardOnNetwork(Platform.java:300)
                    at com.android.org.conscrypt.OpenSSLSocketImpl$SSLOutputStream.write(OpenSSLSocketImpl.java:808)
                    at com.android.okhttp.okio.Okio$1.write(Okio.java:76)
                    at com.android.okhttp.okio.AsyncTimeout$1.write(AsyncTimeout.java:155)
                    at com.android.okhttp.okio.RealBufferedSink.flush(RealBufferedSink.java:221)
                    at com.android.okhttp.internal.http.HttpConnection.flush(HttpConnection.java:141)
                    at com.android.okhttp.internal.http.HttpTransport.finishRequest(HttpTransport.java:52)
                    at com.android.okhttp.internal.http.HttpEngine.readNetworkResponse(HttpEngine.java:904)
                    at com.android.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:782)
                    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:463)
                    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:405)
                    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:521)
                    at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:105)
                    at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java)
                    at com.onedrive.sdk.http.UrlConnection.getResponseCode(UrlConnection.java:100)
                    at com.onedrive.sdk.http.DefaultHttpProvider.sendRequestInternal(DefaultHttpProvider.java:245)
                    at com.onedrive.sdk.http.DefaultHttpProvider.send(DefaultHttpProvider.java:165) 
                    at com.onedrive.sdk.http.BaseStreamRequest.send(BaseStreamRequest.java:76) 
                    at com.onedrive.sdk.generated.BaseItemStreamRequest.get(BaseItemStreamRequest.java:60) 
                    at tw.com.www.onedrivedemo.PlaceholderFragment$DownloadTask$1.success(PlaceholderFragment.java:159) 
                    at tw.com.www.onedrivedemo.PlaceholderFragment$DownloadTask$1.success(PlaceholderFragment.java:133) 
                    at com.onedrive.sdk.concurrency.DefaultExecutors$1.run(DefaultExecutors.java:88) 
                    at com.onedrive.sdk.concurrency.SynchronousExecutor$1.onPostExecute(SynchronousExecutor.java:54) 
                    at com.onedrive.sdk.concurrency.SynchronousExecutor$1.onPostExecute(SynchronousExecutor.java:46) 
                    at android.os.AsyncTask.finish(AsyncTask.java:660) 
                    at android.os.AsyncTask.-wrap1(AsyncTask.java) 
                    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:677) 
                    at android.os.Handler.dispatchMessage(Handler.java:102) 
                    at android.os.Looper.loop(Looper.java:154) 
                    at android.app.ActivityThread.main(ActivityThread.java:6077) 
                    at java.lang.reflect.Method.invoke(Native Method) 
                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) 
                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

3 个答案:

答案 0 :(得分:2)

看起来OneDriveClient正在为您处理异步。

因此,您不需要在AsyncTask中调用基本上是请求的设置。您可能希望在AsyncTask回调中添加success(),因为问题出在客户端上调用.get()时。这是一个阻塞操作,它将执行当前线程上的操作。在这种情况下,该线程是从该线程调用的success的mainThread。

解决方案:了解哪些部分是异步的并将它们移出mainThread。简化您的代码,以便您可以了解哪些部分失败。

使用断点和/或日志查看您在不同位置使用的线程。

答案 1 :(得分:0)

你的onPostExecute方法在哪里?

这是一篇很好的文章:How to fix android.os.NetworkOnMainThreadException?

当您的应用尝试在主线程中进行网络操作时,会引发NetworkOnMainThreadException。 尝试使用runOnUiThread:

runOnUiThread(new Runnable() {
                public void run() {
                // call your async task.
            }
        });

答案 2 :(得分:0)

在UIThread中,您无法像访问网络一样运行耗时的操作。因此,您应该在其他线程上运行它。你可以试试这个:

DownloadTask downloadTask = new DownloadTask();
new Thread(new Runnable() {
        @Override
        public void run() {
            downloadTask.execute();      
        }
    }).start();