Home | History | Annotate | Download | only in android
      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.File;
     20 import java.io.FileFilter;
     21 import java.io.FilenameFilter;
     22 import java.io.IOException;
     23 import java.io.InputStream;
     24 
     25 import android.content.res.AssetFileDescriptor;
     26 import android.content.res.AssetManager;
     27 
     28 import com.badlogic.gdx.Files.FileType;
     29 import com.badlogic.gdx.Gdx;
     30 import com.badlogic.gdx.files.FileHandle;
     31 import com.badlogic.gdx.utils.GdxRuntimeException;
     32 
     33 /** @author mzechner
     34  * @author Nathan Sweet */
     35 public class AndroidFileHandle extends FileHandle {
     36 	// The asset manager, or null if this is not an internal file.
     37 	final private AssetManager assets;
     38 
     39 	AndroidFileHandle (AssetManager assets, String fileName, FileType type) {
     40 		super(fileName.replace('\\', '/'), type);
     41 		this.assets = assets;
     42 	}
     43 
     44 	AndroidFileHandle (AssetManager assets, File file, FileType type) {
     45 		super(file, type);
     46 		this.assets = assets;
     47 	}
     48 
     49 	public FileHandle child (String name) {
     50 		name = name.replace('\\', '/');
     51 		if (file.getPath().length() == 0) return new AndroidFileHandle(assets, new File(name), type);
     52 		return new AndroidFileHandle(assets, new File(file, name), type);
     53 	}
     54 
     55 	public FileHandle sibling (String name) {
     56 		name = name.replace('\\', '/');
     57 		if (file.getPath().length() == 0) throw new GdxRuntimeException("Cannot get the sibling of the root.");
     58 		return Gdx.files.getFileHandle(new File(file.getParent(), name).getPath(), type); //this way we can find the sibling even if it's inside the obb
     59 	}
     60 
     61 	public FileHandle parent () {
     62 		File parent = file.getParentFile();
     63 		if (parent == null) {
     64 			if (type == FileType.Absolute)
     65 				parent = new File("/");
     66 			else
     67 				parent = new File("");
     68 		}
     69 		return new AndroidFileHandle(assets, parent, type);
     70 	}
     71 
     72 	public InputStream read () {
     73 		if (type == FileType.Internal) {
     74 			try {
     75 				return assets.open(file.getPath());
     76 			} catch (IOException ex) {
     77 				throw new GdxRuntimeException("Error reading file: " + file + " (" + type + ")", ex);
     78 			}
     79 		}
     80 		return super.read();
     81 	}
     82 
     83 	public FileHandle[] list () {
     84 		if (type == FileType.Internal) {
     85 			try {
     86 				String[] relativePaths = assets.list(file.getPath());
     87 				FileHandle[] handles = new FileHandle[relativePaths.length];
     88 				for (int i = 0, n = handles.length; i < n; i++)
     89 					handles[i] = new AndroidFileHandle(assets, new File(file, relativePaths[i]), type);
     90 				return handles;
     91 			} catch (Exception ex) {
     92 				throw new GdxRuntimeException("Error listing children: " + file + " (" + type + ")", ex);
     93 			}
     94 		}
     95 		return super.list();
     96 	}
     97 
     98 	public FileHandle[] list (FileFilter filter) {
     99 		if (type == FileType.Internal) {
    100 			try {
    101 				String[] relativePaths = assets.list(file.getPath());
    102 				FileHandle[] handles = new FileHandle[relativePaths.length];
    103 				int count = 0;
    104 				for (int i = 0, n = handles.length; i < n; i++) {
    105 					String path = relativePaths[i];
    106 					FileHandle child = new AndroidFileHandle(assets, new File(file, path), type);
    107 					if (!filter.accept(child.file())) continue;
    108 					handles[count] = child;
    109 					count++;
    110 				}
    111 				if (count < relativePaths.length) {
    112 					FileHandle[] newHandles = new FileHandle[count];
    113 					System.arraycopy(handles, 0, newHandles, 0, count);
    114 					handles = newHandles;
    115 				}
    116 				return handles;
    117 			} catch (Exception ex) {
    118 				throw new GdxRuntimeException("Error listing children: " + file + " (" + type + ")", ex);
    119 			}
    120 		}
    121 		return super.list(filter);
    122 	}
    123 
    124 	public FileHandle[] list (FilenameFilter filter) {
    125 		if (type == FileType.Internal) {
    126 			try {
    127 				String[] relativePaths = assets.list(file.getPath());
    128 				FileHandle[] handles = new FileHandle[relativePaths.length];
    129 				int count = 0;
    130 				for (int i = 0, n = handles.length; i < n; i++) {
    131 					String path = relativePaths[i];
    132 					if (!filter.accept(file, path)) continue;
    133 					handles[count] = new AndroidFileHandle(assets, new File(file, path), type);
    134 					count++;
    135 				}
    136 				if (count < relativePaths.length) {
    137 					FileHandle[] newHandles = new FileHandle[count];
    138 					System.arraycopy(handles, 0, newHandles, 0, count);
    139 					handles = newHandles;
    140 				}
    141 				return handles;
    142 			} catch (Exception ex) {
    143 				throw new GdxRuntimeException("Error listing children: " + file + " (" + type + ")", ex);
    144 			}
    145 		}
    146 		return super.list(filter);
    147 	}
    148 
    149 	public FileHandle[] list (String suffix) {
    150 		if (type == FileType.Internal) {
    151 			try {
    152 				String[] relativePaths = assets.list(file.getPath());
    153 				FileHandle[] handles = new FileHandle[relativePaths.length];
    154 				int count = 0;
    155 				for (int i = 0, n = handles.length; i < n; i++) {
    156 					String path = relativePaths[i];
    157 					if (!path.endsWith(suffix)) continue;
    158 					handles[count] = new AndroidFileHandle(assets, new File(file, path), type);
    159 					count++;
    160 				}
    161 				if (count < relativePaths.length) {
    162 					FileHandle[] newHandles = new FileHandle[count];
    163 					System.arraycopy(handles, 0, newHandles, 0, count);
    164 					handles = newHandles;
    165 				}
    166 				return handles;
    167 			} catch (Exception ex) {
    168 				throw new GdxRuntimeException("Error listing children: " + file + " (" + type + ")", ex);
    169 			}
    170 		}
    171 		return super.list(suffix);
    172 	}
    173 
    174 	public boolean isDirectory () {
    175 		if (type == FileType.Internal) {
    176 			try {
    177 				return assets.list(file.getPath()).length > 0;
    178 			} catch (IOException ex) {
    179 				return false;
    180 			}
    181 		}
    182 		return super.isDirectory();
    183 	}
    184 
    185 	public boolean exists () {
    186 		if (type == FileType.Internal) {
    187 			String fileName = file.getPath();
    188 			try {
    189 				assets.open(fileName).close(); // Check if file exists.
    190 				return true;
    191 			} catch (Exception ex) {
    192 				// This is SUPER slow! but we need it for directories.
    193 				try {
    194 					return assets.list(fileName).length > 0;
    195 				} catch (Exception ignored) {
    196 				}
    197 				return false;
    198 			}
    199 		}
    200 		return super.exists();
    201 	}
    202 
    203 	public long length () {
    204 		if (type == FileType.Internal) {
    205 			AssetFileDescriptor fileDescriptor = null;
    206 			try {
    207 				fileDescriptor = assets.openFd(file.getPath());
    208 				return fileDescriptor.getLength();
    209 			} catch (IOException ignored) {
    210 			} finally {
    211 				if (fileDescriptor != null) {
    212 					try {
    213 						fileDescriptor.close();
    214 					} catch (IOException e) {
    215 					}
    216 					;
    217 				}
    218 			}
    219 		}
    220 		return super.length();
    221 	}
    222 
    223 	public long lastModified () {
    224 		return super.lastModified();
    225 	}
    226 
    227 	public File file () {
    228 		if (type == FileType.Local) return new File(Gdx.files.getLocalStoragePath(), file.getPath());
    229 		return super.file();
    230 	}
    231 
    232 	/**
    233 	 * @return an AssetFileDescriptor for this file or null if the file is not of type Internal
    234 	 * @throws IOException - thrown by AssetManager.openFd()
    235 	 */
    236 	public AssetFileDescriptor getAssetFileDescriptor() throws IOException {
    237 		return assets != null ? assets.openFd(path()) : null;
    238 	}
    239 }
    240