我正在使用我的Android应用中的Vimeo API从我的Vimeo Pro帐户中提取特定vimeo视频的链接,然后通过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(String link,string outputName)行是我的主要问题。我从videoFile.getLink()打印出链接,并将其用作代码的测试链接。当我在vimeoClient.fetchNetworkContent之外运行string link = xxx和DownloadFile时(在最后注释掉),代码工作,而当它们放在fetchNetworkContent()方法中时,它会遇到NetworkOnMainThreadException。
问题是我需要在DownloadFile()运行之前检索链接。有没有办法让我在fetchNetworkContent中解决这个问题?或者有没有办法强制系统在注释掉的DownloadFile()之前等待,直到networkFetchContent完成?
编辑:所以我根据cricket_007链接AsyncTasks的答案更新了我的代码。我没有创建第二个AsyncTask,而是决定用逻辑系统将它循环到同一个任务中。
首先运行的DownloadFileFromURL()基本上询问,我给出了哪些信息?
如果给出了一个url,它将运行DownloadFile(url,outputsFileName)。 如果没有,如果它收到关键字&#34; vimeo&#34;,它使用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();
}
}
}
我已经将他的答案标记为正确,而不是因为它是最终的代码,但我发现它比我使用的特定代码更具信息性。我的代码确实特定于我在这个用例中的特定解决方案,但他的解释是真正的解决方案。
答案 0 :(得分: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);
}
答案 1 :(得分:0)
目前还不清楚DownloadFile方法正在做什么,但您可能需要一个辅助AsyncTask。
旁注:我希望VimeoClient.getInstance().fetchNetworkContent
无论如何都会在其自己的主题中运行,因此它不应该需要AsyncTask,但我们会假装它不会。
推荐的方法&#34;等待&#34;对于AsyncTask,要小心地将调用链接在一起。例如,如果给一个AsyncTask回调,那么success
方法就会运行。在success
内,你可以开始一个新的任务,调用DownloadFile
(如果你想下载所有的链接,可能会给它整个ArrayList<VideoFile>
而不是一个链接)
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);
}
...
}
然后,无论您在何处调用该任务,都要传递要执行的操作的界面
// 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");