android/NDK开发assets资源中文名打包问题

本文介绍了一种将C项目资源打包并解压至Android设备SD卡的方法,通过将资源压缩为ZIP文件放置于assets目录下,在程序启动时进行解压,解决了资源无法随APK一同安装的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目是C开发的能在android跑了,最近想把项目打包上传googleplay碰到一个问题资源图片没办法打包,原先我的图片资源都是直接拷贝到SDcard一个文件夹下的,C代码层直接访问SDcard的资源图片就OK了 ,安装过程好麻烦图片资源要手动拷贝到sdcard上。
这问题纠结了好久 
本想把资源放到res目录下的,但是资源有图片 ini配置档之类的文件C代码层访问这个目录也是问题。
放到这个assets文件呢? 测试过这个目录不支持中文名字,由于项目的资源都是中文命名的,改成英文工作量大也影响其他人的修改。
后来发现把资源压缩成zip能放到assets目录下,太高兴了问题能解决了。
解决方案:
把资源打包成zip 放入assets目录下,当程序启动的时候把zip解压到sdcard目录下,这样C层代码能直接访问sdcard下的资源包了。


解压的代码:
Test.java: //判断资源是否需要安装,需要跳转到安装页面


public class Test extends Activity {
    super.onCreate(savedInstanceState);
        JmpPage();


}
private void JmpPage(){
        String path = android.os.Environment.getExternalStorageDirectory() + "/Test";
        String ZipPath = android.os.Environment.getExternalStorageDirectory() + "/Test.zip";
        
         long length = 28;//Test 文件大小 设置比原文件夹小
       //判断是否有SDcard
        if(android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)){
       	File file = new File(path);
       	long FileSize = 0;
       	
       	if(file.exists())
       	{
       	  FileSize = GetFileSize(new File(path))/(1024*1024); //获取SDcard剩余容量
       	  Log.v("Test","FileSize:"+FileSize);
       	}
       	
       	file = new File(ZipPath);//删除zip
       	if(file.exists()){
       		file.delete();
       	}
       	if(FileSize < length){//如果资源包小于37M数据包不完整
       		if(GetAvailableSdcard() > (length+4))//sdcard内存需要大于39M才可以安装资源
       		{
       		  Intent intent = new Intent(Test.this, InstallActivity.class); //跳转到解压页面
                  intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
                  startActivity(intent);
       		}
       		else
       		{
       			Toast.makeText(Test.this, "sdcard容量满了,请删除一些!", 1).show();
       		}
       	}
       	Log.v("Test","FileSize > length");
       }
       else{
       	
       	Toast.makeText(Test.this, "未找到sdcard无法安装程序!", 1).show();
       }
	} 
	
	private long GetAvailableSdcard()
	{
		android.os.Environment.getExternalStorageDirectory();
		StatFs statFs = new StatFs(android.os.Environment.getExternalStorageDirectory().toString());


       // 获取block的SIZE
       long BlockSize = statFs.getBlockSize();
       // 可使用的Block的数量
       long AvailaBlock = statFs.getAvailableBlocks();
       long AvailableSize = AvailaBlock * BlockSize;
       return AvailableSize;
	}
	
	//获取文件夹大小
	private long GetFileSize(File file){
		long result = 0;
		
		 File[] filelist=file.listFiles();
		 for(int i = 0; i < filelist.length; i++) {
		        
		        if(filelist[i].isDirectory()) {
		            result += GetFileSize(filelist[i]);
		        } else {
		            result += filelist[i].length();
		        }
		    }
		    return result;
	}
InstallActivity.java //解压zip
package com.Test;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;




import com.Test.R;




import android.app.Activity;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;




public class InstallActivity extends Activity {
 
	    final private int ZipFileMax = 29965053;//文件夹大小
	    private int UnZipSize;
	    private ProgressBar progressbar;
	    private TextView    showtext;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.install);
		progressbar = (ProgressBar)findViewById(R.id.progressBar1);
        showtext    = (TextView)findViewById(R.id.textView1);
        
        
        
        final String ZipFileName = android.os.Environment.getExternalStorageDirectory() + "/Test.zip";  
        final String UnZipLocation = android.os.Environment.getExternalStorageDirectory() + "/"; 
       
        
        new Thread(){
            public void run(){
            
              CopyAssets();
             
              
              Log.e("Test",ZipFileName);
              Decompression dec = new Decompression(ZipFileName, UnZipLocation);  
              dec.UnZip(); 
              File file = new File(ZipFileName);//zipFilename
              
              if(file.exists()){
            	  file.delete();
              }
              UpdateProgress(2);
              try {
				sleep(2000);
			   finish();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
             




        	}
        }.start();
	}




	private Handler handler = new Handler(){
		  @Override
		  public void handleMessage(Message msg){
			  if(!Thread.currentThread().isInterrupted()){
				  switch(msg.what){
				  
				  case 0:
					  progressbar.setMax(ZipFileMax);
					  break;
				  case 1:
					  progressbar.setProgress(UnZipSize);
					 // int n = (UnZipSize*100)/ZipFileMax;
					  //Log.v("Test","百分比:"+n+"%");
					  //showtext.setText(n);
					  break;
				  case 2:
					  //Toast.makeText(GetNumberActivity.this, "安装完毕", 1).show();
					  showtext.setText("安装完毕,请重新启动程序进入!");
					  break;
				  case 3:
					  showtext.setText("配置系统中。。。");
				  case -1:
					  //String error = msg.getData().getString("error");
			          // Toast.makeText(InstallActivity.this, error, 1).show();
					  break;
				  }
			  }
		  super.handleMessage(msg);
		  }
		};
		private void UpdateProgress(int type)
		{
		    Message msg = new Message();
		    msg.what = type;
		    handler.sendMessage(msg);
		}
		public String getSDPath(){ 
			File sdDir = null; 
			boolean sdCardExist = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED); //判断sd卡是否存在 
			if (sdCardExist) 
			{ 
			  sdDir =android.os.Environment.getExternalStorageDirectory();//获取跟目录 
			} 
			return sdDir.toString(); 
		}




		public class Decompression {  
			  private String ZipFile;  
			  private String Location;  
			 
			  public Decompression(String zipFile, String location) {  
			    ZipFile = zipFile;  
			    Location = location;  
			 
			    _dirChecker("");  
			  }  
			 
			  public void UnZip() {  
			    try  {  
			      BufferedInputStream fin = new BufferedInputStream(new FileInputStream(ZipFile));  
			      ZipInputStream zin = new ZipInputStream(fin);  
			      ZipEntry ze = null;
			      byte[] buf = new byte[1024];
			      int n= 0;
			      int len = 0;
			      
			     // ZipFileMax = 52272746;//zin.available();
			      Log.v("Test","ZipFileMax:"+ZipFileMax);
			      UpdateProgress(0);
			      
			      while ((ze = zin.getNextEntry()) != null) {  
			       // Log.v("Test", "pacth:" + ze.getName());  
			       // Log.v("Test","Len:"+ze.getSize());
			       // Log.v("Test","Time:"+ze.getTime());
			 
			        if(ze.isDirectory()) {  
			          _dirChecker(ze.getName());  
			        } else {  
			        BufferedOutputStream fout = new BufferedOutputStream(new FileOutputStream(Location + ze.getName()));  
			      
			        
			       while((n = zin.read(buf,0,1024))> 0)
			        	 {
			        	   
			        	   fout.write(buf,0,n);
			        	   UnZipSize += n;
			        	   UpdateProgress(1);
			        	 }
			 
			          zin.closeEntry();  
			          fout.close();  
			        }  
			        
			      }  
			     
			      zin.close();  
			    } catch(Exception e) {  
			      Log.e("Test", "unzip", e);  
			    }  
			 
			  }  
			 
			  private void _dirChecker(String dir) {  
			  File f = new File(Location + dir);  
			 
			    if(!f.isDirectory()) {  
			      f.mkdirs();  
			    }  
			  }  
	   } 
		
		
		private void CopyAssets() { 
		    AssetManager assetManager = getAssets(); 
		    String[] files = null; 
		    try { 
		        files = assetManager.list(""); 
		    } catch (IOException e) { 
		        Log.e("Test", e.getMessage()); 
		    } 
		    UpdateProgress(3);
		    for(String filename : files) { 
		        InputStream in = null; 
		        OutputStream out = null; 
		        try { 
		          in = assetManager.open(filename); 
		          out = new FileOutputStream(android.os.Environment.getExternalStorageDirectory()+"/" + filename); 
		          CopyFile(in, out); 
		          in.close(); 
		          in = null; 
		          out.flush(); 
		          out.close(); 
		          out = null; 
		        } catch(Exception e) { 
		            Log.e("Test", e.getMessage()); 
		        }        
		    } 
		} 
		private void CopyFile(InputStream in, OutputStream out) throws IOException { 
		    byte[] buf = new byte[1024]; 
		    int n; 
		    
		    BufferedInputStream fin = new BufferedInputStream(in);
		    BufferedOutputStream fout = new BufferedOutputStream(out);
		    while((n = fin.read(buf)) != -1){ 
		      fout.write(buf, 0, n); 
		    } 
		} 
}


AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.Test"
      android:versionCode="20120417"
      android:versionName="1.0">
      <uses-sdk android:minSdkVersion="4" />
    <uses-permission android:name="android.permission.RESTART_PACKAGES"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_OWNER_DATA"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" /> 
    <application android:label="@string/app_name" android:icon="@drawable/icon" android:debuggable="true"
    android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
        <activity android:name=".Test"
                  android:label="@string/app_name"
                  android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
                  android:launchMode="singleTask" android:screenOrientation="landscape"> 
                  <!--android:launchMode="singleTask" android:screenOrientation="portrait"  -->        
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
         <activity android:name="com.Test.InstallActivity" android:label="@string/app_name"
              android:screenOrientation="portrait">
        </activity>
    </application>
</manifest> 




这有个很严重问题apk会很大,而且apk卸载了sdcard中的文件不会自动删除希望各位同仁提供方法。
上面代码有部分参考其他人的,本人一直玩C刚学java不久,相信也有人遇到同样的问题拿出来分享一下,如果有更好的方法希望可以交流交流。







评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值