2016-08-02 7 views
2

Ich bin ziemlich neu in Android-Entwicklung. Bitte lassen Sie mich wissen, sollte es weitere Details geben, die ich hinzufügen sollte.Download-Datei in AsyncTask mit OneDrive SDK wirft NetworkOnMainThreadException

Soweit ich weiß, AsyncTask verwendet einen Arbeitsthread, so sollte es NetworkOnMainThreadException nicht verursachen. Habe ich irgendetwas falsch gemacht? Vielen Dank.

Ich habe die Struktur von OneDrive's Explorer Beispiel angedeutet. Ich habe eine baseApplication erstellt, die die Anwendung erweitert, die eine Instanz für IOneDriveClient enthält.

/** 
* 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(); 
    } 
} 

Und in meinem Fragment habe ich eine asynctask Klasse erstellt, um Dateien herunterzuladen.

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

und führen Sie es mit

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

Allerdings führt es eine NetworkOnMainThreadException wenn eine GET-Anfrage zu senden.

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) 
+1

möglich divicate von [wie android.os.NetworkOnMainThreadException zu beheben?] (Http://stackoverflow.com/questions/6343166/how-to-fix-android-os-networkonmainthreadexception) –

Antwort

2

Es sieht aus wie die OneDriveClient die async für Sie verarbeitet.

So müssen Sie nicht anrufen, was im Wesentlichen die Einrichtung der Anfrage in einem AsyncTask ist. Vielleicht möchten Sie eine AsyncTask innerhalb der success() Rückruf, wie das Problem ist, wenn Sie .get() auf dem Client aufrufen. Dies ist eine Blockierungsoperation, die die Aktion dann und dort auf dem aktuellen Thread ausführt. In diesem Fall ist dieser Thread der mainThread als success, der von diesem Thread aufgerufen wird.

Lösung: Verstehen Sie, welche Teile async sind und verschieben Sie sie aus dem mainThread. Vereinfachen Sie Ihren Code, damit Sie verstehen, welcher Teil fehlschlägt.

Verwenden Sie Haltepunkte und/oder Protokolle, um zu sehen, an welchem ​​Thread Sie sich an verschiedenen Stellen befinden.

+1

Danke! Die Verwendung von AsyncTask innerhalb des success() - Callbacks funktioniert. – Chiu

0

Wo ist Ihre onPostExecute-Methode?

Das ist ein guter Artikel für Sie: How to fix android.os.NetworkOnMainThreadException?

NetworkOnMainThreadException wird ausgelöst, wenn Ihre Anwendung versucht in Haupt-Thread Betrieb Vernetzung. Versuchen runOnUiThread zu verwenden:

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

In UIThread, können Sie nicht zeitaufwendiger Vorgang wie den Zugang zum network.So Sie sollte es laufen auf anderen Thread ausgeführt. Sie können dies versuchen:

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

Danke. Habe gerade versucht, die downloadTask in "new Thread" auszuführen, aber "NetworkOnMainThreadException" passiert immer noch. – Chiu

Verwandte Themen