os: improve Android interop (#14827)
parent
585b5145fa
commit
3fb88500a2
|
@ -42,11 +42,6 @@ jobs:
|
||||||
./v -os windows cmd/v
|
./v -os windows cmd/v
|
||||||
./v -os windows examples/2048/2048.v
|
./v -os windows examples/2048/2048.v
|
||||||
|
|
||||||
- name: Compile to raw Android (non-graphic) compatible
|
|
||||||
run: |
|
|
||||||
# Test that V can compile non-graphic app to Android compatible code *without* using the -apk flag
|
|
||||||
./v -os android -gc none examples/toml.v
|
|
||||||
|
|
||||||
linux-cross:
|
linux-cross:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||||
|
@ -64,6 +59,7 @@ jobs:
|
||||||
sudo apt-get install --quiet -y libssl-dev sqlite3 libsqlite3-dev
|
sudo apt-get install --quiet -y libssl-dev sqlite3 libsqlite3-dev
|
||||||
sudo apt-get install --quiet -y mingw-w64 wine-stable winetricks
|
sudo apt-get install --quiet -y mingw-w64 wine-stable winetricks
|
||||||
## sudo apt-get install --quiet -y wine32
|
## sudo apt-get install --quiet -y wine32
|
||||||
|
|
||||||
- name: Turn off the wine crash dialog
|
- name: Turn off the wine crash dialog
|
||||||
run: winetricks nocrashdialog
|
run: winetricks nocrashdialog
|
||||||
|
|
||||||
|
@ -95,12 +91,6 @@ jobs:
|
||||||
./v -os windows examples/2048/2048.v
|
./v -os windows examples/2048/2048.v
|
||||||
ls -lart examples/2048/2048.exe
|
ls -lart examples/2048/2048.exe
|
||||||
|
|
||||||
- name: toml.v can be compiled to raw Android C
|
|
||||||
run: |
|
|
||||||
# Test that V can compile non-graphic app to Android compatible code *without* using the -apk flag
|
|
||||||
./v -os android -gc none examples/toml.v
|
|
||||||
|
|
||||||
|
|
||||||
windows-cross:
|
windows-cross:
|
||||||
runs-on: windows-2019
|
runs-on: windows-2019
|
||||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||||
|
|
|
@ -1,41 +1,104 @@
|
||||||
module os
|
module os
|
||||||
|
|
||||||
struct C.AAsset {
|
pub enum AssetMode {
|
||||||
|
buffer = C.AASSET_MODE_BUFFER // Caller plans to ask for a read-only buffer with all data.
|
||||||
|
random = C.AASSET_MODE_RANDOM // Read chunks, and seek forward and backward.
|
||||||
|
streaming = C.AASSET_MODE_STREAMING // Read sequentially, with an occasional forward seek.
|
||||||
|
unknown = C.AASSET_MODE_UNKNOWN // No specific information about how data will be accessed.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct C.ANativeActivity {
|
||||||
|
assetManager &AssetManager // Pointer to the Asset Manager instance for the application.
|
||||||
|
clazz voidptr // (jobject) The NativeActivity object handle.
|
||||||
|
env voidptr // (JNIEnv *) JNI context for the main thread of the app.
|
||||||
|
externalDataPath &char // Path to this application's external (removable/mountable) data directory.
|
||||||
|
instance voidptr // This is the native instance of the application.
|
||||||
|
internalDataPath &char // Path to this application's internal data directory.
|
||||||
|
obbPath &char // Available starting with Honeycomb: path to the directory containing the application's OBB files (if any).
|
||||||
|
sdkVersion int // The platform's SDK version code.
|
||||||
|
vm voidptr // (JavaVM *) The global handle on the process's Java VM.
|
||||||
|
}
|
||||||
|
|
||||||
|
// NativeActivity defines the native side of an android.app.NativeActivity.
|
||||||
|
pub type NativeActivity = C.ANativeActivity
|
||||||
|
|
||||||
struct C.AAssetManager {
|
struct C.AAssetManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct C.ANativeActivity {
|
// AssetManager provides access to an application's raw assets by creating Asset objects.
|
||||||
assetManager voidptr
|
pub type AssetManager = C.AAssetManager
|
||||||
}
|
|
||||||
|
|
||||||
fn C.AAssetManager_open(&C.AAssetManager, &char, int) &C.AAsset
|
fn C.AAssetManager_open(&C.AAssetManager, &char, int) &C.AAsset
|
||||||
|
|
||||||
|
// open opens an Android `Asset`
|
||||||
|
pub fn (am &AssetManager) open(filename string, mode AssetMode) !&Asset {
|
||||||
|
asset := C.AAssetManager_open(am, filename.str, int(mode))
|
||||||
|
if isnil(asset) {
|
||||||
|
return error('file `$filename` not found')
|
||||||
|
}
|
||||||
|
return asset
|
||||||
|
}
|
||||||
|
|
||||||
|
struct C.AAsset {
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Asset = C.AAsset
|
||||||
|
|
||||||
|
fn C.AAsset_getBuffer(&C.AAsset) voidptr
|
||||||
|
|
||||||
|
// get_buffer returns a pointer to a buffer holding the entire contents of the asset.
|
||||||
|
pub fn (a &Asset) get_buffer() voidptr {
|
||||||
|
return C.AAsset_getBuffer(a)
|
||||||
|
}
|
||||||
|
|
||||||
fn C.AAsset_getLength(&C.AAsset) int
|
fn C.AAsset_getLength(&C.AAsset) int
|
||||||
|
|
||||||
fn C.AAsset_read(&C.AAsset, voidptr, int) int
|
// get_length returns the total size of the asset data.
|
||||||
|
pub fn (a &Asset) get_length() int {
|
||||||
|
return C.AAsset_getLength(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn C.AAsset_getLength64(&C.AAsset) i64
|
||||||
|
|
||||||
|
// get_length_64 returns the total size of the asset data.
|
||||||
|
// get_length_64 returns the size using a 64-bit number insted of 32-bit as `get_length`.
|
||||||
|
pub fn (a &Asset) get_length_64() i64 {
|
||||||
|
return C.AAsset_getLength64(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn C.AAsset_read(&C.AAsset, voidptr, usize) int
|
||||||
|
|
||||||
|
// read attempts to read 'count' bytes of data from the current offset.
|
||||||
|
// read returns the number of bytes read, zero on EOF, or < 0 on error.
|
||||||
|
pub fn (a &Asset) read(buffer voidptr, count usize) int {
|
||||||
|
return C.AAsset_read(a, buffer, count)
|
||||||
|
}
|
||||||
|
|
||||||
fn C.AAsset_close(&C.AAsset)
|
fn C.AAsset_close(&C.AAsset)
|
||||||
|
|
||||||
pub fn read_apk_asset(file string) ?[]u8 {
|
// close closes the asset, freeing all associated resources.
|
||||||
|
pub fn (a &Asset) close() {
|
||||||
|
C.AAsset_close(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// read_apk_asset returns all the data located at `path`.
|
||||||
|
// `path` is expected to be relative to the `assets`
|
||||||
|
pub fn read_apk_asset(path string) ![]u8 {
|
||||||
$if apk {
|
$if apk {
|
||||||
act := &C.ANativeActivity(C.sapp_android_get_native_activity())
|
act := &NativeActivity(C.sapp_android_get_native_activity())
|
||||||
if isnil(act) {
|
if isnil(act) {
|
||||||
return error('Could not get reference to Android activity')
|
return error('could not get reference to Android activity')
|
||||||
}
|
}
|
||||||
asset := C.AAssetManager_open(&C.AAssetManager(act.assetManager), file.str, C.AASSET_MODE_STREAMING)
|
asset_manager := &AssetManager(act.assetManager)
|
||||||
if isnil(asset) {
|
asset := asset_manager.open(path, .streaming)!
|
||||||
return error('File `$file` not found')
|
len := asset.get_length()
|
||||||
}
|
|
||||||
len := C.AAsset_getLength(asset)
|
|
||||||
buf := []u8{len: len}
|
buf := []u8{len: len}
|
||||||
for {
|
for {
|
||||||
if C.AAsset_read(asset, buf.data, len) > 0 {
|
if asset.read(buf.data, usize(len)) > 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
C.AAsset_close(asset)
|
asset.close()
|
||||||
return buf
|
return buf
|
||||||
} $else {
|
} $else {
|
||||||
return error(@FN + ' can only be used with APK/AAB packaged Android apps')
|
return error(@FN + ' can only be used with APK/AAB packaged Android apps')
|
||||||
|
|
Loading…
Reference in New Issue