Giter Site home page Giter Site logo

attach's Introduction

Gluon Attach

Maven Central Github Actions License: GPL v3

Gluon Attach is the component that addresses the integration with low-level platform APIs in an end-to-end Java Mobile solution.

Attach provides an uniform, platform-independent API to access device and hardware features. At runtime, the appropriate implementation (attach:desktop, attach:android, attach:ios) makes sure the platform specific code is used to deliver the functionality.

Attach is open source, and it is freely licensed under the GPL license. Gluon can provide custom consultancy and training, commercial licenses, and open source commercial support, including daily and monthly releases.

Getting started

The best way to get started with Gluon Attach is using the GluonFX Maven archetype from your IDE and creating a Gluon Mobile project.

The Gluon samples are a good way to find out how Attach is used.

See the documentation on how to add Attach with the GluonFX Plugin.

The JavaDoc contains the reference documentation for the Attach API's.

The list of available services at Attach can be found here.

Building Attach

Gluon Attach is frequently released, and this is only required in case you want to fork and build your local version of Attach.

Requisites

These are the requisites:

  • A recent version of JDK 11
  • Gradle 6.0 or superior.

To build the iOS Services:

  • A Mac with with MacOS X 11 or superior
  • XCode 11.x or superior

How to build and install Attach

To build the Attach services on the project's root, run:

./gradlew clean build

If you want to install them, run:

./gradlew clean publishToMavenLocal

When the process finishes successfully, the different services can be added to a Gluon Mobile project.

For instance, the Display service for desktop can be added to the project like:

<!-- dependencies -->
<dependency>
    <groupId>com.gluonhq.attach</groupId>
    <artifactId>display</artifactId>
    <version>4.0.9-SNAPSHOT</version>
</dependency>

<!-- plugin -->
<configuration>
    <attachList>
        <list>display</list>
    </attachList>
</configuration>

Issues and Contributions

Issues can be reported to the Issue tracker

Contributions can be submitted via Pull requests, providing you have signed the Gluon Individual Contributor License Agreement (CLA).

attach's People

Contributors

abhinayagarwal avatar almasb avatar cseeberg avatar gluon-bot avatar johanvos avatar jperedadnr avatar mipastgt avatar molbertz avatar salmonb avatar scientificware avatar tiainen avatar vjovanov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

attach's Issues

allow attach services to contain resources

Currently, only the classes from attach services are considered by Substrate. There might be resources though (e.g. egm180.nor in the DalvikPositionService) that need to be handled by Substrate, in this case it has to be added to the apk.

Use GlassApplication in Runtime-Args

When refactoring the RuntimeArgs service from Charm Down to Attach, the iOS implementation removed the GlassApplication (RuntimeArgsAdditions) extension.

We need to restore it back.

Include desktop requirements in module-info

The module-info descriptor for each service should add a requirement in the JavaFX modules that the desktop implementation needs. Therefore, the build should add them too.

App crashes on Android, running but idle, when phone switched off

stacktrace:

04-17 17:36:17.640   922  1027 D ActivityTaskManager: Top Process State changed to PROCESS_STATE_TOP_SLEEPING
04-17 17:36:17.668 19409 19409 V GraalActivity: onPause
04-17 17:36:17.669 19409 19409 E GraalGluon: Dispatching lifecycle event from native Dalvik layer: pause
04-17 17:36:17.669 19409 19409 D GluonAttach: Call Attach method from native Lifecycle: pause
04-17 17:36:17.669 19409 19409 D GraalGluon: ATTACH_DALVIK, tid = 19409, existed? 1, dalvikEnv at 0x7c661036c0
04-17 17:36:17.669 19409 19409 D GluonAttach: Call2 Attach method from native Lifecycle: pause, class at 0x0 and method at 0x0 and jc at 0x75
04-17 17:36:17.669 19409 19409 F hello.hellofx: java_vm_ext.cc:570] JNI DETECTED ERROR IN APPLICATION: mid == null
04-17 17:36:17.669 19409 19409 F hello.hellofx: java_vm_ext.cc:570]     in call to CallStaticVoidMethod
04-17 17:36:17.669 19409 19409 F hello.hellofx: java_vm_ext.cc:570]     from void com.gluonhq.helloandroid.MainActivity.nativeDispatchLifecycleEvent(java.lang.String)
04-17 17:36:17.699   922  1027 V DisplayPowerController: Brightness [0] reason changing to: 'screen_off', previous reason: 'automatic'.
04-17 17:36:17.701   922   978 I DisplayManagerService: Display device changed state: "Pantalla integrada", OFF
04-17 17:36:17.702   500   500 D SurfaceFlinger: Setting power mode 0 on display 0
04-17 17:36:17.705   502   551 I SDM     : DisplayBase::SetDisplayState: Set state = 0, display 0
04-17 17:36:17.847  1480  1492 I ndroid.systemu: NativeAlloc concurrent copying GC freed 64655(2280KB) AllocSpace objects, 0(0B) LOS objects, 49% free, 6540KB/12MB, paused 76us total 181.550ms
04-17 17:36:17.847  1480  1492 W ndroid.systemu: Reducing the number of considered missed Gc histogram windows from 111 to 100
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630] Runtime aborting...
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630] Dumping all threads without mutator lock held
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630] All threads:
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630] DALVIK THREADS (15):
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630] "main" prio=5 tid=1 Runnable
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   | group="" sCount=0 dsCount=0 flags=0 obj=0x724fdd98 self=0x7c66051000
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   | sysTid=19409 nice=0 cgrp=default sched=0/0 handle=0x7c675a3ed0
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   | state=R schedstat=( 281036245 113944523 267 ) utm=14 stm=12 core=0 HZ=100
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   | stack=0x7fd2d46000-0x7fd2d48000 stackSize=8192KB
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   | held mutexes= "abort lock" "mutator lock"(shared held)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   native: #00 pc 0000000000412794  /apex/com.android.runtime/lib64/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, int, BacktraceMap*, char const*, art::ArtMethod*, void*, bool)+140)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   native: #01 pc 00000000004f9c5c  /apex/com.android.runtime/lib64/libart.so (art::Thread::DumpStack(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, bool, BacktraceMap*, bool) const+508)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   native: #02 pc 000000000051429c  /apex/com.android.runtime/lib64/libart.so (art::DumpCheckpoint::Run(art::Thread*)+812)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   native: #03 pc 000000000050d2f0  /apex/com.android.runtime/lib64/libart.so (art::ThreadList::RunCheckpoint(art::Closure*, art::Closure*)+456)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   native: #04 pc 000000000050c6fc  /apex/com.android.runtime/lib64/libart.so (art::ThreadList::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, bool)+1792)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   native: #05 pc 00000000004b9d8c  /apex/com.android.runtime/lib64/libart.so (art::Runtime::Abort(char const*)+1352)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   native: #06 pc 000000000000c634  /system/lib64/libbase.so (android::base::LogMessage::~LogMessage()+604)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   native: #07 pc 00000000003781f0  /apex/com.android.runtime/lib64/libart.so (art::JavaVMExt::JniAbort(char const*, char const*)+1608)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   native: #08 pc 00000000003bbc0c  /apex/com.android.runtime/lib64/libart.so (art::JNI::CallStaticVoidMethod(_JNIEnv*, _jclass*, _jmethodID*, ...)+1472)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   native: #09 pc 00000000015397ec  /data/app/hello.hellofx-BF1yGdBRyHGdBnQCEs-bjA==/lib/arm64/libsubstrate.so (attach_setLifecycleEvent+448)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   at com.gluonhq.helloandroid.MainActivity.nativeDispatchLifecycleEvent(Native method)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   at com.gluonhq.helloandroid.MainActivity.notifyLifecycleEvent(MainActivity.java:316)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   at com.gluonhq.helloandroid.MainActivity.onPause(MainActivity.java:281)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   at android.app.Activity.performPause(Activity.java:7978)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1507)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   at android.app.ActivityThread.performPauseActivityIfNeeded(ActivityThread.java:4493)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   at android.app.ActivityThread.performPauseActivity(ActivityThread.java:4454)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:4406)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   at android.app.servertransaction.PauseActivityItem.execute(PauseActivityItem.java:46)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
04-17 17:36:17.889 19409 19409 F hello.hellofx: runtime.cc:630]   at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
04-17 17:36:17.890 19409 19409 F hello.hellofx: runtime.cc:630]   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
04-17 17:36:17.890 19409 19409 F hello.hellofx: runtime.cc:630]   at android.os.Handler.dispatchMessage(Handler.java:107)
04-17 17:36:17.890 19409 19409 F hello.hellofx: runtime.cc:630]   at android.os.Looper.loop(Looper.java:214)
04-17 17:36:17.890 19409 19409 F hello.hellofx: runtime.cc:630]   at android.app.ActivityThread.main(ActivityThread.java:7356)
04-17 17:36:17.890 19409 19409 F hello.hellofx: runtime.cc:630]   at java.lang.reflect.Method.invoke(Native method)
04-17 17:36:17.890 19409 19409 F hello.hellofx: runtime.cc:630]   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
04-17 17:36:17.890 19409 19409 F hello.hellofx: runtime.cc:630]   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
04-17 17:36:17.890 19409 19409 F hello.hellofx: runtime.cc:630] 

Silent exceptions if platform implementation is not provided

When DefaultServiceFactory tries to create the service instance, if there is no platform implementation provided, it shouldn't print the stacktrace exception, but fail silently.

It is up to the service consumer to throw an exception if the implementation is mandatory but it wasn't provided.

create a method in util to throw exceptions if needed

On some places in native code, we need to do some checks and on failure, a Java exception needs to be thrown. Instead of having this boilerplate code in all native files, it's better to have a macro in util.c that does this, e.g.

void attachJavaException(JNIEnv *env, const char* msg) {
    jclass rte = env->FindClass("java/lang/RuntimeException");
    env->ThrowNew(rte, msg);
}

fix memory issues in native layers

Currently many env->ReleaseXX statements are put in comments, as they created GC issues (memory that was not allocated was trying to be freed).
This leads to memory leaks. Typically, those leaks can be ignored for the lifecycle of an app, so not high priority.

PushNotifications uses unnecessary additions interface

PushNotifications has an extra interface with the NotificationsAdditions category, that adds two methods.

When linking this with Gluon Substrate if fails to find "_OBJC_CLASS_$_PushNotifications" from l_OBJC_$_CATEGORY_PushNotifications_$_NotificationsAdditions.

Having this extra interface seems not necessary at all, as it doesn't really add any value. The methods could be directly added to the interface PushNotifications.

Playing video shows a black screen until view is refreshed

Using the VideoService to play audio, a view is created, and it should go to the back. However, the first time it is created, it keeps on front, showing a black screen, until the view is refreshed somehow.
A possible workaround: resize the view to 0x0.

Native Callbacks fail if service is started from background thread

Gluon Attach services need to be initialized from the JavaFX thread, in order to perform the callbacks to the same thread

If any service is initialized from another thread (i.e. a background thread), the native part will work, but the callbacks will fail (and the app will crash)

Investigate the use of AttachCurrentThread, or document the use of Platform.isFxApplicationThread() to do the service initialization from Platform.runLater().

Refactor Lifecycle/Util

And set Lifecycle events in Util, so these can be accessed by any service that needs them in the Dalvik side

Add audio player service

A service that allows playing standalone (i.e. not via a video player) sound effects / music.

I originally implemented a working audio service for desktop/android using charm down - fxgl audio plugin. Happy to contribute that as a basis, updating for the general use case as necessary.

Or is this going to be provided by the "client" plugin once media is supported?

Improve warning message when service implementation is missing

Loading an attach service via Services.get() returns an empty Optional if the platform implementation class could not be found. In that case, the following message is logged:

WARNING: No new instance for interface com.gluonhq.attach.storage.StorageService and class com.gluonhq.attach.storage.impl.DesktopStorageService

The meaning of the ClassNotFoundException can have the following causes and the message should be adapted accordingly to give the correct information to the developer:

  1. the platform specific implementation of the service is not included on the classpath, most likely because of a missing project dependency declaration
  2. the service is not yet implemented for the platform
  3. the service is not supported on the platform or doesn't make much sense

Duplicated modules

With the current approach, if we have a service with API and platform implementation, both are using the same module descriptor. For instance, for the Display service:

  • display-4.0.0-SNAPSHOT.jar (API, not empty, module com.gluonhq.attach.display)
  • display-4.0.0-SNAPSHOT-desktop.jar (desktop implementation, module com.gluonhq.attach.display)

This means that when a project requires the Display service:

module moduleName {
    requires com.gluonhq.attach.display;
}

it will get both jars.

While Gradle, luckily, the classpath contains first the desktop jar, and the API is not used (if this wasn't the case, the implementation will be missed).

With Maven, the API is selected first, though, so the implementation is not added and missed on runtime.

We use an "extension" mechanism for the platform service to use the API module definition, where we copy the API classes including the module-info file, but probably we should fine a better way to avoid duplicated names (JavaFX uses "empty" suffix for instance).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.