Merge pull request #81 from triplef/android-temp-dir

Added support for temp and caches dir on Android.
This commit is contained in:
Gregory Casamento 2019-11-25 04:09:56 -05:00 committed by GitHub
commit 69f7130fa7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 81 additions and 19 deletions

View file

@ -14,6 +14,17 @@
* NSTimeZones/NSTimeZones.tar: updated to latest info
2019-11-05 Frederik Seiffert <frederik@algoriddim.com>
* Headers/Foundation/NSProcessInfo.h:
* Source/NSPathUtilities.m:
* Source/NSProcessInfo.m:
Added support for NSTemporaryDirectory() on Android using subfolder
in folder returned by Context.getCacheDir(), as there is no official
temp dir prior to API level 26. Clean up temp dir on launch in
GSInitializeProcessAndroid(). Also use Context.getCacheDir()
as NSCachesDirectory (with NSUserDomainMask) on Android.
2019-10-27 Fred Kiefer <fredkiefer@gmx.de>
* Headers/Foundation/NSUnit.h,

View file

@ -273,6 +273,7 @@ DEFINE_BLOCK_TYPE(GSPerformExpiringActivityBlock, void, BOOL);
#ifdef __ANDROID__
- (jobject) androidContext;
- (NSString *) androidFilesDir;
- (NSString *) androidCacheDir;
#endif
@end

View file

@ -1950,9 +1950,7 @@ NSTemporaryDirectory(void)
int perm;
int owner;
BOOL flag;
#if !defined(_WIN32)
int uid;
#else
#if defined(_WIN32)
unichar buffer[1024];
if (GetTempPathW(1024, buffer))
@ -1960,6 +1958,20 @@ NSTemporaryDirectory(void)
baseTempDirName = [NSString stringWithCharacters: buffer
length: wcslen(buffer)];
}
#elif defined(__ANDROID__)
/*
* Use subfolder of cache directory as temp dir on Android, as there
* is no official temp dir prior to API level 26, and the cache dir
* is at least auto-purged by the system if disk space is needed.
* We also clean it up on launch in GSInitializeProcessAndroid().
*/
NSString *cacheDir = [[NSProcessInfo processInfo] androidCacheDir];
if (cacheDir)
{
baseTempDirName = [cacheDir stringByAppendingPathComponent: @"tmp"];
}
#else
int uid;
#endif
/*
@ -2004,10 +2016,31 @@ NSTemporaryDirectory(void)
if ([manager fileExistsAtPath: tempDirName isDirectory: &flag] == NO
|| flag == NO)
{
#ifdef __ANDROID__
/*
* Create our own temp dir on Android. We can disregard attributes
* since they are not supported.
*/
if ([manager createDirectoryAtPath: tempDirName
withIntermediateDirectories: YES
attributes: nil
error: NULL] == NO)
{
NSWarnFLog(@"Attempt to create temporary directory (%@)"
@" failed.", tempDirName);
return nil;
}
#else
NSWarnFLog(@"Temporary directory (%@) does not exist", tempDirName);
return nil;
#endif
}
// Mateu Batle: secure temporary directories don't work in MinGW
// Ivan Vucica: there are also problems with Cygwin
// probable cause: http://stackoverflow.com/q/9561759/39974
#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__ANDROID__)
/*
* Check that we are the directory owner, and that we, and nobody else,
* have access to it. If other people have access, try to create a secure
@ -2018,20 +2051,11 @@ NSTemporaryDirectory(void)
perm = [[attr objectForKey: NSFilePosixPermissions] intValue];
perm = perm & 0777;
// Mateu Batle: secure temporary directories don't work in MinGW
// Ivan Vucica: there are also problems with Cygwin
// probable cause: http://stackoverflow.com/q/9561759/39974
#if !defined(_WIN32) && !defined(__CYGWIN__)
#if defined(_WIN32)
uid = owner;
#else
#ifdef HAVE_GETEUID
uid = geteuid();
#else
uid = getuid();
#endif /* HAVE_GETEUID */
#endif
if ((perm != 0700 && perm != 0600) || owner != uid)
{
NSString *secure;
@ -2472,12 +2496,17 @@ L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\GNUstep",
case NSCachesDirectory:
{
#ifdef __ANDROID__
/* Use system-provided cache directory on Android */
ADD_PATH(NSUserDomainMask, [[NSProcessInfo processInfo] androidCacheDir], @"");
#else
/* Uff - at the moment the only place to put Caches seems to
* be Library. Unfortunately under GNU/Linux Library will
* end up in /usr/lib/GNUstep which could be mounted
* read-only!
*/
ADD_PATH(NSUserDomainMask, gnustepUserLibrary, @"Caches");
#endif
ADD_PATH(NSLocalDomainMask, gnustepLocalLibrary, @"Caches");
ADD_PATH(NSNetworkDomainMask, gnustepNetworkLibrary, @"Caches");
ADD_PATH(NSSystemDomainMask, gnustepSystemLibrary, @"Caches");

View file

@ -234,6 +234,7 @@ static NSMutableSet *mySet = nil;
#ifdef __ANDROID__
static jobject _androidContext = NULL;
static NSString *_androidFilesDir = nil;
static NSString *_androidCacheDir = nil;
#endif
/*************************************************************************
@ -1607,21 +1608,36 @@ GSInitializeProcessAndroid(JNIEnv *env, jobject context)
free(arg0);
// get File class and path method
jclass fileCls = (*env)->FindClass(env, "java/io/File");
jmethodID getAbsolutePathMethod = (*env)->GetMethodID(env, fileCls, "getAbsolutePath", "()Ljava/lang/String;");
// get Android files dir
jmethodID filesDirMethod = (*env)->GetMethodID(env, cls, "getFilesDir", "()Ljava/io/File;");
jobject filesDirObj = (*env)->CallObjectMethod(env, context, filesDirMethod);
jclass filesDirCls = (*env)->GetObjectClass(env, filesDirObj);
jmethodID getStoragePath = (*env)->GetMethodID(env, filesDirCls, "getAbsolutePath", "()Ljava/lang/String;");
jstring filesDirJava = (*env)->CallObjectMethod(env, filesDirObj, getStoragePath);
const jchar *unichars = (*env)->GetStringChars(env, filesDirJava, NULL);
jsize length = (*env)->GetStringLength(env, filesDirJava);
_androidFilesDir = [NSString stringWithCharacters:unichars length:length];
(*env)->ReleaseStringChars(env, filesDirJava, unichars);
jstring filesDirJava = (*env)->CallObjectMethod(env, filesDirObj, getAbsolutePathMethod);
const jchar *filesDirUnichars = (*env)->GetStringChars(env, filesDirJava, NULL);
jsize filesDirLength = (*env)->GetStringLength(env, filesDirJava);
_androidFilesDir = [NSString stringWithCharacters:filesDirUnichars length:filesDirLength];
(*env)->ReleaseStringChars(env, filesDirJava, filesDirUnichars);
// get Android cache dir
jmethodID cacheDirMethod = (*env)->GetMethodID(env, cls, "getCacheDir", "()Ljava/io/File;");
jobject cacheDirObj = (*env)->CallObjectMethod(env, context, cacheDirMethod);
jstring cacheDirJava = (*env)->CallObjectMethod(env, cacheDirObj, getAbsolutePathMethod);
const jchar *cacheDirUnichars = (*env)->GetStringChars(env, cacheDirJava, NULL);
jsize cacheDirLength = (*env)->GetStringLength(env, cacheDirJava);
_androidCacheDir = [NSString stringWithCharacters:cacheDirUnichars length:cacheDirLength];
(*env)->ReleaseStringChars(env, cacheDirJava, cacheDirUnichars);
// get asset manager and initialize NSBundle
jmethodID assetManagerMethod = (*env)->GetMethodID(env, cls, "getAssets", "()Landroid/content/res/AssetManager;");
jstring assetManagerJava = (*env)->CallObjectMethod(env, context, assetManagerMethod);
[NSBundle setJavaAssetManager:assetManagerJava withJNIEnv:env];
// clean up our NSTemporaryDirectory() if it exists
NSString *tempDirName = [_androidCacheDir stringByAppendingPathComponent: @"tmp"];
[[NSFileManager defaultManager] removeItemAtPath:tempDirName error:NULL];
}
#endif
@ -1667,6 +1683,11 @@ GSInitializeProcessAndroid(JNIEnv *env, jobject context)
{
return _androidFilesDir;
}
- (NSString *) androidCacheDir
{
return _androidCacheDir;
}
#endif
@end