我正在用3个按钮的简单BasicView测试条形码扫描服务,定位服务和图片服务。条码扫描服务可以,但是pictureservice在AndroidPicturesService.java:132中产生空指针错误。 positionservice一个AndroidRuntimeException:从Activity上下文外部调用startActivity()需要FLAG_ACTIVITY_NEW_TASK标志。在这两种情况下,程序都会中断。
我正在使用org.javafxports:jfxmobile-plugin:1.3.16和com.gluonhq:charm:5.0.2。在Android 4.4.4和Android 8.0中进行了测试,结果相同。该代码是从Api文档复制的。
代码:
Button butFoto = new Button("Photo");
butFoto.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Services.get(PicturesService.class).ifPresent(service -> {
service.takePhoto(false).ifPresent(image -> imageView.setImage(image));
});
}
});
Button butBarcode = new Button("Barcode");
butBarcode.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
String barcodeValue = Services.get(BarcodeScanService.class)
.flatMap(service -> service
.scan("Scan Test", "Place a barcode under the camera", "Barcode found with value"))
.orElse("No barcode found");
System.out.println("Scanned Bar Code: " + barcodeValue);
label2.setText(barcodeValue);
}
});
Button butGPS = new Button("Position");
butGPS.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Services.get(PositionService.class)
.ifPresent(positionService -> {
positionService.start();
ReadOnlyObjectProperty<Position> positionProperty = positionService.positionProperty();
Position position = positionProperty.get();
label2.setText("Lat=" + String.valueOf(position.getLatitude())
+ " Lon=" + String.valueOf(position.getLongitude()));
});
}
});
Android清单:
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.cip.cipgesfx" android:versionCode="1" android:versionName="1.0">
<supports-screens android:xlargeScreens="true"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="21"/>
<application android:label="cipmobile" android:name="android.support.multidex.MultiDexApplication" android:icon="@mipmap/cip_icono">
<activity android:name="javafxports.android.FXActivity" android:label="CipMobile" android:configChanges="orientation|screenSize">
<meta-data android:name="main.class" android:value="com.cipmobile.Cipmobile"/>
<meta-data android:name="debug.port" android:value="0"/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name="com.gluonhq.impl.charm.down.plugins.android.scan.zxing.CaptureActivity"
android:screenOrientation="sensorPortrait"
android:clearTaskOnLaunch="true"
android:stateNotNeeded="true"
android:windowSoftInputMode="stateAlwaysHidden">
<intent-filter>
<action android:name="com.gluonhq.charm.down.plugins.android.scan.SCAN"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity android:name="com.gluonhq.impl.charm.down.plugins.android.PermissionRequestActivity" />
<service android:name="com.gluonhq.impl.charm.down.plugins.android.AndroidPositionBackgroundService"
android:process=":positionBackgroundService" />
</application>
</manifest>
构建Gradle:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.3.16'
}
}
apply plugin: 'org.javafxports.jfxmobile'
repositories {
jcenter()
maven {
url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
}
}
mainClassName = 'com.cip.cipgesfx.IniciarApli'
dependencies {
compile 'com.gluonhq:charm:5.0.2'
compile fileTree(dir: 'lib', include: ['*.jar'])
//compile 'org.eclipse.persistence:org.eclipse.persistence.jpa:2.6.3'
// https://mvnrepository.com/artifact/org.eclipse.persistence/org.eclipse.persistence.jpa
compile group: 'org.eclipse.persistence', name: 'org.eclipse.persistence.jpa', version: '2.7.4'
// https://mvnrepository.com/artifact/org.controlsfx/controlsfx
compile group: 'org.controlsfx', name: 'controlsfx', version: '8.40.14'
// https://mvnrepository.com/artifact/com.google.code.gson/gson
compile group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.8'
}
jfxmobile {
downConfig {
version = '3.8.6'
// Do not edit the line below. Use Gluon Mobile Settings in your project context menu instead
plugins 'barcode-scan', 'display', 'lifecycle', 'pictures', 'position', 'statusbar', 'storage'
}
android {
manifest = 'src/android/AndroidManifest.xml'
dexOptions {
javaMaxHeapSize '3g'
}
androidSdk='/home/cesar/Android/Sdk'
packagingOptions {
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/DEPENDENCIES.txt'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/notice.txt'
exclude 'META-INF/license.txt'
exclude 'META-INF/dependencies.txt'
exclude 'META-INF/INDEX.LIST'
exclude 'META-INF/LGPL2.1'
exclude 'license.html'
exclude 'readme.html'
exclude 'LICENSE.txt'
exclude 'NOTICE.txt'
pickFirst 'META-INF/eclipse.inf'
}
compileSdkVersion=21
}
ios {
infoPList = file('src/ios/Default-Info.plist')
forceLinkClasses = [
'com.gluonhq.**.*',
'javax.annotations.**.*',
'javax.inject.**.*',
'javax.json.**.*',
'org.glassfish.json.**.*'
]
}
}
图片服务的Stacktrace错误:
04-21 19:31:13.678 5482-5514/com.cip.cipgesfx I/GLASS: Call InternalSurfaceView_onMultiTouchEventNative
04-21 19:31:13.678 5482-5514/com.cip.cipgesfx I/GLASS: Glass will pass multitouchevent to monocle with count = 1
04-21 19:31:13.678 5482-5514/com.cip.cipgesfx I/System.out: don't add points, primary = -1
04-21 19:31:13.688 5482-5514/com.cip.cipgesfx I/AndroidPicturesService: Picture file: file:/storage/emulated/0/Pictures/IMG_20190421_193113.jpg
04-21 19:31:13.708 5482-5514/com.cip.cipgesfx E/AndroidRuntime: FATAL EXCEPTION: JavaFX Application Thread
Process: com.cip.cipgesfx, PID: 5482
java.lang.NullPointerException
at android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.java:584)
at android.support.v4.content.FileProvider.getPathStrategy(FileProvider.java:558)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:400)
at com.gluonhq.charm.down.plugins.android.AndroidPicturesService.takePicture(AndroidPicturesService.java:132)
at com.gluonhq.charm.down.plugins.android.AndroidPicturesService.takePhoto(AndroidPicturesService.java:95)
at com.cipmobile.BasicView$2.lambda$handle$1(BasicView.java:50)
at com.cipmobile.BasicView$2$$Lambda$1.accept(BasicView.java)
at java.util.Optional.ifPresent(Optional.java:154)
at com.cipmobile.BasicView$2.handle(BasicView.java:49)
at com.cipmobile.BasicView$2.handle(BasicView.java:46)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Node.fireEvent(Node.java:8411)
at javafx.scene.control.Button.fire(Button.java:185)
at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
位置服务的Stacktrace错误:
04-21 19:33:28.648 5544-5568/com.cip.cipgesfx I/AndroidPositionService: Available location providers on this device: [passive, gps, network].
04-21 19:33:28.648 5544-5568/com.cip.cipgesfx I/AndroidPositionService: Picked network as best location provider.
04-21 19:33:28.648 5544-5568/com.cip.cipgesfx I/AndroidPositionService: Location provider network is not enabled, starting intent to ask user to activate the location provider.
04-21 19:33:28.668 5544-5568/com.cip.cipgesfx E/AndroidRuntime: FATAL EXCEPTION: JavaFX Application Thread
Process: com.cip.cipgesfx, PID: 5544
android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
at android.app.ContextImpl.startActivity(ContextImpl.java:1112)
at android.app.ContextImpl.startActivity(ContextImpl.java:1093)
at android.content.ContextWrapper.startActivity(ContextWrapper.java:311)
at com.gluonhq.charm.down.plugins.android.AndroidPositionService.initialize(AndroidPositionService.java:179)
at com.gluonhq.charm.down.plugins.android.AndroidPositionService.start(AndroidPositionService.java:110)
at com.gluonhq.charm.down.plugins.android.AndroidPositionService.start(AndroidPositionService.java:99)
at com.cipmobile.BasicView$4.lambda$handle$0(BasicView.java:75)
at com.cipmobile.BasicView$4$$Lambda$1.accept(BasicView.java)
at java.util.Optional.ifPresent(Optional.java:154)
at com.cipmobile.BasicView$4.handle(BasicView.java:74)
at com.cipmobile.BasicView$4.handle(BasicView.java:70)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Node.fireEvent(Node.java:8411)
at javafx.scene.control.Button.fire(Button.java:185)
at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
我希望在单击“照片”按钮时打开相机,但会出现异常。单击GPS按钮时也是如此。
答案 0 :(得分:0)
对于像我这样的所有新手,我都要写下正确的代码和配置。它可以在Android 8上正常运行。
public class BasicView extends View {
final Label lblPosition;
public BasicView() {
System.setProperty("com.gluonhq.charm.down.debug", "true"); //*********************** ATTENTION
ImageView imageView = new ImageView();
//setting the fit height and width of the image view
imageView.setFitHeight(200);
imageView.setFitWidth(200);
//Setting the preserve ratio of the image view
imageView.setPreserveRatio(true);
lblPosition = new Label("Auto");
Label lblBarcode = new Label("Barcode");
Label lblManualPosition = new Label("Manual Position");
Button butExit = new Button("Exit");
butExit.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Services.get(LifecycleService.class).ifPresent(lifecycle -> {
lifecycle.shutdown();
});
}
});
Button butPhoto = new Button("Photo");
butPhoto.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Services.get(PicturesService.class).ifPresent(service -> {
service.takePhoto(false).ifPresent(image -> imageView.setImage(image));
});
}
});
Button butBarcode = new Button("Barcode");
butBarcode.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
String barcodeValue = Services.get(BarcodeScanService.class)
.flatMap(service -> service
.scan("Scan Test", "Place a barcode under the camera", "Barcode value:"))
.orElse("No barcode found");
System.out.println("Scanned Bar Code: " + barcodeValue);
lblBarcode.setText(barcodeValue);
}
});
Button butGPS = new Button("Position");
butGPS.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Services.get(PositionService.class)
.ifPresent(service -> {
service.positionProperty().addListener(
(obs, ov, nv)
-> {
lblManualPosition.setText("Lat=" + String.valueOf(nv.getLatitude())
+ " Lon=" + String.valueOf(nv.getLongitude()));
//System.out.printf("Current position: %.5f, %.5f",nv.getLatitude(), nv.getLongitude()));
});
service.start();
});
}
});
VBox controls = new VBox(5);
controls.getChildren().addAll(imageView, lblPosition, lblBarcode, lblManualPosition, butExit, butPhoto, butBarcode, butGPS);
controls.setAlignment(Pos.CENTER);
setCenter(controls);
if (!Services.get(PositionService.class).isPresent()) {
lblPosition.setText("No GPS avalilable");
} else {
lblPosition.setText("Found GPS");
}
}
@Override
protected void updateAppBar(AppBar appBar) {
appBar.setNavIcon(MaterialDesignIcon.MENU.button(e -> System.out.println("Menu")));
appBar.setTitleText("Basic View");
appBar.getActionItems().add(MaterialDesignIcon.SEARCH.button(e -> System.out.println("Search")));
}
}
build.gradle文件:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.3.16'
}
}
apply plugin: 'org.javafxports.jfxmobile'
repositories {
jcenter()
maven {
url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
}
}
mainClassName = 'com.prufx.Prufx'
dependencies {
compile 'com.gluonhq:charm:5.0.2'
}
jfxmobile {
downConfig {
version = '3.8.6'
// Do not edit the line below. Use Gluon Mobile Settings in your project context menu instead
plugins 'barcode-scan', 'display', 'lifecycle', 'pictures', 'position', 'statusbar', 'storage'
}
android {
manifest = 'src/android/AndroidManifest.xml'
dexOptions {
javaMaxHeapSize '3g'
}
compileSdkVersion=28
androidSdk='/home/cesar/Android/Sdk'
}
ios {
infoPList = file('src/ios/Default-Info.plist')
forceLinkClasses = [
'com.gluonhq.**.*',
'javax.annotations.**.*',
'javax.inject.**.*',
'javax.json.**.*',
'org.glassfish.json.**.*'
]
}
}
然后是AndroidManifest.xml:
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.prufx" android:versionCode="1" android:versionName="1.0">
<supports-screens android:xlargeScreens="true"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="21"/>
<application android:label="prufx" android:name="android.support.multidex.MultiDexApplication" android:icon="@mipmap/ic_launcher">
<activity android:name="javafxports.android.FXActivity" android:label="prufx" android:configChanges="orientation|screenSize">
<meta-data android:name="main.class" android:value="com.prufx.Prufx"/>
<meta-data android:name="debug.port" android:value="0"/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name="com.gluonhq.impl.charm.down.plugins.android.PermissionRequestActivity" />
<activity android:name="com.gluonhq.impl.charm.down.plugins.android.scan.zxing.CaptureActivity"
android:screenOrientation="sensorPortrait"
android:clearTaskOnLaunch="true"
android:stateNotNeeded="true"
android:windowSoftInputMode="stateAlwaysHidden">
<intent-filter>
<action android:name="com.gluonhq.charm.down.plugins.android.scan.SCAN"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<service android:name="com.gluonhq.impl.charm.down.plugins.android.AndroidPositionBackgroundService"
android:process=":positionBackgroundService" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.prufx.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider_paths" />
</provider>
</application>
</manifest>