1 /******************************************************************************* 2 * Copyright 2011 See AUTHORS file. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 ******************************************************************************/ 16 17 package com.badlogic.gdx.backends.android; 18 19 import java.io.*; 20 21 import android.content.res.AssetFileDescriptor; 22 23 import com.badlogic.gdx.Gdx; 24 import com.badlogic.gdx.Files.FileType; 25 import com.badlogic.gdx.backends.android.ZipResourceFile.ZipEntryRO; 26 import com.badlogic.gdx.files.FileHandle; 27 import com.badlogic.gdx.utils.GdxRuntimeException; 28 29 /** @author sarkanyi */ 30 public class AndroidZipFileHandle extends AndroidFileHandle { 31 private AssetFileDescriptor assetFd; 32 private ZipResourceFile expansionFile; 33 private String path; 34 35 public AndroidZipFileHandle(String fileName) { 36 super(null, fileName, FileType.Internal); 37 initialize(); 38 } 39 40 public AndroidZipFileHandle(File file, FileType type) { 41 super(null, file, type); 42 initialize(); 43 } 44 45 private void initialize() { 46 path = file.getPath().replace('\\', '/'); 47 expansionFile = ((AndroidFiles) Gdx.files).getExpansionFile(); 48 assetFd = expansionFile.getAssetFileDescriptor(getPath()); 49 50 // needed for listing entries and exists() of directories 51 if (isDirectory()) 52 path += "/"; 53 } 54 55 @Override 56 public AssetFileDescriptor getAssetFileDescriptor() throws IOException { 57 return assetFd; 58 } 59 60 private String getPath() { 61 return path; 62 } 63 64 @Override 65 public InputStream read() { 66 InputStream input = null; 67 68 try { 69 input = expansionFile.getInputStream(getPath()); 70 } catch (IOException ex) { 71 throw new GdxRuntimeException("Error reading file: " + file + " (ZipResourceFile)", ex); 72 } 73 return input; 74 } 75 76 @Override 77 public FileHandle child(String name) { 78 if (file.getPath().length() == 0) 79 return new AndroidZipFileHandle(new File(name), type); 80 return new AndroidZipFileHandle(new File(file, name), type); 81 } 82 83 @Override 84 public FileHandle sibling(String name) { 85 if (file.getPath().length() == 0) 86 throw new GdxRuntimeException("Cannot get the sibling of the root."); 87 return Gdx.files.getFileHandle(new File(file.getParent(), name).getPath(), type); //this way we can find the sibling even if it's not inside the obb 88 } 89 90 @Override 91 public FileHandle parent() { 92 File parent = file.getParentFile(); 93 if (parent == null) 94 parent = new File(""); 95 return new AndroidZipFileHandle(parent.getPath()); 96 } 97 98 @Override 99 public FileHandle[] list() { 100 ZipEntryRO[] zipEntries = expansionFile.getEntriesAt(getPath()); 101 FileHandle[] handles = new FileHandle[zipEntries.length]; 102 for (int i = 0, n = handles.length; i < n; i++) 103 handles[i] = new AndroidZipFileHandle(zipEntries[i].mFileName); 104 return handles; 105 } 106 107 @Override 108 public FileHandle[] list(FileFilter filter) { 109 ZipEntryRO[] zipEntries = expansionFile.getEntriesAt(getPath()); 110 FileHandle[] handles = new FileHandle[zipEntries.length]; 111 int count = 0; 112 for (int i = 0, n = handles.length; i < n; i++) { 113 FileHandle child = new AndroidZipFileHandle(zipEntries[i].mFileName); 114 if (!filter.accept(child.file())) 115 continue; 116 handles[count] = child; 117 count++; 118 } 119 if (count < zipEntries.length) { 120 FileHandle[] newHandles = new FileHandle[count]; 121 System.arraycopy(handles, 0, newHandles, 0, count); 122 handles = newHandles; 123 } 124 return handles; 125 } 126 127 @Override 128 public FileHandle[] list(FilenameFilter filter) { 129 ZipEntryRO[] zipEntries = expansionFile.getEntriesAt(getPath()); 130 FileHandle[] handles = new FileHandle[zipEntries.length]; 131 int count = 0; 132 for (int i = 0, n = handles.length; i < n; i++) { 133 String path = zipEntries[i].mFileName; 134 if (!filter.accept(file, path)) 135 continue; 136 handles[count] = new AndroidZipFileHandle(path); 137 count++; 138 } 139 if (count < zipEntries.length) { 140 FileHandle[] newHandles = new FileHandle[count]; 141 System.arraycopy(handles, 0, newHandles, 0, count); 142 handles = newHandles; 143 } 144 return handles; 145 } 146 147 @Override 148 public FileHandle[] list(String suffix) { 149 ZipEntryRO[] zipEntries = expansionFile.getEntriesAt(getPath()); 150 FileHandle[] handles = new FileHandle[zipEntries.length]; 151 int count = 0; 152 for (int i = 0, n = handles.length; i < n; i++) { 153 String path = zipEntries[i].mFileName; 154 if (!path.endsWith(suffix)) 155 continue; 156 handles[count] = new AndroidZipFileHandle(path); 157 count++; 158 } 159 if (count < zipEntries.length) { 160 FileHandle[] newHandles = new FileHandle[count]; 161 System.arraycopy(handles, 0, newHandles, 0, count); 162 handles = newHandles; 163 } 164 return handles; 165 } 166 167 @Override 168 public boolean isDirectory() { 169 return assetFd == null; 170 } 171 172 @Override 173 public long length() { 174 return assetFd != null ? assetFd.getLength() : 0; 175 } 176 177 @Override 178 public boolean exists() { 179 return assetFd != null || expansionFile.getEntriesAt(getPath()).length != 0; 180 } 181 } 182