Isolating file utilities

This commit is contained in:
Rodrigo Damazio
2010-08-20 23:10:09 -03:00
parent 3532a6360b
commit bf7b24ecc0
5 changed files with 181 additions and 90 deletions
@@ -32,6 +32,7 @@ import com.google.android.apps.mytracks.io.TrackWriterFactory;
import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat;
import com.google.android.apps.mytracks.services.ITrackRecordingService;
import com.google.android.apps.mytracks.services.TrackRecordingService;
import com.google.android.apps.mytracks.util.FileUtils;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
@@ -62,9 +63,9 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager.BadTokenException;
import android.widget.RelativeLayout;
import android.widget.TabHost;
@@ -1506,18 +1507,11 @@ public class MyTracks extends TabActivity implements OnTouchListener,
final TrackWriter writer =
TrackWriterFactory.newWriter(this, providerUtils, trackId, format);
String sep = System.getProperty("file.separator");
FileUtils fileUtils = new FileUtils();
String extension = format.getExtension();
StringBuilder dirNameBuilder = new StringBuilder();
dirNameBuilder.append(Environment.getExternalStorageDirectory());
dirNameBuilder.append(sep);
dirNameBuilder.append(MyTracksConstants.SDCARD_TOP_DIR);
dirNameBuilder.append(sep);
dirNameBuilder.append(extension);
dirNameBuilder.append(sep);
dirNameBuilder.append("tmp");
String dirName = fileUtils.buildExternalDirectoryPath(extension, "tmp");
File dir = new File(dirNameBuilder.toString());
File dir = new File(dirName);
writer.setDirectory(dir);
writer.setOnCompletion(new Runnable() {
public void run() {
@@ -20,6 +20,7 @@ import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.TrackBuffer;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.util.FileUtils;
import com.google.android.apps.mytracks.util.MyTracksUtils;
import com.google.android.maps.mytracks.R;
@@ -27,14 +28,12 @@ import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.location.Location;
import android.os.Environment;
import android.util.Log;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.HashSet;
/**
* The class which exports tracks to the SD card.
@@ -51,39 +50,20 @@ public class TrackWriter {
private final MyTracksProviderUtils providerUtils;
private final Track track;
private final TrackFormatWriter writer;
private final FileUtils fileUtils;
private Runnable onCompletion = null;
private boolean success = false;
private int errorMessage = -1;
private File directory = null;
private File file = null;
/**
* A set of characters that are prohibited from being in file names.
*/
private static final HashSet<Character> PROHIBITED_CHARACTERS =
new HashSet<Character>();
static {
for (int i = 0; i < 48; i++) {
PROHIBITED_CHARACTERS.add(new Character((char) i));
}
for (int i = 58; i < 65; i++) {
PROHIBITED_CHARACTERS.add(new Character((char) i));
}
for (int i = 91; i < 97; i++) {
PROHIBITED_CHARACTERS.add(new Character((char) i));
}
for (int i = 123; i < 128; i++) {
PROHIBITED_CHARACTERS.add(new Character((char) i));
}
}
public TrackWriter(Context context, MyTracksProviderUtils providerUtils,
Track track, TrackFormatWriter writer) {
this.context = context;
this.providerUtils = providerUtils;
this.track = track;
this.writer = writer;
this.fileUtils = new FileUtils();
}
/**
@@ -149,26 +129,6 @@ public class TrackWriter {
* ===============
*/
/**
* Makes sure the given directory exists, creating it if necessary.
*
* @param dir the directory to ensure exists
* @return True on success
*/
private static boolean ensureExists(File dir) {
if (dir.exists()) {
return true;
}
File parent = dir.getParentFile();
if (parent == null) {
return true;
}
if (!ensureExists(parent)) {
return false;
}
return dir.mkdir();
}
private void finished() {
if (onCompletion != null) {
runOnUiThread(onCompletion);
@@ -197,7 +157,7 @@ public class TrackWriter {
// Make sure the name will work on FAT
String fileName =
sanitizeName(track.getName()) + "." + writer.getExtension();
fileUtils.sanitizeName(track.getName() + "." + writer.getExtension());
Log.i(MyTracksConstants.TAG, "Writing track to: " + fileName);
try {
writer.prepare(track, newOutputStream(fileName));
@@ -214,23 +174,16 @@ public class TrackWriter {
*/
protected boolean canWriteFile() {
if (directory == null) {
String sep = System.getProperty("file.separator");
StringBuilder dirNameBuilder = new StringBuilder();
dirNameBuilder.append(Environment.getExternalStorageDirectory());
dirNameBuilder.append(sep);
dirNameBuilder.append(MyTracksConstants.SDCARD_TOP_DIR);
dirNameBuilder.append(sep);
dirNameBuilder.append(writer.getExtension());
directory = newFile(dirNameBuilder.toString());
String dirName = fileUtils.buildExternalDirectoryPath(writer.getExtension());
directory = newFile(dirName);
}
if (!Environment.getExternalStorageState()
.equals(Environment.MEDIA_MOUNTED)) {
if (!fileUtils.isSdCardAvailable()) {
Log.i(MyTracksConstants.TAG, "Could not find SD card.");
errorMessage = R.string.io_no_external_storage_found;
return false;
}
if (!ensureExists(directory)) {
if (!fileUtils.ensureDirectoryExists(directory)) {
Log.i(MyTracksConstants.TAG, "Could not create export directory.");
errorMessage = R.string.io_create_dir_failed;
return false;
@@ -257,25 +210,6 @@ public class TrackWriter {
return new File(path);
}
/**
* Normalizes the input string and make sure it is a valid fat32 file name.
*/
static String sanitizeName(String name) {
StringBuilder cleaned = new StringBuilder();
for (int i = 0; i < name.length(); i++) {
char c = name.charAt(i);
if (!PROHIBITED_CHARACTERS.contains(c)) {
cleaned.append(c);
}
}
// Max = 260
// Boiler plate /[gpx|kml]/ .[gpx|kml] = 8
return (cleaned.length() > 252)
? cleaned.substring(0, 252)
: cleaned.toString();
}
/**
* Writes the waypoints for the given track.
*
@@ -0,0 +1,106 @@
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.util;
import com.google.android.apps.mytracks.MyTracksConstants;
import android.os.Environment;
import java.io.File;
import java.util.HashSet;
/**
* Utilities for dealing with files.
*
* @author Rodrigo Damazio
*/
public class FileUtils {
/**
* A set of characters that are prohibited from being in file names.
*/
private static final HashSet<Character> PROHIBITED_CHARACTERS =
new HashSet<Character>();
static {
for (int i = 0; i < 48; i++) {
PROHIBITED_CHARACTERS.add(new Character((char) i));
}
for (int i = 58; i < 65; i++) {
PROHIBITED_CHARACTERS.add(new Character((char) i));
}
for (int i = 91; i < 97; i++) {
PROHIBITED_CHARACTERS.add(new Character((char) i));
}
for (int i = 123; i < 128; i++) {
PROHIBITED_CHARACTERS.add(new Character((char) i));
}
}
/**
* Builds a path inside the My Tracks directory in the SD card.
*
* @param components the path components inside the mytracks directory
* @return the full path to the destination
*/
public String buildExternalDirectoryPath(String... components) {
StringBuilder dirNameBuilder = new StringBuilder();
dirNameBuilder.append(Environment.getExternalStorageDirectory());
dirNameBuilder.append(File.separatorChar);
dirNameBuilder.append(MyTracksConstants.SDCARD_TOP_DIR);
for (String component : components) {
dirNameBuilder.append(File.separatorChar);
dirNameBuilder.append(component);
}
return dirNameBuilder.toString();
}
/**
* Returns whether the SD card is available.
*/
public boolean isSdCardAvailable() {
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
}
/**
* Normalizes the input string and make sure it is a valid fat32 file name.
*/
public String sanitizeName(String name) {
StringBuilder cleaned = new StringBuilder();
for (int i = 0; i < name.length(); i++) {
char c = name.charAt(i);
if (!PROHIBITED_CHARACTERS.contains(c)) {
cleaned.append(c);
}
}
return (cleaned.length() > 260)
? cleaned.substring(0, 260)
: cleaned.toString();
}
public boolean ensureDirectoryExists(File dir) {
if (dir.exists() && dir.isDirectory()) {
return true;
}
if (dir.mkdirs()) {
return true;
}
return false;
}
}
@@ -117,7 +117,6 @@ public class TrackWriterTest extends AndroidTestCase {
private static final long TRACK_ID = 1234567L;
private static final String EXTENSION = "ext";
private static final String TRACK_NAME = "Swimming across the pacific";
private static final String TRACK_SANITIZED_NAME = "Swimmingacrossthepacific";
private static final String FULL_TRACK_NAME = "Swimmingacrossthepacific.ext";
private Track track;
@@ -188,10 +187,6 @@ public class TrackWriterTest extends AndroidTestCase {
mocksControl.verify();
}
public void testSanitizeName() {
assertEquals(TRACK_SANITIZED_NAME, TrackWriter.sanitizeName(TRACK_NAME));
}
public void testOpenFile() {
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
writer = new OpenFileTrackWriter(
@@ -0,0 +1,62 @@
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.util;
import com.google.android.apps.mytracks.MyTracksConstants;
import android.os.Environment;
import java.io.File;
import junit.framework.TestCase;
/**
* Tests for {@link FileUtils}.
*
* @author Rodrigo Damazio
*/
public class FileUtilsTest extends TestCase {
private static final String ORIGINAL_NAME = "Swimming across the pacific";
private static final String SANITIZED_NAME = "Swimmingacrossthepacific";
private FileUtils fileUtils;
@Override
protected void setUp() throws Exception {
super.setUp();
fileUtils = new FileUtils();
}
public void testBuildExternalDirectoryPath() {
String expectedName = Environment.getExternalStorageDirectory()
+ File.separator
+ MyTracksConstants.SDCARD_TOP_DIR
+ File.separator
+ "a"
+ File.separator
+ "b"
+ File.separator
+ "c";
String dirName = fileUtils.buildExternalDirectoryPath("a", "b", "c");
assertEquals(expectedName, dirName);
}
public void testSanitizeName() {
assertEquals(SANITIZED_NAME, fileUtils.sanitizeName(ORIGINAL_NAME));
}
}