2

I'm fairly new to Android development. Please let me know should there be any more detail I should add.

As far as I know, AsyncTask is using a worker thread, so it shouldn't cause NetworkOnMainThreadException. Is there anything I did wrong? Thanks.

I have intimated the structure of OneDrive's Explorer example. I created an baseApplication extending Application, which includes an instance for 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();
    }
}

And in my fragment, I created an asynctask class to download files.

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;
    }
}

And execute it with

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

However, it results a NetworkOnMainThreadException when sending a GET request.

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)
Chiu
  • 350
  • 4
  • 14
  • 1
    possible diplicate of [How to fix android.os.NetworkOnMainThreadException?](http://stackoverflow.com/questions/6343166/how-to-fix-android-os-networkonmainthreadexception) – V-rund Puro-hit Aug 02 '16 at 09:53

3 Answers3

2

It looks like the OneDriveClient is handling the async for you.

So you don't need to call what is essentially the setup of the request in an AsyncTask. You may want to put an AsyncTask inside the success() callback, as the problem is when you call .get() on the client. This is a blocking operation which will perform the action then and there on the current thread. In this case, that thread is the mainThread as success called from that thread.

Solution: understand which parts are async and move them off of the mainThread. Simplify your code so that you can understand what part is failing.

Use breakpoints and/or logs to see what thread you are on at different places.

Andrew G
  • 2,596
  • 2
  • 19
  • 26
0

Where is your onPostExecute method?

This is good article for you: How to fix android.os.NetworkOnMainThreadException?

NetworkOnMainThreadException is thrown when your app tries networking operation in main thread. Try to use runOnUiThread:

runOnUiThread(new Runnable() {
                public void run() {
                // call your async task.
            }
        });
Community
  • 1
  • 1
xxx
  • 3,315
  • 5
  • 21
  • 40
0

In UIThread,you can't run time-consuming operation like access to the network.So you should run it on other thread. You can try this:

DownloadTask downloadTask = new DownloadTask();
new Thread(new Runnable() {
        @Override
        public void run() {
            downloadTask.execute();      
        }
    }).start();
  • Thanks. Just tried execute the downloadTask in "new Thread", but "NetworkOnMainThreadException" still happens. – Chiu Aug 02 '16 at 10:11