从 url 将图像保存到 SD 卡会在 android 中引发 NetworkOnmainThread 异常
Save image to SD card from url throws NetworkOnmainThread Exception in android
我是 Android 编程新手,正在开发一个应用程序,我想在用户点击按钮时将图像从 URL 存储到 SD 卡。
我找到了一个方法并使用了它,但它抛出 NetworkOnMainThread
异常导致应用程序崩溃。我做错了什么?
这是我的代码:
void DownloadPost(){
try
{
URL url = new URL( mPost.postImagePath);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.connect();
File SDCardRoot = Environment.getExternalStorageDirectory().getAbsoluteFile();
String filename="downloadedFile.png";
Log.i("Local filename:",""+filename);
File file = new File(SDCardRoot,filename);
if(file.createNewFile())
{
file.createNewFile();
}
FileOutputStream fileOutput = new FileOutputStream(file);
InputStream inputStream = urlConnection.getInputStream();
int totalSize = urlConnection.getContentLength();
int downloadedSize = 0;
byte[] buffer = new byte[1024];
int bufferLength = 0;
while ( (bufferLength = inputStream.read(buffer)) > 0 )
{
fileOutput.write(buffer, 0, bufferLength);
downloadedSize += bufferLength;
Log.i("Progress:","downloadedSize:"+downloadedSize+"totalSize:"+ totalSize) ;
}
fileOutput.close();
Toast.makeText(PostListItem.this.getContext(),"Post saved to gallery",Toast.LENGTH_SHORT).show();
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
catch (IOException e)
{
// filepath=null;
e.printStackTrace();
}
// Log.i("filepath:"," "+filepath) ;
}
实际上您是从主线程调用 DownloadPost
,例如 onCreate 或 onResume
。创建一个 AsyncTask 并从 doInBackGround
方法调用 DownloadPost
方法。
Android 不允许来自主线程的任何网络操作,因为您必须从后台调用它。
希望对您有所帮助。
你不能运行网络请求主线程。
AsyncTask asyncTask=new AsyncTask() {
@Override
protected Object doInBackground(Object[] params) {
DownloadPost();
}
};
asyncTask.execute();
或使用线程:
Thread thread = new Thread(new Runnable()
{
@Override
public void run()
{
try
{
DownloadPost();
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
thread.start();
应用程序试图在其主线程上执行网络操作时抛出的异常。
这仅针对针对 Honeycomb SDK 或更高版本的应用程序抛出。允许针对早期 SDK 版本的应用程序在其主事件循环线程上进行联网,但强烈建议不要这样做。请参阅文档 Designing for Responsiveness
另见 StrictMode。
您应该使用 AsyncTask:
AsyncTask<Void, Void, Boolean> asyncTask = new AsyncTask<Void, Void, Boolean>() {
@Override
protected Boolean doInBackground(Void... params) {
return DownloadPost();
}
@Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
if (aBoolean)
// UI Positive feedback
else
// UI Negative feedback
}
};
确保 Download() return 一个布尔结果来管理 onPostExecute() 中的反馈。
doInBackground()
到业务逻辑(不是 UI),onPostExecute()
在 UI 线程上工作
我是 Android 编程新手,正在开发一个应用程序,我想在用户点击按钮时将图像从 URL 存储到 SD 卡。
我找到了一个方法并使用了它,但它抛出 NetworkOnMainThread
异常导致应用程序崩溃。我做错了什么?
这是我的代码:
void DownloadPost(){
try
{
URL url = new URL( mPost.postImagePath);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.connect();
File SDCardRoot = Environment.getExternalStorageDirectory().getAbsoluteFile();
String filename="downloadedFile.png";
Log.i("Local filename:",""+filename);
File file = new File(SDCardRoot,filename);
if(file.createNewFile())
{
file.createNewFile();
}
FileOutputStream fileOutput = new FileOutputStream(file);
InputStream inputStream = urlConnection.getInputStream();
int totalSize = urlConnection.getContentLength();
int downloadedSize = 0;
byte[] buffer = new byte[1024];
int bufferLength = 0;
while ( (bufferLength = inputStream.read(buffer)) > 0 )
{
fileOutput.write(buffer, 0, bufferLength);
downloadedSize += bufferLength;
Log.i("Progress:","downloadedSize:"+downloadedSize+"totalSize:"+ totalSize) ;
}
fileOutput.close();
Toast.makeText(PostListItem.this.getContext(),"Post saved to gallery",Toast.LENGTH_SHORT).show();
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
catch (IOException e)
{
// filepath=null;
e.printStackTrace();
}
// Log.i("filepath:"," "+filepath) ;
}
实际上您是从主线程调用 DownloadPost
,例如 onCreate 或 onResume
。创建一个 AsyncTask 并从 doInBackGround
方法调用 DownloadPost
方法。
Android 不允许来自主线程的任何网络操作,因为您必须从后台调用它。
希望对您有所帮助。
你不能运行网络请求主线程。
AsyncTask asyncTask=new AsyncTask() {
@Override
protected Object doInBackground(Object[] params) {
DownloadPost();
}
};
asyncTask.execute();
或使用线程:
Thread thread = new Thread(new Runnable()
{
@Override
public void run()
{
try
{
DownloadPost();
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
thread.start();
应用程序试图在其主线程上执行网络操作时抛出的异常。
这仅针对针对 Honeycomb SDK 或更高版本的应用程序抛出。允许针对早期 SDK 版本的应用程序在其主事件循环线程上进行联网,但强烈建议不要这样做。请参阅文档 Designing for Responsiveness
另见 StrictMode。
您应该使用 AsyncTask:
AsyncTask<Void, Void, Boolean> asyncTask = new AsyncTask<Void, Void, Boolean>() {
@Override
protected Boolean doInBackground(Void... params) {
return DownloadPost();
}
@Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
if (aBoolean)
// UI Positive feedback
else
// UI Negative feedback
}
};
确保 Download() return 一个布尔结果来管理 onPostExecute() 中的反馈。
doInBackground()
到业务逻辑(不是 UI),onPostExecute()
在 UI 线程上工作