Android: Implement vibrate-on-press and dualshock vibration

This commit is contained in:
Connor McLaughlin
2020-11-09 00:35:56 +10:00
parent c1a81aefa4
commit 82ffb1bc81
16 changed files with 616 additions and 497 deletions

View File

@ -15,6 +15,7 @@ public class AndroidHostInterface {
private Context mContext;
static public native String getScmVersion();
static public native AndroidHostInterface create(Context context, String userDirectory);
public AndroidHostInterface(Context context) {
@ -71,7 +72,9 @@ public class AndroidHostInterface {
public native void setDisplayAlignment(int alignment);
public native PatchCode[] getPatchCodeList();
public native void setPatchCodeEnabled(int index, boolean enabled);
public native boolean importPatchCodesFromString(String str);
public native void addOSDMessage(String message, float duration);
@ -81,10 +84,13 @@ public class AndroidHostInterface {
public native String importBIOSImage(byte[] data);
public native boolean isFastForwardEnabled();
public native void setFastForwardEnabled(boolean enabled);
public native String[] getMediaPlaylistPaths();
public native int getMediaPlaylistIndex();
public native boolean setMediaPlaylistIndex(int index);
static {

View File

@ -8,6 +8,7 @@ import android.content.res.Configuration;
import android.hardware.input.InputManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Vibrator;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.View;
@ -124,6 +125,7 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
private void doApplySettings() {
AndroidHostInterface.getInstance().applySettings();
updateRequestedOrientation();
updateControllers();
}
private void applySettings() {
@ -163,9 +165,6 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
doApplySettings();
}
if (AndroidHostInterface.getInstance().isEmulationThreadPaused())
AndroidHostInterface.getInstance().pauseEmulationThread(false);
return;
}
@ -323,8 +322,7 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
private void showMenu() {
if (getBooleanSetting("Main/PauseOnMenu", false) &&
!AndroidHostInterface.getInstance().isEmulationThreadPaused())
{
!AndroidHostInterface.getInstance().isEmulationThreadPaused()) {
AndroidHostInterface.getInstance().pauseEmulationThread(true);
}
@ -485,8 +483,7 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
private void showDiscChangeMenu() {
final String[] paths = AndroidHostInterface.getInstance().getMediaPlaylistPaths();
final int currentPath = AndroidHostInterface.getInstance().getMediaPlaylistIndex();
if (paths == null)
{
if (paths == null) {
onMenuClosed();
return;
}
@ -515,6 +512,8 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
final String controllerType = getStringSetting("Controller1/Type", "DigitalController");
final String viewType = getStringSetting("Controller1/TouchscreenControllerView", "digital");
final boolean autoHideTouchscreenController = getBooleanSetting("Controller1/AutoHideTouchscreenController", false);
final boolean hapticFeedback = getBooleanSetting("Controller1/HapticFeedback", false);
final boolean vibration = getBooleanSetting("Controller1/Vibration", false);
final FrameLayout activityLayout = findViewById(R.id.frameLayout);
Log.i("EmulationActivity", "Controller type: " + controllerType);
@ -526,14 +525,18 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
if (mTouchscreenController != null) {
activityLayout.removeView(mTouchscreenController);
mTouchscreenController = null;
mVibratorService = null;
}
} else {
if (mTouchscreenController == null) {
mTouchscreenController = new TouchscreenControllerView(this);
if (vibration)
mVibratorService = (Vibrator) getSystemService(VIBRATOR_SERVICE);
activityLayout.addView(mTouchscreenController);
}
mTouchscreenController.init(0, controllerType, viewType);
mTouchscreenController.init(0, controllerType, viewType, hapticFeedback);
}
}
@ -578,4 +581,21 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
mInputDeviceListener = null;
}
private Vibrator mVibratorService;
public void setVibration(boolean enabled) {
if (mVibratorService == null)
return;
runOnUiThread(() -> {
if (mVibratorService == null)
return;
if (enabled)
mVibratorService.vibrate(1000);
else
mVibratorService.cancel();
});
}
}

View File

@ -9,19 +9,14 @@ import android.net.Uri;
import android.os.Build;
import android.os.storage.StorageManager;
import android.provider.DocumentsContract;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.nio.charset.Charset;

View File

@ -73,7 +73,9 @@ public class GameListEntry {
return mTitle;
}
public String getFileTitle() { return mFileTitle; }
public String getFileTitle() {
return mFileTitle;
}
public String getModifiedTime() {
return mModifiedTime;

View File

@ -5,6 +5,7 @@ import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.HapticFeedbackConstants;
import android.view.View;
/**
@ -14,6 +15,7 @@ public class TouchscreenControllerButtonView extends View {
private Drawable mUnpressedDrawable;
private Drawable mPressedDrawable;
private boolean mPressed = false;
private boolean mHapticFeedback = false;
private int mControllerIndex = -1;
private int mButtonCode = -1;
@ -81,6 +83,10 @@ public class TouchscreenControllerButtonView extends View {
mPressed = pressed;
invalidate();
updateControllerState();
if (mHapticFeedback) {
performHapticFeedback(pressed ? HapticFeedbackConstants.VIRTUAL_KEY : HapticFeedbackConstants.VIRTUAL_KEY_RELEASE);
}
}
public void setButtonCode(int controllerIndex, int code) {
@ -88,6 +94,10 @@ public class TouchscreenControllerButtonView extends View {
mButtonCode = code;
}
public void setHapticFeedback(boolean enabled) {
mHapticFeedback = enabled;
}
private void updateControllerState() {
if (mButtonCode >= 0)
AndroidHostInterface.getInstance().setControllerButtonState(mControllerIndex, mButtonCode, mPressed);

View File

@ -20,6 +20,7 @@ public class TouchscreenControllerView extends FrameLayout {
private View mMainView;
private ArrayList<TouchscreenControllerButtonView> mButtonViews = new ArrayList<>();
private ArrayList<TouchscreenControllerAxisView> mAxisViews = new ArrayList<>();
private boolean mHapticFeedback;
public TouchscreenControllerView(Context context) {
super(context);
@ -33,9 +34,10 @@ public class TouchscreenControllerView extends FrameLayout {
super(context, attrs, defStyle);
}
public void init(int controllerIndex, String controllerType, String viewType) {
public void init(int controllerIndex, String controllerType, String viewType, boolean hapticFeedback) {
mControllerIndex = controllerIndex;
mControllerType = controllerType;
mHapticFeedback = hapticFeedback;
mButtonViews.clear();
mAxisViews.clear();
@ -99,6 +101,7 @@ public class TouchscreenControllerView extends FrameLayout {
if (code >= 0) {
buttonView.setButtonCode(mControllerIndex, code);
buttonView.setHapticFeedback(mHapticFeedback);
mButtonViews.add(buttonView);
} else {
Log.e("TouchscreenController", String.format("Unknown button name '%s' " +