实例:下载服务器zip资源(Json,Png,多种文件)

Posted Chin_style

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实例:下载服务器zip资源(Json,Png,多种文件)相关的知识,希望对你有一定的参考价值。

一、前期基础知识储备

1)OKGO库地址:https://github.com/jeasonlzy/okhttp-OkGo

作者已停止维护,所以使用时需要在文档基础上,做必要的修改。

2)笔者用以下载服务器上一些简单的资源,比如Json,Png,这些资源都是打包成zip包的形式,尽量减小包体,便以传输。

3)由于是zip的形式传输,所以资源下载到本地之后,会有一个解压缩保存本地的过程,解压缩完毕得到对应资源后,需要删去zip包。

4)涉及到Json解析的时候,使用Gson库进行解析。

 

二、上代码,具体实现

1)引入依赖库

    def gsonVersion = "2.6.2"
    def okgoVersion = "3.0.4"
    implementation "com.google.code.gson:gson:$gsonVersion" // 解析Gson
    implementation "com.lzy.net:okgo:$okgoVersion" // 下载资源
    implementation "com.blankj:utilcode:1.25.9" // 万能工具库

2)初始化OKGO

public class ArtApp extends Application 

    @Override
    public void onCreate() 
        super.onCreate();
        if (isMainProcess()) 

            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            //全局的读取超时时间
            builder.readTimeout(30000L, TimeUnit.MILLISECONDS);
            //全局的写入超时时间
            builder.writeTimeout(30000L, TimeUnit.MILLISECONDS);
            //全局的连接超时时间
            builder.connectTimeout(100000L, TimeUnit.MILLISECONDS);
            builder.proxy(Proxy.NO_PROXY);
            builder.hostnameVerifier(new HostnameVerifier() 
                @Override
                public boolean verify(String hostname, SSLSession session) 
                    try 
                        if (TextUtils.isEmpty(hostname) || TextUtils.isEmpty(session.getPeerHost())) 
                            return false;
                        
                        return hostname.equals(session.getPeerHost());
                     catch (Exception e) 
                        return false;
                    
                
            );
            OkGo.getInstance().init(this).setOkHttpClient(builder.build()).setRetryCount(3);

        
    

    private String getCurrentProcessName() 
        int pid = android.os.Process.myPid();
        String processName = "";
        ActivityManager manager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningAppProcessInfo process : manager.getRunningAppProcesses()) 
            if (process.pid == pid) 
                processName = process.processName;
            
        
        return processName;
    

    public boolean isMainProcess() 
        return getApplicationContext().getPackageName().equals(getCurrentProcessName());
    

进入Android 29之后,OKGO需要补充一些声明,要不然会遇到一些 HostnameVerifier 错误;

3)Manifest文件中新增

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

    <application
        android:name=".ArtApp"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:requestLegacyExternalStorage="true"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:usesCleartextTraffic="true">
        ... ...
    </application>

①需要新增两项权限,后续需要了解网络状态,以做出不同的处理;

②处理不安全的网络访问,由于资源是放在“http”下,需要做下面处理,要不然访问不到;

android:requestLegacyExternalStorage="true"
android:usesCleartextTraffic="true"

4)下载一份放置Png的zip包

    private static final String URL = "http://121.40.46.187/ts_paint_color/texture_001_png.zip";
    private static final String FILENAME = "templatePng";

    onDownLoadAndSavePNG(URL, "texture_001_png");    
    
    /*下载填充用的纹理图片*/
    private void onDownLoadAndSavePNG(String pngUrl, final String fileName) 
        if (Utils.isNetWorkEnable(this)) 
            OkGo.<File>get(pngUrl)
                    .execute(new FileCallback(this.getExternalFilesDir(FILENAME).getAbsolutePath()
                            + File.separator, fileName + ".zip") 
                        @Override
                        public void onSuccess(com.lzy.okgo.model.Response<File> response) 
                            String zipFileName = getExternalFilesDir(FILENAME).getAbsolutePath()
                                    + File.separator + File.separator + fileName + ".zip";
                            String svgUnzipPath = ZipAndReadJsonUtils.unZipDownlaodSvgToSdCard(OkgoActivity.this, zipFileName);
                            txt.setText(svgUnzipPath);
                            File f = response.body();
                            if (f != null && f.exists()) 
                                Log.d(TAG, "onSuccess: file_Download success file exists 11,," + svgUnzipPath);
                                /*/storage/emulated/0/Android/data/camera.editor.art.paintsplash/files/templatePng/texture_001_png.zip*/
                                String jsonPath = getExternalFilesDir(FILENAME).getAbsolutePath() + File.separator + fileName;
                                Log.d(TAG, "onSuccess: file_Download success file exists 22,," + jsonPath);
                                /*/storage/emulated/0/Android/data/camera.editor.art.paintsplash/files/templatePng/texture_001_png*/
                            
                            // 下载完毕删除zip包资源
                            File zipFile = response.body();
                            if (zipFile != null && zipFile.exists()) 
                                zipFile.delete();
                            
                        

                        @Override
                        public void onError(Response<File> response) 
                            Log.d(TAG, "onError: file_Download file出错,," + response + ",," + response.body()
                                    + ",," + response.message() + ",," + response.getException() + ",," + response.isSuccessful());
                        

                        @Override
                        public void downloadProgress(Progress progress) 
                            
                        
                    );
         else 
            /*没有联网 下载出错 解析出错 都要初始化本地数据*/

        
    

1)excute方法中,定义好下载后的资源存储处,下载成功监听中再处理;

2)onSuccess方法中,拿到下载好zip的资源存储处地址,然后调用解压缩的方法进行处理;

3)解压缩的方法中,输入参数为“需要解压缩文件所在地址”,输出的参数为“解压缩后得到的文件地址”;

解压缩方法如下:

    public static String unZipDownlaodSvgToSdCard(Context context, String zipFileName) 
        String svgUnzipPath = "";
        File zipFile = new File(zipFileName);
        Log.d(TAG, "unZipDownlaodToSdCard: 需要解压缩文件所在地址," + zipFile.getAbsolutePath());
        String fileName = "";
        File saveJsonFile = context.getExternalFilesDir("templatePng");
        if (saveJsonFile != null) 
            fileName = saveJsonFile.getAbsolutePath();
        
        File file = new File(fileName);
        try 
            ZipUtils.unzipFile(zipFile, file);
            List<File> files = FileUtils.listFilesInDir(file);
            svgUnzipPath = files.get(0).getAbsolutePath();
            Log.d(TAG, "unZipDownlaodToSdCard: 解压缩后得到的文件地址," + files.get(0).getAbsolutePath());
         catch (IOException e) 
            Log.e(TAG, "unZipDownlaodSvgToSdCard: " + e.getMessage() );
            e.printStackTrace();
        
        return svgUnzipPath;
    

5)下载一份放置Json文件的zip包

下载解压缩部分如上,此外多加一步处理——解析下载好的Json文件:

    private JsonParser parser = new JsonParser();
    private static final String CATEGORY = "artphoto";
    private static final String CONTENT = "classic";
    private static final String VERSION = "version";

    /*下载Json文件*/
    private void onDownLoadAndSaveJson(String svgUrl, String fileName) 
        if (Utils.isNetWorkEnable(getActivity())) 
            OkGo.<File>get(svgUrl)
                    .execute(new FileCallback(getActivity().getExternalFilesDir("templateJson").getAbsolutePath()
                            + File.separator, fileName + ".zip") 
                        @Override
                        public void onSuccess(com.lzy.okgo.model.Response<File> response) 
                            String zipFileName = getActivity().getExternalFilesDir("templateJson").getAbsolutePath()
                                    + File.separator + File.separator + fileName + ".zip";
                            String svgUnzipPath = ZipAndReadJsonUtils.unZipDownlaodSvgToSdCard(getActivity(), zipFileName);
                            File f = response.body();
                            if (f != null && f.exists()) 
                                String jsonPath = getActivity().getExternalFilesDir("templateJson").getAbsolutePath() + File.separator + "templates.json";
                                String jsonText = Utils.jsonTransformFromFile(jsonPath);
                                JsonObject netRootObject = null;
                                List<StyleEntity> entities = LitePal.select("name").find(StyleEntity.class); /*只查询name这一列 其他字段为null*/
                                List<String> entitieNames = new ArrayList<>();
                                for (int i = 0; i < entities.size(); i++) 
                                    entitieNames.add(entities.get(i).getNmae());
                                
                                try 
                                    netRootObject = (JsonObject) parser.parse(jsonText);
                                    JsonObject netCategoryObject = netRootObject.getAsJsonObject(CATEGORY);
                                    JsonArray netJsonArray = netCategoryObject.getAsJsonArray(CONTENT);
                                    String netVersion = netCategoryObject.getAsJsonPrimitive(VERSION).getAsString();
                                    String localVersion = PreferenceManager.getDefaultSharedPreferences(getActivity()).getString("localVer", "0.0");
                                    if (!localVersion.equals(netVersion)) 
                                        if (netJsonArray != null && netJsonArray.size() > 0) 
                                            PreferenceManager.getDefaultSharedPreferences(getActivity()).edit().putString("localVer", netVersion).apply();
                                            for (int i = 0; i < netJsonArray.size(); i++) 
                                                JsonObject netObject = netJsonArray.get(i).getAsJsonObject();
                                                String name = netObject.get("name").getAsString();
                                                String index = netObject.get("index").getAsString();
                                                String selected = netObject.get("selected").getAsString();
                                                StyleEntity styleEntity = new StyleEntity(index, name, selected);
                                                if (!entitieNames.contains(name)) 
                                                    styleEntity.save();
                                                    styleList.add(styleEntity);
                                                
                                            
                                        
                                    
                                    initAdapter();
                                 catch (JsonSyntaxException e) 
                                    Log.e(TAG, "onSuccess: 解析出错," + e.getMessage());
                                    initAdapter();
                                
                            
                        

                        @Override
                        public void onError(Response<File> response) 
                            Log.d(TAG, "onError: file_Download file出错,," + response + ",," + response.body()
                                    + ",," + response.message() + ",," + response.getException() + ",," + response.isSuccessful());
                            initAdapter();
                        

                        @Override
                        public void downloadProgress(Progress progress) 
              
                        
                    );
         else 
            /*没有联网 下载出错 解析出错 都要初始化本地数据*/
            initAdapter();
        
    

①拿到解析后的Json文件地址,然后读取该地址的Json文件,得到String类型的数据源;

    /*将存储在本地Json文件读取出来*/
    public static String jsonTransformFromFile(String filePath) 
        File file = new File(filePath);
        StringBuilder stringBuilder = new StringBuilder();
        try 
            FileInputStream fileInputStream = new FileInputStream(file);
            BufferedReader bf = new BufferedReader(new InputStreamReader(fileInputStream));
            String line;
            while ((line = bf.readLine()) != null) 
                stringBuilder.append(line);
            
         catch (FileNotFoundException e) 
            e.printStackTrace();
         catch (IOException e) 
            e.printStackTrace();
        
        return stringBuilder.toString();
    

② 利用Gson库,将Json数据源按照字段,解析为一个个对象;

/**
 *     Json格式为:
 *         
 *     "artphoto": 
 *         "version": "1.0",
 *         "classic": [
 *             
 *                 "name": "Forest Air",
 *                 "index": "http://120.55.58.174/artphoto/style30.jpg",
 *                 "selected": "false"
 *             
 *                    ]
 *              
 *          
 */

        JsonObject netRootObject = null;
        netRootObject = (JsonObject) parser.parse(jsonText);
        JsonObject netCategoryObject = netRootObject.getAsJsonObject(CATEGORY);
        JsonArray netJsonArray = netCategoryObject.getAsJsonArray(CONTENT);
        String netVersion = netCategoryObject.getAsJsonPrimitive(VERSION).getAsString();

        if (netJsonArray != null && netJsonArray.size() > 0) 

            for (int i = 0; i < netJsonArray.size(); i++) 
                JsonObject netObject = netJsonArray.get(i).getAsJsonObject();
                String name = netObject.get("name").getAsString();
                String index = netObject.get("index").getAsString();
                String selected = netObject.get("selected").getAsString();
                StyleEntity styleEntity = new StyleEntity(index, name, selected);
                if (!entitieNames.contains(name)) 
                    styleEntity.save();
                    styleList.add(styleEntity);
                
            
        

补充一个判断网络状态的工具类方法:

    public static boolean isNetWorkEnable(Context context) 
        if (context != null) 
            ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo info = manager.getActiveNetworkInfo();
            if (info != null) 
                return info.isAvailable();
             else 
                return false;
            
        
        return false;
    

6)添加混淆

#okhttp
-dontwarn okhttp3.**
-keep class okhttp3.***;

#okio
-dontwarn okio.**
-keep class okio.***;


# gson
-keepattributes Signature
-keepattributes *Annotation*
-keep class sun.misc.Unsafe  *; 

 

结语:笔者OKGO用久了,顺手。不过现在有更高效的联网下载网络资源的方法,之后再更新。

 

 

以上是关于实例:下载服务器zip资源(Json,Png,多种文件)的主要内容,如果未能解决你的问题,请参考以下文章

按需资源是不是允许存档文件?

下载的两种方式

cURL下载Zip文件 - “参数不是有效的文件句柄资源”

thinkphp 使用http扩展类 下载png等图片格式文件正常,但是下载doc,zip等文件时没有后缀

如何打包Activiti的流程资源文件

将文件从 Zip 保存到特定文件夹