Merge pull request #24622 from alexlyulkov:al/fixed-android-sample-img-save

Fixed problem with saving images in Android sample #24622

Fixes https://github.com/opencv/opencv/issues/24590

Current code for saving images in Android sample worked only on very old phones.
Added support for modern Android versions.

Required:
- https://github.com/opencv/ci-gha-workflow/pull/127
- https://github.com/opencv-infrastructure/opencv-gha-dockerfile/pull/27
This commit is contained in:
alexlyulkov 2023-12-04 15:00:40 +08:00 committed by GitHub
parent 408730b7ab
commit 81656597e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 15 deletions

View File

@ -16,7 +16,7 @@ endif()
set(GRADLE_VERSION "7.6.3" CACHE STRING "Gradle version")
message(STATUS "Gradle version: ${GRADLE_VERSION}")
set(ANDROID_COMPILE_SDK_VERSION "26" CACHE STRING "Android compileSdkVersion")
set(ANDROID_COMPILE_SDK_VERSION "31" CACHE STRING "Android compileSdkVersion")
if(ANDROID_NATIVE_API_LEVEL GREATER 21)
set(ANDROID_MIN_SDK_VERSION "${ANDROID_NATIVE_API_LEVEL}" CACHE STRING "Android minSdkVersion")
else()

View File

@ -157,7 +157,7 @@ def main(args):
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Builds AAR with Java and shared C++ libs from OpenCV SDK")
parser.add_argument('opencv_sdk_path')
parser.add_argument('--android_compile_sdk', default="26")
parser.add_argument('--android_compile_sdk', default="31")
parser.add_argument('--android_min_sdk', default="21")
parser.add_argument('--android_target_sdk', default="31")
parser.add_argument('--java_version', default="1_8")

View File

@ -230,9 +230,9 @@ def main(args):
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Builds AAR with static C++ libs from OpenCV SDK")
parser.add_argument('opencv_sdk_path')
parser.add_argument('--android_compile_sdk', default="26")
parser.add_argument('--android_compile_sdk', default="31")
parser.add_argument('--android_min_sdk', default="21")
parser.add_argument('--android_target_sdk', default="26")
parser.add_argument('--android_target_sdk', default="31")
parser.add_argument('--java_version', default="1_8")
parser.add_argument('--ndk_location', default="")
parser.add_argument('--cmake_location', default="")

View File

@ -13,8 +13,11 @@ import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.hardware.Camera.Size;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
@ -177,10 +180,17 @@ public class Tutorial3Activity extends CameraActivity implements CvCameraViewLis
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.i(TAG,"onTouch event");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permissions, 1);
return false;
}
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
String currentDateandTime = sdf.format(new Date());
String fileName = Environment.getExternalStorageDirectory().getPath() +
"/sample_picture_" + currentDateandTime + ".jpg";
String fileName = "sample_picture_" + currentDateandTime + ".jpg";
mOpenCvCameraView.takePicture(fileName);
Toast.makeText(this, fileName + " saved", Toast.LENGTH_SHORT).show();
return false;

View File

@ -1,14 +1,24 @@
package org.opencv.samples.tutorial3;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Objects;
import org.opencv.android.JavaCameraView;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.AttributeSet;
import android.util.Log;
@ -73,15 +83,36 @@ public class Tutorial3View extends JavaCameraView implements PictureCallback {
mCamera.setPreviewCallback(this);
// Write the image in a file (in jpeg format)
try {
FileOutputStream fos = new FileOutputStream(mPictureFileName);
fos.write(data);
fos.close();
} catch (java.io.IOException e) {
Log.e("PictureDemo", "Exception in photoCallback", e);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
new Thread(new Runnable() {
@Override
public void run() {
ContentResolver resolver = getContext().getContentResolver();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, mPictureFileName);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);
Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
try {
OutputStream fos = resolver.openOutputStream(Objects.requireNonNull(imageUri));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
Objects.requireNonNull(fos).close();
} catch (java.io.IOException e) {
Log.e("PictureDemo", "Exception in photoCallback", e);
}
}
}).start();
} else {
mPictureFileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath()
+ "/" + mPictureFileName;
try {
FileOutputStream fos = new FileOutputStream(mPictureFileName);
fos.write(data);
fos.close();
} catch (java.io.IOException e) {
Log.e("PictureDemo", "Exception in photoCallback", e);
}
}
}
}