は、私は上のいくつかのドキュメンテーションとを掘り、AndroidのAPIで遊んで数時間後に解決策を見つけました。
私の解決策は、部分的には、@ホセペレダがトピック"javafxports how to call android native Media Player"で与えた答えに基づいています。
私は "volumeDown" と "ミュート"、タスク "volumeUp" のためのインタフェースを作成しました:
public interface NativeVolumeService {
void volumeUp();
void volumeDown();
void mute();
}
その後、system volume on Androidを設定する方法については、以下の回答に基づいて、 Androidで次の実装を考えました:
import java.util.ArrayList;
import java.util.logging.Logger;
import android.content.Context;
import android.media.AudioManager;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import my.package.platform.NativeVolumeService;
import javafxports.android.FXActivity;
public class NativeVolumeServiceAndroid implements NativeVolumeService {
private static final Logger LOG = Logger.getLogger(NativeVolumeServiceAndroid.class.getName());
private final AudioManager audioManager;
private final int maxVolume;
private int preMuteVolume = 0;
private int currentVolume = 0;
public NativeVolumeServiceAndroid() {
audioManager = (AudioManager) FXActivity.getInstance().getSystemService(Context.AUDIO_SERVICE);
maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
}
@Override
public void volumeUp() {
LOG.info("dispatch volume up event");
KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_VOLUME_UP);
dispatchEvent(event, true, false);
}
@Override
public void volumeDown() {
LOG.info("dispatch volume down event");
KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_VOLUME_DOWN);
dispatchEvent(event, false, false);
}
@Override
public void mute() {
LOG.info("dispatch volume mute event");
KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_VOLUME_MUTE);
dispatchEvent(event, false, true);
}
private void dispatchEvent(KeyEvent event, boolean up, boolean mute) {
// hardware key events (amongst others) get caught by the JavaFXPorts engine (or better: the Dalvik impl from Oracle)
// to circumvent this, we need to do the volume adjustment the hard way: via the AudioManager
// see: https://developer.android.com/reference/android/media/AudioManager.html
// see: https://stackoverflow.com/questions/9164347/setting-the-android-system-volume?rq=1
// reason:
// FXActivity registers a FXDalvikEntity, which etends the surface view and passing a key processor
// called KeyEventProcessor - this one catches all key events and matches them to JavaFX representations.
// Unfortunately, we cannot bypass this, so we need the AudioManager
currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
if (mute) {
if (currentVolume > 0) {
preMuteVolume = currentVolume;
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_SAME,
AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE | AudioManager.FLAG_SHOW_UI);
} else {
preMuteVolume = 0;
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, preMuteVolume, AudioManager.FLAG_SHOW_UI);
}
} else if (up) {
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
(currentVolume + 1) <= maxVolume ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_SAME, AudioManager.FLAG_SHOW_UI);
} else if (!up) {
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
(currentVolume - 1) >= 0 ? AudioManager.ADJUST_LOWER : AudioManager.ADJUST_SAME, AudioManager.FLAG_SHOW_UI);
}
}
}
これを統合するには、私はappropを作成しました私のメインクラスのインスタンスriate(私は世界的にこれを必要とする - あなたが表示されます、なぜ)
private void instantiateNativeVolumeService() {
String serviceName = NativeVolumeService.class.getName();
if (Platform.isDesktop()) {
serviceName += "Desktop";
} else if (Platform.isAndroid()) {
serviceName += "Android";
}
try {
volumeService = (NativeVolumeService) Class.forName(serviceName).newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
LOG.log(Level.SEVERE, "Could not get an instance of NativeAudioService for platform " + Platform.getCurrent(), e);
}
}
volumeService
はクラス変数です。
それから私は私のStage
のScene
のイベントハンドラ登録:
@Override
public void start(Stage stage) throws Exception {
// initiate everything
scene.addEventFilter(KeyEvent.ANY, this::handleGlobalKeyEvents);
// do more stuff, if needed
}
をそして最後に、このようになりますhandleGlobalKeyEvents
方法:最後に
private void handleGlobalKeyEvents(KeyEvent event) {
// use a more specific key event type like
// --> KeyEvent.KEY_RELEASED == event.getEventType()
// --> KeyEvent.KEY_PRESSED == event.getEventType()
// without it, we would react on both events, thus doing one operation too much
if (event.getCode().equals(KeyCode.VOLUME_UP) && KeyEvent.KEY_PRESSED == event.getEventType()) {
if (volumeService != null) {
volumeService.volumeUp();
event.consume();
}
}
if (event.getCode().equals(KeyCode.VOLUME_DOWN) && KeyEvent.KEY_PRESSED == event.getEventType()) {
if (volumeService != null) {
volumeService.volumeDown();
event.consume();
}
}
}
は、解決策は同じくらいきれいですそれはあまりにも複雑ではありません。それが働くまでの道のりはちょっと厄介でした。
@JoséPereda:このソリューションをチャームダウンプラグインなどとして統合したい場合は、気軽にお気軽にご連絡ください。
よろしく、 ダニエル
http://stackoverflow.com/questions/40562263/how-to-play-a-sound-on-android-using-gluon-javafx-project、https://でビットバケット.org/javafxports/android/issues/73/hardware-button-key-events-report – jns
うわー!どのような素晴らしい応答! 2つのリンクを提供するだけで、それは解決されておらず、解決できないことを示唆しているようです。いい加減にして!これは私たちが話しているアンドロイドであり、それは解決可能です! - 私の答えを見て、私はこのトピックを提供します。 – dzim
私は参照してください。とにかくあなた自身の質問に常に答えているので、トピックに関する情報を提供するリンクには興味がありません。 – jns