读写SDCard

Android高版本不能使用http协议,需要在清单文件中添加(application内)

android:usesCleartextTraffic="true"
<!--这个属性用于指示应用是否允许使用明文网络流量,即未加密的网络请求,比如 HTTP 请求。-->

在清单文件里面申请使用网络权限、读SD卡的权限、写SD卡的权限、管理SD卡的权限

<uses-permission android:name="android.permisson.INTERNET"></uses-permission>
<uses-permission android:name="android.permisson.READ_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permisson.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permisson.MANAGE_EXTERNAL_STORAGE"></uses-permission>

MainActivity.java,部分代码

public class MainActivity extends AppCompatActivity
{
TextView tv = findViewById(R.id.tv_downloadResult);
tv.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
DownloadZip downloadZip = new DownloadZip(tv);
downloadZip.execute("http:192.168.31.197/down/test/zip");
}
});
findViedById(R.id.btn_startUnzip).setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick((View view))
{
UnzipFile unzipFile = new UnzipFile(tv);
unzipFile.execute("");
}
});
}

DownloadZip.java

public class DownloadZip extends AsyncTask<String,String,String>
{
//AsyncTask是一个用于在后台线程中执行耗时操作(如网络请求、文件读写等)的类,同时允许你在操作完成后更新UI
//Params(第一个String):这是传递给execute()方法的参数的类型
//Progress(第二个String):这是onProgressUpdate()方法接收的进度更新信息的类型。
//Result(第三个String):这是doInBackground()方法执行完成后返回的结果的类型。
private TextView tv;
private String ret = "";
public DownloadZip(TextView ptv)
{
tv = ptv;
}
@Override
protected String doInBackground(String...String)
{
//doInBackground 方法是 AsyncTask 类中的一个关键方法,用于执行那些应该在后台线程中运行的耗时操作。
HttpURLConnection httpURLConnection = null;
//HttpURLConnection 是 Java 标准库中的一个类,用于处理 HTTP 请求和响应。它是 URLConnection 的一个子类,专门用于 HTTP 通信。
InputStream inputStream = null;
//InputStream 是 Java 中的一个抽象类,用于表示字节输入流的所有类的超类。在文件下载的场景中,InputStream 用于从 HTTP 响应中读取数据。
FileOutputStream outputStreamToFile = null;
//FileOutputStream 是 Java 标准库中的一个类,用于向文件写入数据。
try
{
URL url = new URL(string[0]);
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.connect();
if(httpURLConnection.getResponseCode != HttpURLConnection.HTTP_OK)
{
Log.d("DownloadZip","nor error code" + httpURLConnection.getResponseCode());
return "code error";
}
inputStream = httpURLConnection.getInputStream();

File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS+"/"+"zipSaveDir/");
if(!dir.exists())
{
dir.mkdir
}
String fullFilePath = dir + "/" +"2058.zip";
File file = new File(fullFilePath);
if(file.exists)
{
file.delete();
}
file.createNewFile();
outputStreamToFile = new File(file.getAbsolutePath);
byte[] buffer = new byte[1024];
int count;
while(true)
{
count = inputStream.read(buffer);
if(count == -1)
{
break;
}
outputStreamFile.write(buffer,0,count);
}
outputStreamToFile.close();
ret = "success";

}catch(Exception ee)
{
ee.printStackTrace();
ret = "fail";
}finally
{
try
{
if(inputStream !=null)
{
inputStream.close();
}
if(httpURLConnection !=null)
{
httpURLConnection.disconnect();
}
}catch(Exception ee)
{
ee.pringStackTrace;
}
}
return ret;
}
@Override
protected void onPostExecute(String s)
{
super.onPostExecute(s);
if(s.equals("success"))
{
tv.setText("下载success");
}
else
{
tv.setText("下载failed");
}
//rotected void onPostExecute(String s) 是一个通常在AsyncTask中重写的方法,用于在后台任务执行完毕后(即doInBackground方法完成后)在主线程(UI线程)上执行的操作。这里的参数String s是doInBackground方法返回的结果
}
}

UnzipFile.java

public class UnzipFile extends AsyncTask<String, String, String>
{
private String ret = "";
public UnzipFile(TextView ptv)
{
tv = ptv;
}
@Override
protected String doInBackground(String...strings)
{
InputStream inputStream = null;
ZipInputStream zipInputStream = null;
OutputStream outputStream = null;
try
{
File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS + "/" +"zipSaveDir/");
String fullFilePath = dir + "/" +"2058.zip";
File file = new File(fullFilePath);
if(file.exists())
{
String jieyaDir = dir.getAbsolutePath();
inputStream = new FileInputStream(file);
zipInputStream = new ZipInputStream(new BufferedInputStream(inputStream));
//这是ZipInputStream类型的一个变量,用于引用新创建的ZipInputStream对象。之后,你可以使用这个变量来读取ZIP文件中的内容。
byte[] buffer = new byte[1024];
ZipEntry zipEntry;
while((zipEntry = zipInputStream.getNextEntry())!=null)
{
String fileName = zipEntry.getName();
if(zipEntry.isDirectory())
{
File subDir = new File(jieyaDir + "/" + fileName);
subDir.mkdirs();
continue;
}
int rCount;
FileOutputStream fout = new FileOutputStream(jieyaDir + "/"+ fileName);
while((rCount = zipInputStream.read(buffer))!=-1)
{
fout.write(buffer,0,rCount);
}
fout.close();
zipInputStream.closeEntry();
}
zipInputStream.close();
ret = "unzip success";
}else
{
ret = "file not exists";
}

}catch(Exception ee)
{
ee.printStackTrace();
}
return ret;
@Overrride
protected void onPostExecute(String s)
{
super.onPostExecute(s);
}
if(s.equals("unzip success"))
{
tv.setText("解压成功");
}
else
{
tv.setText("解压失败");
}
}
}

Handler

MainActivity,部分代码

public class MainActivity extends AppCompatActivity
{
private MyHandler myHandler;
TextView tv;
public void updateUI01()
{
tv.setText("01");
}
public void updateUI02()
{
tv.setText("02");
}
public void updateUI03()
{
tv.setText("03");
}
@Override
protected void onCreate(Bundle saveInstanceState)
{
super.onCreate(savaInstanceState);
setContentView(R.layout.activity_main);
SubThreadCreateHandler subThread = new SubThreadCreateHandler();
subThread.start();
myHandler = new MyHandler(this);
//Handler handler = new Handler(Looper.getMainLooper()){}
//Looper.getMainLooper() 是用来获取主线程的消息循环器(Looper)的静态方法。如果不显式指定消息循环器,它会默认获取主线程的消息循环器。
SubThreadCreateHandler subThread = new SubThreadCreateHandler();
subThread.start();
//子线程用sendMessage给主线程发消息
MyThread myThread = new MyThread(myHandler);
myThread.start();
//子线程用post给主线程发消息
myHandler.post(new Runnable)()
{
@Override
public void run()
{
for(int i=0;i<5;i++)
{
try
{
Thread.sleep(2000);
}
catch(InterruptedException e)
{
e.printStackTrace;
}
updateUI01();
updateUI02();
tv.setText("i:"+i);
}
//使用 Handler 中的 post 方法,将一个 Runnable 对象提交到 Handler 所关联的消息队列中执行
//这里的 myHandler 是一个 Handler 对象,通过 post 方法,将一个 Runnable 对象提交到 Handler 所关联的消息队列中。这个 Runnable 对象的 run 方法将会在主线程中执行
}
}
//主线程做完事情后,把结果通过子线程的handler发送给子线程使用
Message message = Message.obtain();
message.what = 99;
Bundle bundle = new Bunlde();
bundle.putString("key1","这条内容先放入Bundle,然后通过Messsage传递");
message.setData(bundle);
subThred.subHandler.sendMessage(meassage);
}
}

MyHandler

public class MyHandler(MainActivity pMainActivity)
{
mainActivity = pMainActivity;
}
@Override
public void handleMessage(@NoNull Message msg)
{
super.handleMessage(msg);
Log.i("qqqqqqqq","in handleMessage");
switch(msg.what)
{
case 1:
{
mainActivity.updateUI01();
}
case 2:
{
mainActivity.updateUI02();
}
case 3:
{
mianActivity.updateUI03();
}
}
}

MyThread.java

public class MyThread extends Thread
{
private MyHandler mh;
public MyThread(MyHandler mh)
{
this.mh = mh;
}
@Override
public void run()
{
super.run();
for(int i = 0;i<5;i++)
{
try
{
Thread.sleep(200);
}catch(InterruptedException e)
{
e.printStackTrace;
}
Message message = Message.obtain();//这里创建Message对象是用.obtain();
message.what = i;
mh.sendMessage(message);
}
}
}

SubThreadCreateHandler.java

public class SubThreadCreateHandler extends Thread
{
public SubHandler subHandler;
public class SubHandler extends Handler
{
public class SubHandler (Looper myLooper){}
@Override
public void handleMessage(@NonNull Message msg)
{
super.handleMessage(msg);
Log.i("qqqqqqqq","in subHandler");
Bundle data = msg.getData();
Log.i("qqqqqqqq","get String:"+data.getString("key1"));
}
@Override
public void run()
{
super.run();
Looper.prepare();//Looper.prepare() 方法用于为当前线程创建一个消息循环器(Looper)
subHandler = new SubHandler(Looper.myLooper());
//subHandler 是一个 SubHandler 对象,通过 new SubHandler(Looper.myLooper()) 创建。这里的 Looper.myLooper() 表示获取当前线程的消息循环器,然后将其作为参数传递给 SubHandler 的构造函数。
Looper.loop();//Looper.loop() 是一个无限循环,它开始运行消息循环。


}
}
}