2016-09-03 8 views
0

私のアンドロイドアプリでVimeo APIを使用して、特定のvimeoビデオのリンクを自分のVimeo Proアカウントから取得し、AsyncTaskを通じてこのビデオをダウンロードします。ファイルの読み書きは問題ありませんが、リンクを引っ張ってそのメソッドに渡すのに問題があります。次のようにAsyncTask内で非同期ネットワークタスクを待つ最善の方法

コードは:コードの端部に向かって

class DownloadFileFromURL extends AsyncTask<String, String, String> { 
    ... 
    @Override 
    protected String doInBackground(final String... args) { 
     // args[1]/name is the output file name 
     String name = args[1]; 
     ... 
     // pos is the position within the vimeo channel's array 
     final int pos = Integer.parseInt(args[3]); 

     //Here is the main code, args[2] is the channel id for 
     //the specific vimeo channel that the code 
     //needs to pull the video files from. 
     VimeoClient.getInstance().fetchNetworkContent(args[2], new ModelCallback<VideoList>(VideoList.class) { 
       @Override 
       public void success(VideoList videoList) { 

        //If the video exists, get the video object, 
        //and then get the video files related to that object from download[]. 
        if (videoList != null && videoList.data != null && !videoList.data.isEmpty()) { 
         Video video = videoList.data.get(pos); 
         ArrayList<VideoFile> videoFiles = video.download; 

         // Get the video file, and then get it's link, store as string. 
         if(videoFiles != null && !videoFiles.isEmpty()) { 
          VideoFile videoFile = videoFiles.get(2); // you could sort these files by size, fps, width/height 
          String link = videoFile.getLink(); 

          **link = [test direct link to mp4]; 
          DownloadFile(link, args[1]);** 
         } 
        } 
       } 
       ... 
      }); 

      **//String link = [test direct link to mp4]; 
      //DownloadFile(link, args[1]);** 
     } 
     ... 
    } 

文字列変数とDownloadFile(文字列リンク、列outputName)ラインは私の主要な問題です。私はvideoFile.getLink()からリンクを出力し、それをコードのテストリンクとして使用しました。 vimeoClient.fetchNetworkContentの外でstring link = xxx、およびDownloadFileを実行すると、コードはfetchNetworkContent()メソッドの中に置かれているときに動作し、NetworkOnMainThreadExceptionにヒットします。

問題は、DownloadFile()を実行する前にリンクを取得する必要があることです。 fetchNetworkContent内でこれを修正する方法はありますか?または、NetworkFetchContentが完了するまでコメントアウトされているDownloadFile()の前にシステムを強制的に待機させる方法がありますか?

EDIT:私は、asyncTasksを連鎖させるcricket_007の答えに基づいてコードを更新しました。 2番目のAsyncTaskを作成するのではなく、ロジックシステムで同じタスクをループすることにしました。

最初に実行しているDownloadFileFromURL()は基本的に質問しますが、私はどのような情報を与えていますか?

URLを指定すると、DownloadFile(url、outputsFileName)が実行されます。 そうでない場合、キーワード "vimeo"を受け取ると、vimeoClientを使用してリンクを検索し、その中からDownloadFileFromURL(vimeoLinkURL、outputsFileName)を実行します。私は論理木を使ったばかりだと思います。

class DownloadFileFromURL extends AsyncTask<String, String, String> { 

    @Override 
    protected void onPreExecute() { 
     super.onPreExecute(); 
    } 

    /** 
    * Downloading file in background thread 
    */ 
    @Override 
    protected String doInBackground(final String... args) { 
     final String name = args[1]; 

     // Check if this is already a url link ending in .mp4 
     if(FilenameUtils.isExtension(args[0], "mp4")){ 
       DownloadFile(args[0], args[1]); 
     } 

     //If not, is it a vimeo video? Check with keyword "vimeo" 
     else if (args[0].contains("vimeo")){ 
      final int pos = Integer.parseInt(args[3]); 
      VimeoClient.getInstance().fetchNetworkContent(args[2], new ModelCallback<VideoList>(VideoList.class) { 
       @Override 
       public void success(VideoList videoList) { 
        Log.d("VimeoClient", "Success in VimeoList Reading"); 

        if (videoList != null && videoList.data != null && !videoList.data.isEmpty()) { 

         Video video = videoList.data.get(pos); 
         ArrayList<VideoFile> videoFiles = video.download; 

         if(videoFiles != null && !videoFiles.isEmpty()) { 
          VideoFile videoFile = videoFiles.get(2); // you could sort these files by size, fps, width/height 

          String link = videoFile.getLink(); 
          new DownloadFileFromURL().execute(link, args[1], args[2], args[3]); 
         } 
        } 
       } 

       @Override 
       public void failure(VimeoError error) { 
        Log.d("VimeoError", "Failure in VideoList Reading in VideoDownloader class"); 
       } 
      }); 
      // return null so that the Toast is not created for completion 
      // since this ends in DownloadFile() 
      return null; 
     } 
     return name; 
    } 

    @Override 
    protected void onPostExecute(String fileName) { 
     if(fileName != null) { 
      Toast.makeText(mContext, "Completed download of " + fileName, Toast.LENGTH_LONG).show(); 
     } 
    } 
} 

最終的なコードではなく、正しい答えとしてマークしましたが、私が使用した特定のコードよりもはるかに有益です。私のコードはこのユースケースでは私の特定のソリューションに特有ですが、彼の説明は本当の解決策でした。

+1

私はおそらく 'ModelCallBack#success()'がUIスレッドで呼び出されていると思います。私は、 'AsyncTask'で' fetchNetworkContent() '呼び出しをラップするのではなく、UIスレッド上で直接呼び出すことができます(別のスレッドで実行する必要があります) 'メソッドを呼び出して' DownloadFile() 'を呼び出します。 – Clyde

答えて

0

DownloadFileメソッドの処理内容は不明ですが、セカンダリAsyncTaskが必要な場合があります。

Sidenote:私はVimeoClient.getInstance().fetchNetworkContentがそれ自身のスレッドで実行されることを願っています。したがって、AsyncTaskは必要ありませんが、そうではないと思われます。

AsyncTaskを「待機」する推奨の方法は、呼び出しを慎重に連鎖させることです。たとえば、1つのAsyncTaskにコールバックを渡すと、successメソッドが実行されます。その後

class DownloadFileFromURL extends AsyncTask<String, Void, Void> { 
    private ModelCallback<VideoList> callback; 

    public DownloadFileFromURL(ModelCallback<VideoList> callback) { 
     this.callback = callback; 
    } 

    @Override 
    protected Void doInBackground(final String... args) { 

     //Here is the main code, args[0] is the channel id for 
     //the specific vimeo channel that the code 
     //needs to pull the video files from. 
     VimeoClient.getInstance().fetchNetworkContent(args[0], callback); 

    } 
    ... 
} 

をあなたがそのタスクを呼び出すどこでもそのsuccessの中から、あなたがDownloadFileを呼ぶ新しいタスクを開始することができ、(あなたはすべてのリンクをダウンロードしたい場合は、おそらくただ一つのリンクではなく、それを全体ArrayList<VideoFile>を与えます) 、あなたが実行したいアクションのためのインターフェースを渡します

// Need these values inside the callback - have to be final 
final String arg1; 
final int pos; 

// The callback that is hit from doInBackground() 
ModelCallback<VideoList> callback = new ModelCallback<VideoList>(VideoList.class) { 
    @Override 
    public void success(VideoList videoList) { 

     //If the video exists, get the video object, 
     //and then get the video files related to that object from download[]. 
     if (videoList != null && videoList.data != null && !videoList.data.isEmpty()) { 
      Video video = videoList.data.get(pos); 
      ArrayList<VideoFile> videoFiles = video.download; 

      // Get the video file, and then get it's link, store as string. 
      if(videoFiles != null && !videoFiles.isEmpty()) { 
       VideoFile videoFile = videoFiles.get(2); // you could sort these files by size, fps, width/height 
       String link = videoFile.getLink(); 

       // TODO: Might need to execute another AsyncTask 
       DownloadFile(link, arg1); 
      } 
     } 
    } 
    ... 
}; 

// pass the callback to the task 
new DownloadFileFromURL(callback).execute("channel_id"); 
+0

私はあなたの説明を、どのようにして問題を解決すべきかの基礎として使用しました。上で私の編集で説明したように、私は同じAsycTaskを通してループすることにしました。しかし、fetchNetworkContentはおそらくそれ自身のスレッドで動作するはずです。私はそれが何をすると思いますか? AsyncTaskで実行する必要はありません(まだ学習していて、スレッドについてはあまりよく分かりません)。そうであれば、このコードのこのセクションを「より良い」ものに改めるでしょうか? – NappyXIII

+0

それが独自のバックグラウンドで実行されている場合は、おそらく、AsyncTaskを持たないことをお勧めします。 「正常に完了しました」というメッセージをコールバックの成功メソッドの末尾に移動することができます –

+2

fetchメソッドは新しいスレッドでその作業を行います。要求を開始したスレッドで成功ブロックが呼び出されます。 AsyncTaskでラップする必要はありません。 –

0

あなたがやってみることができるものは次のとおりです。

class DownloadFileFromURL extends AsyncTask<String, String, String> implements LinkReceivedListener{ 
... 
LinkRecievedListener callbackListener; 

@Override 
protected void onPostExecute(String result) { 
    // The result is the returned String link value from doInbackground() 
    DownloadFile(result, args[1]); 
} 

@Override 
protected String doInBackground(final String... args) { 
    String name = args[1]; 
    final int pos = Integer.parseInt(args[3]); 

    VimeoClient.getInstance().fetchNetworkContent(args[2], new ModelCallback<VideoList>(VideoList.class) { 
      @Override 
      public void success(VideoList videoList) { 

       //If the video exists, get the video object, 
       //and then get the video files related to that object from download[]. 
       if (videoList != null && videoList.data != null && !videoList.data.isEmpty()) { 
        Video video = videoList.data.get(pos); 
        ArrayList<VideoFile> videoFiles = video.download; 

        // Get the video file, and then get it's link, store as string. 
        if(videoFiles != null && !videoFiles.isEmpty()) { 
         VideoFile videoFile = videoFiles.get(2); // you could sort these files by size, fps, width/height 
         String link = videoFile.getLink(); 
         callbackListener.onSuccess(link); 
        } 
       } 
      } 
      ... 
     }); 
    } 
    ... 
} 

public interface LinkRecievedListener { 
    void onSuccess(String linkString); 
} 
+0

これは動作しません...成功メソッドは無効です、あなたから返すことはできません –

+0

私は自分の答えを編集しました。それは正しい方向を指すはずです。 –

関連する問題