android asset

2019-08-14 12:42:58 weixin_43017662 阅读数 258

今天在Unity的安卓平台打包时,莫名打包失败,报的错误为

CommandInvokationFailure:Android Asset Packaging Tool Failed

如下图:
报错搜到一篇博客:Android Asset Packaging Tool Failed解决方法,博客中的评论解决了这个问题,原来是因为StreamAssets路径下不能含有带有中文字符文件名的文件。
删除掉这些文件或者将文件名中的中文字符改成英文即可。

2018-06-14 20:41:10 LIXIAONA_1101 阅读数 5320

资源分为两种:

    第一种:res目录下的资源(该资源不会被编译,但是会生成id)

    第二种:Assets文件夹下的资源文件,又叫原始资源文件(不会被编译,也不会生成id)

如何创建Assest文件夹

可以直接把资源复制粘贴到该文件夹下

实现访问Assets文件夹里面的资源:

一,获取Assets文件夹的管理类


二,便利文件夹下的资源列表:


三,Assets的绝对路径


四.获取Assets文件夹的文本


五,获取Assets文件夹下的网页(红方框里面放的是网页名称)


效果展示:

点击按钮:


这个就是刚才的double.xml

六,获取Assets文件夹下的图片


效果展示:


点击按钮:哈哈哈哈嗝~


七,获取Assets文件夹下的音频



2018-12-24 11:02:48 crazyZhangxl 阅读数 1268

记录下assetManager的简要使用。

1.列出assets目录下所有文件

    private void showAssetList(){
        AssetManager assetManager = getResources().getAssets();
        try {
            String[] lists = assetManager.list("zxl");
            for (String fileName:lists){
                Log.e("asset文件",fileName );
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

 

如上图所展示,我们可通过 fileName.concat(".") 来判定此文件是 文件夹(directory)还是文件(file) 。但该案例还没有打印出所有文件,下面我们就来实现迭代打印该文件夹下的所有文件

    private void showAssetList(String fileAssetName){
        AssetManager assetManager = getResources().getAssets();
        try {
            String[] lists = assetManager.list(fileAssetName);
            for (String fileName:lists){
                if (fileName.contains(".")){
                    // 文件
                    Log.e("asset","文件名路径  = "+fileAssetName+File.separator+fileName+"\n");
                }else {
                    Log.e("asset","文件夹路径  = "+fileAssetName+File.separator+fileName+"\n");
                    showAssetList(fileAssetName+File.separator+fileName);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 E/asset: 文件名路径  = zxl/1.txt
 E/asset: 文件夹路径  = zxl/l
 E/asset: 文件名路径  = zxl/l/hehe.txt
 E/asset: 文件夹路径  = zxl/x
 E/asset: 文件名路径  = zxl/x/haha.txt
 E/asset: 文件夹路径  = zxl/z
 E/asset: 文件名路径  = zxl/z/wuwu.txt

 打印文件txt内容

    private void showContent(String fileName) {
        InputStream inputStream = null;
        BufferedReader bufferedReader = null;
        String line = null;
        AssetManager assetManager = getResources().getAssets();
        try {
            inputStream = assetManager.open(fileName);
            bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            while ((line = bufferedReader.readLine()) != null) {
                Log.e("数据打印", line+"");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 E/数据打印: 哦哦 加油
 E/数据打印: 你是谁
 E/数据打印: 我是开发者
 E/数据打印: 哦哦 你好

2.sax解析asset下的xml文件<规范数据>

 数据源----

<?xml version="1.0" encoding="utf-8"?>
<!-- 测试数据-->
<data>
    <person>
        <name>小张</name>
        <age>18</age>
        <sex>男</sex>
    </person>

    <person>
        <name>小力</name>
        <age>15</age>
        <sex>男</sex>
    </person>

    <person>
        <name>小丽</name>
        <age>17</age>
        <sex>女</sex>
    </person>
</data>

具体解析过程,中间含详细的说明

调用:ParseDataManager.getInstance().parseData(MainActivity.this);

public class ParseDataManager {
    private static final String TAG = "ParseDataManager";
    private String assetPath = "person.xml";
    private static final int NODE_NAME = 1;
    private static final int NODE_AGE = 2;
    private static final int NODE_SEX = 3;
    private Person mPerson;
    private  List<Person> mDefaultEntries = new ArrayList<>();
    private int mCurrentState = 0;
    private ParseDataManager(){}

    public static ParseDataManager getInstance(){
        return ParseDataManagerHolder.MINATANCE;
    }

    private static class ParseDataManagerHolder{
        private static final ParseDataManager MINATANCE = new ParseDataManager();
    }

    public  void parseData(Context context){
        new EntryLoad().load(context,assetPath);
        if (mDefaultEntries != null){
            for (Person person:mDefaultEntries){
                Log.e(TAG, person.toString());
            }
        }
    }
    
    // sax解析必须实现的类
    private class EntryLoad extends DefaultHandler{

        public void load(Context context,String assetPath){
            InputStream is = null;
            try {
                // 打开待解析文件 获得文件流
                is = context.getAssets().open(assetPath);
                // 对绑定的handler进行解析
                Xml.parse(is,Xml.Encoding.UTF_8,this);
            } catch (IOException e) {
                e.printStackTrace();
            }catch (SAXException e) {
                e.printStackTrace();
            }finally {
                if (is != null){
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        /**
         * xml解析开始 ------ 只会调用一次
         * @throws SAXException
         */
        @Override
        public void startDocument() throws SAXException {
            super.startDocument();
            Log.e(TAG, "startDocument:开始解析");
        }

        /**
         * xml解析结束 ------- 只会调用一次
         * @throws SAXException
         */
        @Override
        public void endDocument() throws SAXException {
            super.endDocument();
            Log.e(TAG, "endDocument:结束解析 ");
        }

        /**
         * 检测节点开始 <....>
         */
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            super.startElement(uri, localName, qName, attributes);
            Log.e(TAG, "startElement: 处理节点 = "+localName);
            if ("data".equals(localName)){
                mCurrentState = 0;
                return;
            }

            if ("person".equals(localName)){
                mPerson = new Person();
                return;
            }

            if ("name".equals(localName)){
                mCurrentState = NODE_NAME;
                return;
            }

            if ("age".equals(localName)){
                mCurrentState = NODE_AGE;
                return;
            }

            if ("sex".equals(localName)){
                mCurrentState = NODE_SEX;
                return;
            }

            mCurrentState = 0;
        }

        /**
         * 检测节点结束  </....>
         */
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            super.endElement(uri, localName, qName);
            Log.e(TAG, "endElement: ----------");
            if ("person".equals(localName)){
                mDefaultEntries.add(mPerson);
            }
        }

        /**
         * 节点中的文本信息
         */
        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            super.characters(ch, start, length);
            String value = new String(ch, start, length);
            Log.e(TAG, "characters 文本 = "+value);
            switch (mCurrentState){
                case NODE_NAME:
                    mPerson.setName(value);
                    break;
                case NODE_AGE:
                    mPerson.setAge(Integer.parseInt(value));
                    break;
                case NODE_SEX:
                    mPerson.setSex(value);
                    break;
                    default:
                        break;
            }
            mCurrentState = 0;
        }
    }
}

解析数据log日志 

startDocument:开始解析
startElement: 处理节点 = data
characters 文本 = 
characters 文本 =     
startElement: 处理节点 = person ****(所以在这里检测节点 新建person对象)
characters 文本 = 
characters 文本 =         
startElement: 处理节点 = name
characters 文本 = 小张
endElement: ----------  ***(</...> 指代的是一个节点的结束标志)
characters 文本 = 
characters 文本 =         
startElement: 处理节点 = age
characters 文本 = 18
endElement: ----------
characters 文本 = 
characters 文本 =         
startElement: 处理节点 = sex
characters 文本 = 男
endElement: ----------
characters 文本 = 
characters 文本 =     
endElement: ------- (*****当结束节点的标志是person时,说明是有效数据 就加入缓存****)
characters 文本 = 
characters 文本 = 
characters 文本 =     
startElement: 处理节点 = person
characters 文本 = 
characters 文本 =         
startElement: 处理节点 = name
characters 文本 = 小力
endElement: ----------
...
characters 文本 = 
characters 文本 =     
endElement: ----------
characters 文本 = 
endElement: ----------
endDocument:结束解析 
name = 小张 age = 18 sex = 男
name = 小力 age = 15 sex = 男
name = 小丽 age = 17 sex = 女

3.利用属性来进行解析<自定义数据>

案例2的解析是比较常规的,通过检测节点开始初始化对象,在character中设置属性结果,在节点结束标记判断来缓存对象数据,正常来说我们应该多熟悉和掌握,下面将介绍一种通过属性来解析缓存数据的方式

//数据源
<?xml version="1.0" encoding="utf-8"?>
<data>
    <person name="小张" age="18" sex="男" />
    <person name="小李" age="13" sex="女"/>
    <person name="小王" age="12" sex="男"/>
    <person name="小白" age="15" sex="女"/>
</data>


//结果
name = 小张 age = 18 sex = 男
name = 小李 age = 13 sex = 女
name = 小王 age = 12 sex = 男
name = 小白 age = 15 sex = 女

主体和案例2一致,主要通过获取属性值然后再添加入缓存中。api, attributes.getValue(uri,'属性名称'); 


        /**
         * 根据parson 获取属性值加入缓存中
         * @param uri
         * @param localName
         * @param qName
         * @param attributes
         * @throws SAXException
         */
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            super.startElement(uri, localName, qName, attributes);
            if ("person".equals(localName)){
                String name = attributes.getValue(uri, "name");
                String age = attributes.getValue(uri, "age");
                String sex = attributes.getValue(uri, "sex");
                mEntriesList.add(new Person(name,sex,Integer.parseInt(age)));
            }
        }

4. 设置自定义字体,并获取

public class TypefaceUtils {
    private static Typeface getTypeface() {
        Context context = MyApp.getmContext();
        return Typeface.createFromAsset(context.getAssets(),
                "fonts/MTfin-Regular3.0.ttf");
    }

    public static void setTypeface(TextView tv) {
        tv.setTypeface(getTypeface());
    }
}

5.读取assets并解析json

  json/person.json 数据源

{
  "name":"zxl",
  "age":15,
  "data":[
    {
      "year":"2018",
      "money":10000
    },
    {
      "year":"2019",
      "money":100000
    }
  ],
  "show":{
    "English":28,
    "total":16
  }
}

 概要简述: 1. 读取assets文件,并转换为inputStream榴

                  2. 将 inputStream 转换为 streamReader

                  3. gson解析,将reader流转换为json bean

说明一下范型解析的要点: 有时需要传递范型的成员,可使用typeToken

(TypeToken是Gson库中包含的一种获取JSON类型的类,可以传入泛型来获取类型)

    private Person<ShowBean> parseSampleJson(){
        InputStreamReader inputStreamReader = null;
        try {
            inputStreamReader = new InputStreamReader(getAssets().open("json/person.json"), "UTF-8");
            return new Gson().fromJson(inputStreamReader, new TypeToken<Person<ShowBean>>(){}.getType());
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (null != inputStreamReader){
                try {
                    inputStreamReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

6. 文件写入 并判断是否存在该文件

    private void writeToFile(String file){
        FileOutputStream fileOutputStream = null;
        String msg ="大家好,我是谁,我喜欢你?";
        try {
            fileOutputStream = openFileOutput(file, MODE_PRIVATE);
            fileOutputStream.write(msg.getBytes());
            fileOutputStream.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            if (null != fileOutputStream){
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private boolean isFileIsExits(String fileNmae){
        File streamPath = getFileStreamPath(fileNmae);
        return streamPath.exists();
    }
    
    // 返回true [相同的文件名]
    Log.e(TAG,  isFileIsExits(FILE_NAME)+"");


 openFileOutput  (文件名,操作模式)  注意这里指定的文件名不可以包含路径,因为所有的文件都是默认存储到/data/data/<package  name>/files/目录下的,无法指定更深一级的文件夹。第二个参数是文件的操作模式,主要有两种模式可选, MODE_PRIVATE和MODE_APPEND。其中MODE_PRIVATE是默认的操作模式,表示当指 定同样文件名的时候,所写入的内容将会覆盖原文件中的内容,MODE_APPEND则表示 如果该文件已存在就往文件里面追加内容,不存在就创建新文件。且会在卸载你的应用程序时被删除掉 

7.后续

     对asset的解析案例记录先到这里,后面会陆续的进行增加包括对db文件的解析。

2016-10-28 16:38:09 zouxin_88 阅读数 5517

Unity发布安卓程序时提示 Android Asset Packaging Tool Failed。

后来通过各种方式试,发现是Assets\StreamingAssets有多个文件夹,删除就对了,原因是什么我也不知道。知道请说一下,谢谢。
2018-08-06 13:44:50 xindeluoye 阅读数 7886

一、创建:

右击app->new->Folder->Assets Folder.

这样就在main文件夹下创建了一个和res文件夹同级的assets文件夹了:

二、使用:

1.加载assets目录下的网页

//加载assets/win8_Demo/目录下的index.html网页
webView.loadUrl(”file:///android_asset/win8_Demo/index.html”);

说明:这种方式可以加载assets目录下的网页,并且与网页有关的css,js,图片等文件也会加载。

2.访问assets目录下的资源文件:

// 读取Assets文件夹下对应文件的输入流
InputStream is = getAssets().open("asset_test.txt");
// 读取Assets文件夹下mysw文件夹内对应文件的输入流
InputStream is2 = getAssets().open("mysw/asset_test.txt");

3.获取assets的文件及目录名

String fileNames[] =context.getAssets().list(path); 

4.将assets下的文件复制到SD卡

/** 
 *  从assets目录中复制整个文件夹内容 
 *  @param  context  Context 使用CopyFiles类的Activity
 *  @param  oldPath  String  原文件路径  如:/aa 
 *  @param  newPath  String  复制后路径  如:xx:/bb/cc 
 */ 
public void copyFilesFassets(Context context,String oldPath,String newPath) {                    
         try {
        String fileNames[] = context.getAssets().list(oldPath);//获取assets目录下的所有文件及目录名
        if (fileNames.length > 0) {//如果是目录
            File file = new File(newPath);
            file.mkdirs();//如果文件夹不存在,则递归
            for (String fileName : fileNames) {
               copyFilesFassets(context,oldPath + "/" + fileName,newPath+"/"+fileName);
            }
        } else {//如果是文件
            InputStream is = context.getAssets().open(oldPath);
            FileOutputStream fos = new FileOutputStream(new File(newPath));
            byte[] buffer = new byte[1024];
            int byteCount=0;               
            while((byteCount=is.read(buffer))!=-1) {//循环从输入流读取 buffer字节        
                fos.write(buffer, 0, byteCount);//将读取的输入流写入到输出流
            }
            fos.flush();//刷新缓冲区
            is.close();
            fos.close();
        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        //如果捕捉到错误则通知UI线程
                   MainActivity.handler.sendEmptyMessage(COPY_FALSE);
    }                           
}
 
该方法调用时的代码:music为assets目录下面的文件夹,里面包括具体的文件
copyFilesFassets(this, "music", "sdcard/clock");
 

摘自:https://blog.csdn.net/shandong_chu/article/details/52779356

ANDROID ASSET STUDIO

阅读数 9542