Allow to load and save.

This commit is contained in:
dgis 2018-12-11 22:41:34 +00:00
parent 7e008185b5
commit d623bcc609
9 changed files with 94 additions and 44 deletions

View file

@ -1,7 +1,7 @@
ABOUT
This project ports the Windows application Emu48 written in C to Android.
It uses the Android NDK. The former Emu48 source code remains untouch because a thin win32 emulation layer above Linux/NDK!
This win32 layer will allow to update easily from the original source code.
This win32 layer will allow to easily update from the original Emu48 source code.
NOT WORKING
- Sound
@ -12,6 +12,9 @@ NOT WORKING
- Serial Ports (Wire or Ir)
TODO
- Choose KML/Change KML/NewDocument
- Option to allow rotation
- Option to auto hide the menu
- Bitmap corruption when touching the buttons
- Android UI Settings
- Sound

View file

@ -33,6 +33,7 @@ extern void mainViewUpdateCallback();
extern void mainViewResizeCallback(int x, int y);
extern int mainViewGetOpenFileNameCallback(OPENFILENAME * ofn);
extern int mainViewGetSaveFileNameCallback(OPENFILENAME * ofn);
extern int openFileFromContentResolver(const TCHAR * url, int writeAccess);
#if !defined VERIFY

View file

@ -13,6 +13,7 @@
extern void emu48Start();
extern AAssetManager * assetManager;
static jobject viewToUpdate = NULL;
static jobject mainActivity = NULL;
jobject bitmapMainScreen;
AndroidBitmapInfo androidBitmapInfo;
@ -40,6 +41,7 @@ extern void OnBackupRestore();
extern void OnBackupDelete();
JNIEnv *getJNIEnvironment();
JavaVM *java_machine;
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
@ -48,6 +50,21 @@ JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
return JNI_VERSION_1_6;
}
JNIEnv *getJNIEnvironment() {
JNIEnv * jniEnv;
jint ret;
BOOL needDetach = FALSE;
ret = (*java_machine)->GetEnv(java_machine, &jniEnv, JNI_VERSION_1_6);
if (ret == JNI_EDETACHED) {
// GetEnv: not attached
ret = (*java_machine)->AttachCurrentThread(java_machine, &jniEnv, NULL);
if (ret == JNI_OK) {
needDetach = TRUE;
}
}
return jniEnv;
}
enum CALLBACK_TYPE {
CALLBACK_TYPE_INVALIDATE = 0,
CALLBACK_TYPE_WINDOW_RESIZE = 1,
@ -132,36 +149,33 @@ int mainViewGetSaveFileNameCallback(OPENFILENAME * ofn) {
// https://stackoverflow.com/questions/9630134/jni-how-to-callback-from-c-or-c-to-java
int mainViewCallback(int type, int param1, int param2, const TCHAR * param3, const TCHAR * param4) {
if (viewToUpdate) {
JNIEnv * jniEnv;
jint ret;
BOOL needDetach = FALSE;
ret = (*java_machine)->GetEnv(java_machine, &jniEnv, JNI_VERSION_1_6);
if (ret == JNI_EDETACHED) {
// GetEnv: not attached
ret = (*java_machine)->AttachCurrentThread(java_machine, &jniEnv, NULL);
if (ret == JNI_OK) {
needDetach = TRUE;
}
}
JNIEnv *jniEnv = getJNIEnvironment();
jclass viewToUpdateClass = (*jniEnv)->GetObjectClass(jniEnv, viewToUpdate);
//jmethodID midStr = (*jniEnv)->GetMethodID(jniEnv, viewToUpdateClass, "updateCallback", "()V");
jmethodID midStr = (*jniEnv)->GetMethodID(jniEnv, viewToUpdateClass, "updateCallback", "(IIILjava/lang/String;Ljava/lang/String;)I");
jstring utfParam3 = (*jniEnv)->NewStringUTF(jniEnv, param3);
jstring utfParam4 = (*jniEnv)->NewStringUTF(jniEnv, param4);
int result = (*jniEnv)->CallIntMethod(jniEnv, viewToUpdate, midStr, type, param1, param2, utfParam3, utfParam4);
// if(needDetach)
// ret = (*java_machine)->DetachCurrentThread(java_machine);
// if(needDetach) ret = (*java_machine)->DetachCurrentThread(java_machine);
return result;
}
}
// Must be called in the main thread
int openFileFromContentResolver(const TCHAR * url, int writeAccess) {
JNIEnv *jniEnv = getJNIEnvironment();
jclass mainActivityClass = (*jniEnv)->GetObjectClass(jniEnv, mainActivity);
jmethodID midStr = (*jniEnv)->GetMethodID(jniEnv, mainActivityClass, "openFileFromContentResolver", "(Ljava/lang/String;I)I");
jstring utfUrl = (*jniEnv)->NewStringUTF(jniEnv, url);
int result = (*jniEnv)->CallIntMethod(jniEnv, mainActivity, midStr, utfUrl, writeAccess);
return result;
}
JNIEXPORT void JNICALL Java_com_regis_cosnier_emu48_NativeLib_start(JNIEnv *env, jobject thisz, jobject assetMgr, jobject bitmapMainScreen0, jobject view) {
JNIEXPORT void JNICALL Java_com_regis_cosnier_emu48_NativeLib_start(JNIEnv *env, jobject thisz, jobject assetMgr, jobject bitmapMainScreen0, jobject activity, jobject view) {
viewToUpdate = (*env)->NewGlobalRef(env, view);
bitmapMainScreen = (*env)->NewGlobalRef(env, bitmapMainScreen0);
mainActivity = (*env)->NewGlobalRef(env, activity);
viewToUpdate = (*env)->NewGlobalRef(env, view);
int ret = AndroidBitmap_getInfo(env, bitmapMainScreen, &androidBitmapInfo);
if (ret < 0) {

View file

@ -101,23 +101,27 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
flags |= O_CREAT;
}
fd = open(lpFileName, flags, perm);
if (-1 != fd && 0 != dwShareMode) {
// Not specifiying shared write means non-shared (exclusive) write
if (0 == (dwShareMode & FILE_SHARE_WRITE))
lock.l_type = F_WRLCK;
else if (0 != (dwShareMode & FILE_SHARE_READ))
lock.l_type = F_RDLCK;
// Lock entire file
lock.l_len = lock.l_start = 0;
lock.l_whence = SEEK_SET;
if (-1 == fcntl(fd, F_SETLK, &lock) && (EACCES == errno || EAGAIN == errno)) {
close(fd);
return -1;
}
}
TCHAR * urlSchemeFound = _tcsstr(lpFileName, _T("://"));
if(urlSchemeFound)
fd = openFileFromContentResolver(lpFileName, dwDesiredAccess);
else
fd = open(lpFileName, flags, perm);
// if (-1 != fd && 0 != dwShareMode) {
// // Not specifiying shared write means non-shared (exclusive) write
// if (0 == (dwShareMode & FILE_SHARE_WRITE))
// lock.l_type = F_WRLCK;
// else if (0 != (dwShareMode & FILE_SHARE_READ))
// lock.l_type = F_RDLCK;
//
// // Lock entire file
// lock.l_len = lock.l_start = 0;
// lock.l_whence = SEEK_SET;
//
// if (-1 == fcntl(fd, F_SETLK, &lock) && (EACCES == errno || EAGAIN == errno)) {
// close(fd);
// return -1;
// }
// }
if (fd != -1) {
HANDLE handle = malloc(sizeof(_HANDLE));
memset(handle, 0, sizeof(_HANDLE));

View file

@ -934,10 +934,11 @@ extern int lstrcmp(LPCWSTR lpString1, LPCWSTR lpString2);
extern int lstrcmpi(LPCWSTR lpString1, LPCWSTR lpString2);
#define _tcstoul wcstoul
#define _tcsncmp wcsncmp
#define _tcslen wcslen
#define _tcscpy wcscpy
#define _tcscat wcscat
#define _tcsncmp wcsncmp
#define _tcslen wcslen
#define _tcscpy wcscpy
#define _tcscat wcscat
#define _tcsstr wcsstr
#else
@ -959,6 +960,7 @@ extern int lstrcmpi(LPCSTR lpString1, LPCSTR lpString2);
#define _tcslen strlen
#define _tcscpy strcpy
#define _tcscat strcat
#define _tcsstr strstr
#endif // !UNICODE

View file

@ -4,6 +4,7 @@ import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewGroup;
@ -23,6 +24,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
@ -169,7 +171,7 @@ public class MainActivity extends AppCompatActivity
public static int INTENT_GETSAVEFILENAME = 2;
private void OnFileOpen() {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
//intent.setType("YOUR FILETYPE"); //not needed, but maybe usefull
intent.setType("*/*");
@ -269,7 +271,8 @@ public class MainActivity extends AppCompatActivity
//just as an example, I am writing a String to the Uri I received from the user:
Log.d(TAG, "onActivityResult INTENT_GETSAVEFILENAME " + uri.toString());
NativeLib.onFileSaveAs(uri.toString());
String url = uri.toString();
NativeLib.onFileSaveAs(url);
// try {
// OutputStream output = getContentResolver().openOutputStream(uri);
//
@ -283,4 +286,25 @@ public class MainActivity extends AppCompatActivity
}
super.onActivityResult(requestCode, resultCode, data);
}
final int GENERIC_READ = 1;
final int GENERIC_WRITE = 2;
int openFileFromContentResolver(String url, int writeAccess) {
//https://stackoverflow.com/a/31677287
Uri uri = Uri.parse(url);
ParcelFileDescriptor filePfd;
try {
String mode = "";
if((writeAccess & GENERIC_READ) == GENERIC_READ)
mode += "r";
if((writeAccess & GENERIC_WRITE) == GENERIC_WRITE)
mode += "w";
filePfd = getContentResolver().openFileDescriptor(uri, mode);
} catch (FileNotFoundException e) {
e.printStackTrace();
return 0;
}
int fd = filePfd != null ? filePfd.getFd() : 0;
return fd;
}
}

View file

@ -36,7 +36,7 @@ public class MainScreenView extends SurfaceView {
((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
bitmapMainScreen = Bitmap.createBitmap(displayMetrics.widthPixels, displayMetrics.heightPixels, Bitmap.Config.ARGB_8888);
bitmapMainScreen.eraseColor(Color.LTGRAY);
NativeLib.start(mgr, bitmapMainScreen, this);
NativeLib.start(mgr, bitmapMainScreen, (MainActivity)context, this);
vkmap = new HashMap<Integer, Integer>();
vkmap.put(KeyEvent.KEYCODE_BACK, 0x08); // VK_BACK

View file

@ -2,6 +2,8 @@ package com.regis.cosnier.emu48;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.ParcelFileDescriptor;
import android.view.View;
public class NativeLib {
@ -10,7 +12,7 @@ public class NativeLib {
System.loadLibrary("native-lib");
}
public static native void start(AssetManager mgr, Bitmap bitmapMainScreen, MainScreenView view);
public static native void start(AssetManager mgr, Bitmap bitmapMainScreen, MainActivity activity, MainScreenView view);
public static native void stop();
//public static native void resize(int width, int height);
public static native void draw();