aboutsummaryrefslogtreecommitdiffhomepage
path: root/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers
diff options
context:
space:
mode:
Diffstat (limited to 'platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers')
-rw-r--r--platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/CameraPermissionHelper.java65
-rw-r--r--platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/DisplayRotationHelper.java112
-rw-r--r--platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/FullScreenHelper.java49
-rw-r--r--platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/SnackbarHelper.java113
-rw-r--r--platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/TapHelper.java116
5 files changed, 455 insertions, 0 deletions
diff --git a/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/CameraPermissionHelper.java b/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/CameraPermissionHelper.java
new file mode 100644
index 0000000000..f8e9c33af3
--- /dev/null
+++ b/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/CameraPermissionHelper.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.skar.examples.helloskar.helpers;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.provider.Settings;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.content.ContextCompat;
+
+/**
+ * Helper to ask camera permission.
+ */
+public final class CameraPermissionHelper {
+ private static final int CAMERA_PERMISSION_CODE = 0;
+ private static final String CAMERA_PERMISSION = Manifest.permission.CAMERA;
+
+ /**
+ * Check to see we have the necessary permissions for this app.
+ */
+ public static boolean hasCameraPermission(Activity activity) {
+ return ContextCompat.checkSelfPermission(activity, CAMERA_PERMISSION)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
+ /**
+ * Check to see we have the necessary permissions for this app, and ask for them if we don't.
+ */
+ public static void requestCameraPermission(Activity activity) {
+ ActivityCompat.requestPermissions(
+ activity, new String[]{CAMERA_PERMISSION}, CAMERA_PERMISSION_CODE);
+ }
+
+ /**
+ * Check to see if we need to show the rationale for this permission.
+ */
+ public static boolean shouldShowRequestPermissionRationale(Activity activity) {
+ return ActivityCompat.shouldShowRequestPermissionRationale(activity, CAMERA_PERMISSION);
+ }
+
+ /**
+ * Launch Application Setting to grant permission.
+ */
+ public static void launchPermissionSettings(Activity activity) {
+ Intent intent = new Intent();
+ intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ intent.setData(Uri.fromParts("package", activity.getPackageName(), null));
+ activity.startActivity(intent);
+ }
+}
diff --git a/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/DisplayRotationHelper.java b/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/DisplayRotationHelper.java
new file mode 100644
index 0000000000..7e4ce81c29
--- /dev/null
+++ b/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/DisplayRotationHelper.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.skar.examples.helloskar.helpers;
+
+import android.app.Activity;
+import android.content.Context;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
+import android.view.Display;
+import android.view.WindowManager;
+
+import com.google.ar.core.Session;
+
+/**
+ * Helper to track the display rotations. In particular, the 180 degree rotations are not notified
+ * by the onSurfaceChanged() callback, and thus they require listening to the android display
+ * events.
+ */
+public final class DisplayRotationHelper implements DisplayListener {
+ private boolean viewportChanged;
+ private int viewportWidth;
+ private int viewportHeight;
+ private final Context context;
+ private final Display display;
+
+ /**
+ * Constructs the DisplayRotationHelper but does not register the listener yet.
+ *
+ * @param context the Android {@link Context}.
+ */
+ public DisplayRotationHelper(Context context) {
+ this.context = context;
+ display = context.getSystemService(WindowManager.class).getDefaultDisplay();
+ }
+
+ /**
+ * Registers the display listener. Should be called from {@link Activity#onResume()}.
+ */
+ public void onResume() {
+ context.getSystemService(DisplayManager.class).registerDisplayListener(this, null);
+ }
+
+ /**
+ * Unregisters the display listener. Should be called from {@link Activity#onPause()}.
+ */
+ public void onPause() {
+ context.getSystemService(DisplayManager.class).unregisterDisplayListener(this);
+ }
+
+ /**
+ * Records a change in surface dimensions. This will be later used by {@link
+ * #updateSessionIfNeeded(Session)}. Should be called from {@link
+ * android.opengl.GLSurfaceView.Renderer
+ * #onSurfaceChanged(javax.microedition.khronos.opengles.GL10, int, int)}.
+ *
+ * @param width the updated width of the surface.
+ * @param height the updated height of the surface.
+ */
+ public void onSurfaceChanged(int width, int height) {
+ viewportWidth = width;
+ viewportHeight = height;
+ viewportChanged = true;
+ }
+
+ /**
+ * Updates the session display geometry if a change was posted either by {@link
+ * #onSurfaceChanged(int, int)} call or by {@link #onDisplayChanged(int)} system callback. This
+ * function should be called explicitly before each call to {@link Session#update()}. This
+ * function will also clear the 'pending update' (viewportChanged) flag.
+ *
+ * @param session the {@link Session} object to update if display geometry changed.
+ */
+ public void updateSessionIfNeeded(Session session) {
+ if (viewportChanged) {
+ int displayRotation = display.getRotation();
+ session.setDisplayGeometry(displayRotation, viewportWidth, viewportHeight);
+ viewportChanged = false;
+ }
+ }
+
+ /**
+ * Returns the current rotation state of android display. Same as {@link Display#getRotation()}.
+ */
+ public int getRotation() {
+ return display.getRotation();
+ }
+
+ @Override
+ public void onDisplayAdded(int displayId) {
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ viewportChanged = true;
+ }
+}
diff --git a/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/FullScreenHelper.java b/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/FullScreenHelper.java
new file mode 100644
index 0000000000..3738b963dc
--- /dev/null
+++ b/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/FullScreenHelper.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.skar.examples.helloskar.helpers;
+
+import android.app.Activity;
+import android.view.View;
+import android.view.WindowManager;
+
+/**
+ * Helper to set up the Android full screen mode.
+ */
+public final class FullScreenHelper {
+ /**
+ * Sets the Android fullscreen flags. Expected to be called from {@link
+ * Activity#onWindowFocusChanged(boolean hasFocus)}.
+ *
+ * @param activity the Activity on which the full screen mode will be set.
+ * @param hasFocus the hasFocus flag passed from the {@link Activity#onWindowFocusChanged(boolean
+ * hasFocus)} callback.
+ */
+ public static void setFullScreenOnWindowFocusChanged(Activity activity, boolean hasFocus) {
+ if (hasFocus) {
+ // https://developer.android.com/training/system-ui/immersive.html#sticky
+ activity
+ .getWindow()
+ .getDecorView()
+ .setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+ activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ }
+ }
+}
diff --git a/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/SnackbarHelper.java b/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/SnackbarHelper.java
new file mode 100644
index 0000000000..02393499e9
--- /dev/null
+++ b/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/SnackbarHelper.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.skar.examples.helloskar.helpers;
+
+import android.app.Activity;
+import android.support.design.widget.BaseTransientBottomBar;
+import android.support.design.widget.Snackbar;
+import android.view.View;
+
+/**
+ * Helper to manage the sample snackbar. Hides the Android boilerplate code, and exposes simpler
+ * methods.
+ */
+public final class SnackbarHelper {
+ private static final int BACKGROUND_COLOR = 0xbf323232;
+ private Snackbar messageSnackbar;
+
+ private enum DismissBehavior {HIDE, SHOW, FINISH}
+
+ ;
+
+ public boolean isShowing() {
+ return messageSnackbar != null;
+ }
+
+ /**
+ * Shows a snackbar with a given message.
+ */
+ public void showMessage(Activity activity, String message) {
+ show(activity, message, DismissBehavior.HIDE);
+ }
+
+ /**
+ * Shows a snackbar with a given message, and a dismiss button.
+ */
+ public void showMessageWithDismiss(Activity activity, String message) {
+ show(activity, message, DismissBehavior.SHOW);
+ }
+
+ /**
+ * Shows a snackbar with a given error message. When dismissed, will finish the activity. Useful
+ * for notifying errors, where no further interaction with the activity is possible.
+ */
+ public void showError(Activity activity, String errorMessage) {
+ show(activity, errorMessage, DismissBehavior.FINISH);
+ }
+
+ /**
+ * Hides the currently showing snackbar, if there is one. Safe to call from any thread. Safe to
+ * call even if snackbar is not shown.
+ */
+ public void hide(Activity activity) {
+ activity.runOnUiThread(
+ new Runnable() {
+ @Override
+ public void run() {
+ if (messageSnackbar != null) {
+ messageSnackbar.dismiss();
+ }
+ messageSnackbar = null;
+ }
+ });
+ }
+
+ private void show(
+ final Activity activity, final String message, final DismissBehavior dismissBehavior) {
+ activity.runOnUiThread(
+ new Runnable() {
+ @Override
+ public void run() {
+ messageSnackbar =
+ Snackbar.make(
+ activity.findViewById(android.R.id.content),
+ message,
+ Snackbar.LENGTH_INDEFINITE);
+ messageSnackbar.getView().setBackgroundColor(BACKGROUND_COLOR);
+ if (dismissBehavior != DismissBehavior.HIDE) {
+ messageSnackbar.setAction(
+ "Dismiss",
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ messageSnackbar.dismiss();
+ }
+ });
+ if (dismissBehavior == DismissBehavior.FINISH) {
+ messageSnackbar.addCallback(
+ new BaseTransientBottomBar.BaseCallback<Snackbar>() {
+ @Override
+ public void onDismissed(Snackbar transientBottomBar, int event) {
+ super.onDismissed(transientBottomBar, event);
+ activity.finish();
+ }
+ });
+ }
+ }
+ messageSnackbar.show();
+ }
+ });
+ }
+}
diff --git a/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/TapHelper.java b/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/TapHelper.java
new file mode 100644
index 0000000000..bcbfe2aa98
--- /dev/null
+++ b/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/helpers/TapHelper.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.skar.examples.helloskar.helpers;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnTouchListener;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+
+/**
+ * Helper to detect taps using Android GestureDetector, and pass the taps between UI thread and
+ * render thread.
+ */
+public final class TapHelper implements OnTouchListener {
+ private final GestureDetector gestureDetector;
+ private final BlockingQueue<MotionEvent> queuedSingleTaps = new ArrayBlockingQueue<>(16);
+ private final BlockingQueue<ScrollEvent> queuedFingerHold = new ArrayBlockingQueue<>(16);
+ private boolean isScrolling = false;
+ private boolean previousScroll = true;
+
+ public static class ScrollEvent {
+ public MotionEvent e;
+ public boolean isStartOfScroll;
+
+ public ScrollEvent(MotionEvent e, boolean isStartOfScroll) {
+ this.e = e;
+ this.isStartOfScroll = isStartOfScroll;
+ }
+ }
+
+ /**
+ * Creates the tap helper.
+ *
+ * @param context the application's context.
+ */
+ public TapHelper(Context context) {
+ gestureDetector =
+ new GestureDetector(
+ context,
+ new GestureDetector.SimpleOnGestureListener() {
+ @Override
+ public boolean onSingleTapUp(MotionEvent e) {
+ // Queue tap if there is space. Tap is lost if queue is full.
+ queuedSingleTaps.offer(e);
+ return true;
+ }
+
+ @Override
+ public boolean onScroll (MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+ // Queue motion events when scrolling
+ if (e2.getPointerCount() == 1 && e1.getPointerCount() == 1) {
+ previousScroll = isScrolling;
+ isScrolling = true;
+ queuedFingerHold.offer(new ScrollEvent(e2, startedScrolling()));
+ return true;
+ }
+ return false;
+ }
+
+
+ @Override
+ public boolean onDown(MotionEvent e) {
+ return true;
+ }
+ });
+ }
+
+ /**
+ * Polls for a tap.
+ *
+ * @return if a tap was queued, a MotionEvent for the tap. Otherwise null if no taps are queued.
+ */
+ public MotionEvent poll() {
+ return queuedSingleTaps.poll();
+ }
+
+ public ScrollEvent holdPoll() { return queuedFingerHold.poll(); }
+
+ public boolean startedScrolling() {
+ return isScrolling && !previousScroll;
+ }
+
+ @Override
+ public boolean onTouch(View view, MotionEvent motionEvent) {
+ boolean val = gestureDetector.onTouchEvent(motionEvent);
+
+ // If finger is up + is scrolling: don't scroll anymore, and empty Touch Hold queue
+ if (motionEvent.getAction() == MotionEvent.ACTION_UP && isScrolling) {
+ previousScroll = true;
+ isScrolling = false;
+ queuedFingerHold.clear();
+ }
+ return val;
+ }
+}