使用执行程序服务从 url 下载
download from url with executor service
我在执行程序服务中使用下面的代码从 URL 下载文件。它下载文件但大小为 0 字节。当我使用 asyncTask 时代码工作正常。但是当我把它放在执行程序服务中时不起作用。
下载无法完成的任何想法?
创建时:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ExecutorService pool = Executors.newSingleThreadExecutor();
Button btn = findViewById(R.id.btn);
String url = "https://file-examples-com.github.io/uploads/2017/10/file_example_JPG_100kB.jpg";
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
pool.execute(new NetworkService(url));
}
});
网络服务class:
private class NetworkService implements Runnable {
private String url;
public NetworkService(String url) {
this.url = url;
}
@Override
public void run() {
dlFile(url);
}
private String dlFile(String surl) {
try {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(surl);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK)
return "Server returned HTTP " + connection.getResponseCode() + " " + connection.getResponseMessage();
input = connection.getInputStream();
String title = URLUtil.guessFileName(String.valueOf(url), null, null);
output = new FileOutputStream(Environment.getExternalStorageDirectory().toString() + "/" + title);
} catch (Exception e) {
return e.toString();
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
} finally {
}
return null;
}
}
有几件事你应该做并验证。
1 - 首先,确保您已授予将文件保存到存储器所需的权限。
- READ_EXTERNAL_STORAGE
- WRITE_EXTERNAL_STORAGE
- INTERNET
2 - 将 android:requestLegacyExternalStorage="true"
添加到 android 10 及更高版本的清单文件的应用程序标签中。
3 - 更正您的 FileOutputStream
初始化,因为
val direct = File(Environment.getExternalStorageDirectory().toString() + "/test_files")
您正在 test_files 文件夹中创建上面的路径,但在 FileOutputStream
中您指定了不同的路径。所以,正确的行应该是
output = FileOutputStream( direct + "/" + title)
最后,在 output =
行之后添加以下行以将图像写入缓冲区,因为您正在读取 InputStream
而不是将其写入缓冲区。这就是为什么它只在存储中创建路径,但不将文件写入该路径。
val buf = ByteArray(1024)
var len: Int
while (input.read(buf).also { len = it } > 0) {
output.write(buf, 0, len)
}
PS: 我用 Kotlin 写了代码并在 Android 10 上测试过,它工作正常.
希望对您有所帮助。如果对您有帮助,请不要忘记采纳。
我在执行程序服务中使用下面的代码从 URL 下载文件。它下载文件但大小为 0 字节。当我使用 asyncTask 时代码工作正常。但是当我把它放在执行程序服务中时不起作用。
下载无法完成的任何想法?
创建时:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ExecutorService pool = Executors.newSingleThreadExecutor();
Button btn = findViewById(R.id.btn);
String url = "https://file-examples-com.github.io/uploads/2017/10/file_example_JPG_100kB.jpg";
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
pool.execute(new NetworkService(url));
}
});
网络服务class:
private class NetworkService implements Runnable {
private String url;
public NetworkService(String url) {
this.url = url;
}
@Override
public void run() {
dlFile(url);
}
private String dlFile(String surl) {
try {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(surl);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK)
return "Server returned HTTP " + connection.getResponseCode() + " " + connection.getResponseMessage();
input = connection.getInputStream();
String title = URLUtil.guessFileName(String.valueOf(url), null, null);
output = new FileOutputStream(Environment.getExternalStorageDirectory().toString() + "/" + title);
} catch (Exception e) {
return e.toString();
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
} finally {
}
return null;
}
}
有几件事你应该做并验证。
1 - 首先,确保您已授予将文件保存到存储器所需的权限。
- READ_EXTERNAL_STORAGE
- WRITE_EXTERNAL_STORAGE
- INTERNET
2 - 将 android:requestLegacyExternalStorage="true"
添加到 android 10 及更高版本的清单文件的应用程序标签中。
3 - 更正您的 FileOutputStream
初始化,因为
val direct = File(Environment.getExternalStorageDirectory().toString() + "/test_files")
您正在 test_files 文件夹中创建上面的路径,但在 FileOutputStream
中您指定了不同的路径。所以,正确的行应该是
output = FileOutputStream( direct + "/" + title)
最后,在 output =
行之后添加以下行以将图像写入缓冲区,因为您正在读取 InputStream
而不是将其写入缓冲区。这就是为什么它只在存储中创建路径,但不将文件写入该路径。
val buf = ByteArray(1024)
var len: Int
while (input.read(buf).also { len = it } > 0) {
output.write(buf, 0, len)
}
PS: 我用 Kotlin 写了代码并在 Android 10 上测试过,它工作正常.
希望对您有所帮助。如果对您有帮助,请不要忘记采纳。