diff --git a/.gitignore b/.gitignore index cede787..522692d 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,3 @@ Developer-Examples/hmt1developerexamples/build/ Developer-Examples/local.properties hmt1developerexamples/debug/ hmt1developerexamples/release/ -gradle/wrapper/gradle-wrapper.properties diff --git a/build.gradle b/build.gradle index 7487467..5ea9881 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.4.0' + classpath 'com.android.tools.build:gradle:3.4.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7a3265e..f3d88b1 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..ba94df8 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 index cccdd3d..2fe81a7 --- a/gradlew +++ b/gradlew @@ -1,5 +1,21 @@ #!/usr/bin/env sh +# +# Copyright 2015 the original author or authors. +# +# 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 +# +# https://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. +# + ############################################################################## ## ## Gradle start up script for UN*X @@ -28,7 +44,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -109,8 +125,8 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` @@ -138,19 +154,19 @@ if $cygwin ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi @@ -159,14 +175,9 @@ save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } -APP_ARGS=$(save "$@") +APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index f955316..24467a1 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,84 +1,100 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/hmt1developerexamples/build.gradle b/hmt1developerexamples/build.gradle index b858436..492727f 100644 --- a/hmt1developerexamples/build.gradle +++ b/hmt1developerexamples/build.gradle @@ -1,16 +1,14 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 28 + compileSdkVersion 30 defaultConfig { applicationId "com.realwear.hmt1developerexamples" minSdkVersion 23 - buildToolsVersion "25.0.2" - //noinspection ExpiredTargetSdkVersion - targetSdkVersion 28 - versionCode 120 - versionName "1.2.0" + targetSdkVersion 30 + versionCode 1030100 + versionName "1.3.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { @@ -26,7 +24,7 @@ dependencies { implementation 'androidx.core:core:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - androidTestCompile('androidx.test.espresso:espresso-core:3.1.0', { + androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0', { exclude group: 'com.android.support', module: 'support-annotations' }) testImplementation 'junit:junit:4.12' diff --git a/hmt1developerexamples/src/main/AndroidManifest.xml b/hmt1developerexamples/src/main/AndroidManifest.xml index fee8c62..0205e8d 100644 --- a/hmt1developerexamples/src/main/AndroidManifest.xml +++ b/hmt1developerexamples/src/main/AndroidManifest.xml @@ -2,7 +2,6 @@ - + * * Contact info@realwear.com for further information about the use of this code. */ package com.realwear.hmt1developerexamples; +import android.Manifest; import android.app.Activity; +import android.content.pm.PackageManager; import android.media.AudioFormat; import android.media.AudioRecord; import android.media.MediaPlayer; @@ -15,6 +17,7 @@ import android.media.MediaScannerConnection; import android.os.Bundle; import android.os.CountDownTimer; +import android.os.Environment; import android.util.Log; import android.view.View; import android.view.WindowManager; @@ -24,6 +27,10 @@ import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; @@ -34,7 +41,7 @@ import java.util.concurrent.TimeUnit; /** - * Activity that shows how capture audio at different frequencies on a HMT-1 device + * Activity that shows how capture audio at different frequencies on a HMT-1 device. */ public class AudioCaptureActivity extends Activity implements Runnable { private final static String TAG = "HMT1DevApp-Audio"; @@ -59,17 +66,11 @@ public class AudioCaptureActivity extends Activity implements Runnable { private String mSampleRatedString; private short mChannels; private String mChannelsString; - private String mFilename; private AudioRecord mAudioRecorder; private Thread mMotor; - /** - * Called when the activity is created - * - * @param savedInstanceState See Android docs - */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -79,23 +80,27 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.audio_capture_main); - mRecordButton = (Button) findViewById(R.id.recordButton); - mPlaybackButton = (Button) findViewById(R.id.playbackButton); - mProgressBar = (ProgressBar) findViewById(R.id.progressBar); - mFilenameLabel = (TextView) findViewById(R.id.fileTextLabel); + mRecordButton = findViewById(R.id.recordButton); + mPlaybackButton = findViewById(R.id.playbackButton); + mProgressBar = findViewById(R.id.progressBar); + mFilenameLabel = findViewById(R.id.fileTextLabel); + + mMonoButton = findViewById(R.id.monoButton); + mStereoButton = findViewById(R.id.stereoButton); - mMonoButton = (RadioButton) findViewById(R.id.monoButton); - mStereoButton = (RadioButton) findViewById(R.id.stereoButton); + mRate8Button = findViewById(R.id.rate8Button); + mRate16Button = findViewById(R.id.rate16Button); + mRate44Button = findViewById(R.id.rate44Button); + mRate48Button = findViewById(R.id.rate48Button); - mRate8Button = (RadioButton) findViewById(R.id.rate8Button); - mRate16Button = (RadioButton) findViewById(R.id.rate16Button); - mRate44Button = (RadioButton) findViewById(R.id.rate44Button); - mRate48Button = (RadioButton) findViewById(R.id.rate48Button); + // Check that permissions are granted before continuing + if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) + != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions( + this, new String[]{Manifest.permission.RECORD_AUDIO}, 0); + } } - /** - * Called when activity is resumed - See Android docs - */ @Override protected void onResume() { super.onResume(); @@ -104,16 +109,12 @@ protected void onResume() { mPlaybackButton.setEnabled(true); mProgressBar.setVisibility(View.INVISIBLE); mFilenameLabel.setText(""); - mFilename = ""; setButtonState(true); mRate44Button.performClick(); mStereoButton.performClick(); } - /** - * Called when activity is paused - See Android docs - */ @Override protected void onPause() { super.onPause(); @@ -143,12 +144,6 @@ protected void onPause() { * @param view The start record button */ public void onStartRecord(View view) { - mFilename = mFilenameLabel.getText().toString(); - if (mFilename.isEmpty()) { - Toast.makeText(this, "No file to record to", Toast.LENGTH_LONG).show(); - return; - } - int monoOrStereo = mChannels == 1 ? AudioFormat.CHANNEL_IN_MONO : AudioFormat.CHANNEL_IN_STEREO; @@ -182,15 +177,11 @@ public void onStartRecord(View view) { * @param view The start playback button */ public void onStartPlayback(View view) { - mFilename = mFilenameLabel.getText().toString(); - if (mFilename.isEmpty()) { - Toast.makeText(this, "No file to play back", Toast.LENGTH_LONG).show(); - return; - } + final File recordingFile = getRecordingFile(); try { final MediaPlayer mp = new MediaPlayer(); - mp.setDataSource(mFilename); + mp.setDataSource(recordingFile.getAbsolutePath()); mp.prepare(); mp.start(); @@ -252,7 +243,7 @@ public void run() { mAudioRecorder.release(); mAudioRecorder = null; - writeWAVFile(mFilename, bos, bitsPerSecond); + writeWAVFile(getRecordingFile(), bos, bitsPerSecond); } runOnUiThread(new Runnable() { @@ -327,9 +318,18 @@ public void onSampleRateChanged(View view) { * Updated the filename based on the selected settings */ private void updateFileName() { - mFilename = - "/sdcard/music/audio_test_" + mSampleRatedString + "_" + mChannelsString + ".wav"; - mFilenameLabel.setText(mFilename); + mFilenameLabel.setText(getRecordingFile().toString()); + } + + /** + * Get the file that for recording and playing back an audio file based on the current settings. + * + * @return The file that should be used. + */ + private File getRecordingFile() { + final String filename = "audio_test_" + mSampleRatedString + "_" + mChannelsString + ".wav"; + final File mediaStorageDir = getExternalFilesDir(Environment.DIRECTORY_MUSIC); + return new File(mediaStorageDir, filename); } /** @@ -351,18 +351,16 @@ private void setButtonState(boolean isEnabled) { } /** - * Write the recorded audio data to a wav file + * Write the recorded audio data to a wav file. * - * @param filename The path to the file to create - * @param outputStream The recorded audio data + * @param file The file to write audio data to. + * @param outputStream The recorded audio data. */ - private void writeWAVFile( - String filename, ByteArrayOutputStream outputStream, int bitsPerSamples) { - + private void writeWAVFile(File file, ByteArrayOutputStream outputStream, int bitsPerSamples) { byte[] audioData = outputStream.toByteArray(); try { - FileOutputStream fos = new FileOutputStream(filename); + FileOutputStream fos = new FileOutputStream(file); DataOutputStream dos = new DataOutputStream(fos); writeWaveFileHeader(dos, audioData.length, bitsPerSamples); @@ -378,7 +376,6 @@ private void writeWAVFile( Log.e(TAG, "Error writing wav file: ", ex); } - File file = new File(filename); rescanFolder(file.getParent()); } @@ -489,4 +486,17 @@ private static byte[] intToByteArray(int data) { private static byte[] shortToByteArray(short data) { return new byte[]{(byte) (data & 0xff), (byte) ((data >> 8) & 0xff)}; } + + @Override + public void onRequestPermissionsResult( + int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + for (int grantResult : grantResults) { + if (grantResult != PackageManager.PERMISSION_GRANTED) { + setResult(-1); + Toast.makeText(this, R.string.permissions_error, Toast.LENGTH_LONG).show(); + finish(); + } + } + } } diff --git a/hmt1developerexamples/src/main/java/com/realwear/hmt1developerexamples/CameraActivity.java b/hmt1developerexamples/src/main/java/com/realwear/hmt1developerexamples/CameraActivity.java index 2d90d50..c428324 100644 --- a/hmt1developerexamples/src/main/java/com/realwear/hmt1developerexamples/CameraActivity.java +++ b/hmt1developerexamples/src/main/java/com/realwear/hmt1developerexamples/CameraActivity.java @@ -1,43 +1,57 @@ -/** - * RealWear Development Software, Source Code and Object Code +/* + * RealWear Development Software, Source Code and Object Code. * (c) RealWear, Inc. All rights reserved. - *

+ * * Contact info@realwear.com for further information about the use of this code. */ package com.realwear.hmt1developerexamples; import android.app.Activity; +import android.content.ContentValues; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; -import androidx.core.content.FileProvider; + +import android.util.Log; import android.view.View; import android.view.WindowManager; import android.widget.ImageView; -import java.io.File; import java.util.UUID; import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION; /** - * Activity that shows how to use the camera to take a picture on a HMT-1 device + * Activity that shows how to use the camera to take a pictures and record videos on a HMT-1 device. */ public class CameraActivity extends Activity { + private static final String TAG = "CameraActivity"; + + // Request code for playing back videos. + private static final int FILE_PLAYBACK_REQUEST_CODE = 5; - // Request code identifying camera events - private static final int BASIC_CAMERA_REQUEST_CODE = 1889; - private static final int FILEPROVIDER_CAMERA_REQUEST_CODE = 1998; + // + // Request codes for identifying camera events. + // + private static final int BITMAP_PHOTO_REQUEST_CODE = 1; + private static final int FILE_PROVIDER_PHOTO_REQUEST_CODE = 2; + private static final int BASIC_VIDEO_REQUEST_CODE = 3; + private static final int FILE_PROVIDER_VIDEO_REQUEST_CODE = 4; + + // + // Locations for store content provided images and videos. + // + private static final String DEFAULT_IMAGE_LOCATION = Environment.DIRECTORY_DCIM + "/Camera"; + private static final String DEFAULT_VIDEO_LOCATION = Environment.DIRECTORY_MOVIES + "/Camera"; // Identifier for the image returned by the camera private static final String EXTRA_RESULT = "data"; private ImageView mImageView; - private Uri contentUri; /** * Called when the activity is created @@ -53,66 +67,107 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.camera_main); - mImageView = (ImageView) findViewById(R.id.camera_image_view); + mImageView = findViewById(R.id.camera_image_view); } /** - * Listener for when the basic camera button is clicked + * Listener for when the bitmap photo button is clicked. * - * @param view The launch camera button + * @param view The button. */ - public void onLaunchCameraBasic(View view) { - Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // OR ACTION_VIDEO_CAPTURE - startActivityForResult(intent, BASIC_CAMERA_REQUEST_CODE); + public void onLaunchBitmapPhoto(View view) { + final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + startActivityForResult(intent, BITMAP_PHOTO_REQUEST_CODE); } /** - * Listener for when the FileProvider camera button is clicked + * Listener for when the file provider photo button is clicked. * - * @param view The FileProvider camera button + * @param view The button. */ - public void onLaunchCameraFileProvider(View view) { + public void onLaunchFileProviderPhoto(View view) { + final String fileName = "devexamples-" + UUID.randomUUID() + ".jpg"; - final File mediaStorageDir = getExternalFilesDir(Environment.DIRECTORY_DCIM); + final ContentValues contentValues = new ContentValues(); + contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName); + contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg"); + contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, DEFAULT_IMAGE_LOCATION); - final File file = new File(mediaStorageDir, "devexamples-" + UUID.randomUUID() + ".jpg"); + final Uri contentUri = getBaseContext().getContentResolver().insert( + MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); - contentUri = FileProvider.getUriForFile( - getApplicationContext(), - getApplicationContext().getPackageName() + ".fileprovider", - file); + final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + captureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri); - final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // OR ACTION_VIDEO_CAPTURE - captureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri); + startActivityForResult(captureIntent, FILE_PROVIDER_PHOTO_REQUEST_CODE); + } - startActivityForResult(captureIntent, FILEPROVIDER_CAMERA_REQUEST_CODE); + /** + * Listener for when the bitmap photo button is clicked. + * + * @param view The button. + */ + public void onLaunchBasicVideo(View view) { + final Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); + startActivityForResult(intent, BASIC_VIDEO_REQUEST_CODE); + } + + /** + * Listener for when the file provider video button is clicked. + * + * @param view The button. + */ + public void onLaunchFileProviderVideo(View view) { + final String fileName = "devexamples-" + UUID.randomUUID() + ".mp4"; + + final ContentValues contentValues = new ContentValues(); + contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName); + contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4"); + contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, DEFAULT_VIDEO_LOCATION); + + final Uri contentUri = getBaseContext().getContentResolver().insert( + MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues); + + final Intent captureIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); + captureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri); + + startActivityForResult(captureIntent, FILE_PROVIDER_VIDEO_REQUEST_CODE); } /** * Listener for result from external activities. Receives image data from camera. * - * @param requestCode See Android docs - * @param resultCode See Android docs - * @param data See Android docs + * @param requestCode See Android docs. + * @param resultCode See Android docs. + * @param data See Android docs. */ public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == Activity.RESULT_OK && data != null) { - switch(requestCode) { - case BASIC_CAMERA_REQUEST_CODE: // Display Bitmap received from Camera - Bitmap photo = data.getExtras().getParcelable(EXTRA_RESULT); + switch (requestCode) { + case BITMAP_PHOTO_REQUEST_CODE: + final Bitmap photo = data.getExtras().getParcelable(EXTRA_RESULT); mImageView.setImageBitmap(photo); break; - case FILEPROVIDER_CAMERA_REQUEST_CODE: // View saved file in DocumentViewer + case FILE_PROVIDER_PHOTO_REQUEST_CODE: + final Uri photoUri = data.getData(); + mImageView.setImageURI(photoUri); + break; - Intent intent = new Intent(); - intent.setAction(Intent.ACTION_VIEW); - intent.addFlags(FLAG_GRANT_READ_URI_PERMISSION); - intent.setDataAndType(contentUri, "image/*"); - intent.putExtra("zoom","2"); + case BASIC_VIDEO_REQUEST_CODE: + case FILE_PROVIDER_VIDEO_REQUEST_CODE: + final Uri videoUri = data.getData(); - startActivityForResult(intent, 1234); + final Intent basicVideoPlayIntent = new Intent(); + basicVideoPlayIntent.setAction(Intent.ACTION_VIEW); + basicVideoPlayIntent.addFlags(FLAG_GRANT_READ_URI_PERMISSION); + basicVideoPlayIntent.setDataAndType(videoUri, "video/*"); + startActivityForResult(basicVideoPlayIntent, FILE_PLAYBACK_REQUEST_CODE); + break; + default: + Log.e(TAG, "Unknown request code: " + requestCode); break; } } diff --git a/hmt1developerexamples/src/main/java/com/realwear/hmt1developerexamples/MainActivity.java b/hmt1developerexamples/src/main/java/com/realwear/hmt1developerexamples/MainActivity.java index f98de0f..f0ba13c 100644 --- a/hmt1developerexamples/src/main/java/com/realwear/hmt1developerexamples/MainActivity.java +++ b/hmt1developerexamples/src/main/java/com/realwear/hmt1developerexamples/MainActivity.java @@ -1,31 +1,28 @@ -/** - * RealWear Development Software, Source Code and Object Code +/* + * RealWear Development Software, Source Code and Object Code. * (c) RealWear, Inc. All rights reserved. - *

+ * * Contact info@realwear.com for further information about the use of this code. */ package com.realwear.hmt1developerexamples; import android.app.Activity; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import android.os.Bundle; +import android.util.Log; import android.view.View; import android.view.WindowManager; import android.widget.GridView; +import android.widget.TextView; /** - * Main activity which displays a list of examples to the user + * Main activity which displays a list of examples to the user. */ public class MainActivity extends Activity { + private static final String TAG = "DevEx"; - private MainMenuTileAdaptor mMainMenuTileAdaptor; - private GridView mGridView; - - /** - * Called when the activity is created - * - * @param savedInstanceState See Android docs - */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -35,24 +32,54 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_main); - View[] tileList = new View[12]; - tileList[0] = new MainMenuTile(this, R.string.action_button_command, R.drawable.action_button, "ActionButtonActivity"); - tileList[1] = new MainMenuTile(this, R.string.camera_command, R.drawable.camera, "CameraActivity"); - tileList[2] = new MainMenuTile(this, R.string.document_command, R.drawable.document, "DocumentActivity"); - tileList[3] = new MainMenuTile(this, R.string.movie_command, R.drawable.movie, "MovieActivity"); - tileList[4] = new MainMenuTile(this, R.string.barcode_command, R.drawable.barcode, "BarcodeActivity"); - - tileList[5] = new MainMenuTile(this, R.string.asr_command, R.drawable.asr, "SpeechRecognizerActivity"); - tileList[6] = new MainMenuTile(this, R.string.dication_command, R.drawable.dictation, "DictationActivity"); - tileList[7] = new MainMenuTile(this, R.string.tts_command, R.drawable.tts, "TTSActivity"); - tileList[8] = new MainMenuTile(this, R.string.mute_command, R.drawable.microphone_off, "MicrophoneReleaseActivity"); - tileList[9] = new MainMenuTile(this, R.string.audio_command, R.drawable.asr, "AudioCaptureActivity"); - - tileList[10] = new MainMenuTile(this, R.string.showhelp_command, R.drawable.show_help, "ShowHelpActivity"); - tileList[11] = new MainMenuTile(this, R.string.bnf_command, R.drawable.ic_format_quote_black_24dp, "BNFGrammarActivity"); - - mMainMenuTileAdaptor = new MainMenuTileAdaptor(tileList); - mGridView = (GridView) findViewById(R.id.gridView); - mGridView.setAdapter(mMainMenuTileAdaptor); + final View[] tileList = new View[]{ + createMenuTile(R.string.action_button_command, R.drawable.action_button, "ActionButtonActivity"), + createMenuTile(R.string.camera_command, R.drawable.camera, "CameraActivity"), + createMenuTile(R.string.document_command, R.drawable.document, "DocumentActivity"), + createMenuTile(R.string.movie_command, R.drawable.movie, "MovieActivity"), + createMenuTile(R.string.barcode_command, R.drawable.barcode, "BarcodeActivity"), + + createMenuTile(R.string.asr_command, R.drawable.asr, "SpeechRecognizerActivity"), + createMenuTile(R.string.dication_command, R.drawable.dictation, "DictationActivity"), + createMenuTile(R.string.tts_command, R.drawable.tts, "TTSActivity"), + createMenuTile(R.string.mute_command, R.drawable.microphone_off, "MicrophoneReleaseActivity"), + createMenuTile(R.string.audio_command, R.drawable.asr, "AudioCaptureActivity"), + + createMenuTile(R.string.showhelp_command, R.drawable.show_help, "ShowHelpActivity"), + createMenuTile(R.string.bnf_command, R.drawable.ic_format_quote_black_24dp, "BNFGrammarActivity") + }; + + final MainMenuTileAdaptor mainMenuTileAdaptor = new MainMenuTileAdaptor(tileList); + final GridView gridView = findViewById(R.id.gridView); + gridView.setAdapter(mainMenuTileAdaptor); + + showAppVersion(); + } + + /** + * Create a menu tile button. + * + * @param voiceCommand The voice command for the tile. + * @param icon The icon for the tile. + * @param activity The activity to launch when the tile is selected. + * @return The created tile. + */ + private MainMenuTile createMenuTile(int voiceCommand, int icon, String activity) { + return new MainMenuTile(this, voiceCommand, icon, activity); + } + + /** + * Show the current version number. + */ + private void showAppVersion() { + final TextView versionTextView = findViewById(R.id.versionTextField); + + try { + final PackageInfo packageInfo = getBaseContext().getPackageManager().getPackageInfo( + getBaseContext().getPackageName(), 0); + versionTextView.setText("version: " + packageInfo.versionName); + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "Failed to display version number", e); + } } } diff --git a/hmt1developerexamples/src/main/res/layout/activity_main.xml b/hmt1developerexamples/src/main/res/layout/activity_main.xml index 3b622b7..6ab3d55 100644 --- a/hmt1developerexamples/src/main/res/layout/activity_main.xml +++ b/hmt1developerexamples/src/main/res/layout/activity_main.xml @@ -21,7 +21,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" - android:text="version: 1.2" + android:text="version: 1.3.0" android:textSize="18sp" /> diff --git a/hmt1developerexamples/src/main/res/layout/camera_main.xml b/hmt1developerexamples/src/main/res/layout/camera_main.xml index 612fdf7..0199bdf 100644 --- a/hmt1developerexamples/src/main/res/layout/camera_main.xml +++ b/hmt1developerexamples/src/main/res/layout/camera_main.xml @@ -1,12 +1,10 @@ - + + +