Android mediastore action image capture
In this episode of the android camera2 api we respond to an android mediastore action image capture intent for applications that want image capture.
Get Code
The code is now on github you can get it from here
https://github.com/mobapptuts/recyclerview_image_gallery.git Tag camera2-action-image-capture
or else run this command
git clone –branch camera2-action-image-capture https://github.com/mobapptuts/recyclerview_image_gallery.git
Code Samples
We change the applicationId to something more applicable to the camera2 api app
build.gradle
android { compileSdkVersion 22 buildToolsVersion "22.0.1" defaultConfig { applicationId "com.nigelhenshaw.camera2apiapp" minSdkVersion 21 targetSdkVersion 22 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
Change the label and add an intent filter for media action image capture
strings.xml
<resources> <string name="app_name">Camera API APP</string> <string name="hello_world">Hello world!</string> <string name="action_settings">Settings</string> </resources>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="nigelhenshaw.com.cameraintenttutorial" > <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera2.full" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".CamaraIntentActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.media.action.IMAGE_CAPTURE" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> <activity android:name=".SingleImageActivity" /> </application> </manifest>
CamaraIntentActivity
Create two new activity members, one for the Uri sent from the requesting app and the other an activity for passing to the image saver’s thread.
private static Uri mRequestingAppUri; private Activity mActivity;
Pass the activity to the ImageSaver constructor call
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() { @Override public void onImageAvailable(ImageReader reader) { mBackgroundHandler.post(new ImageSaver(mActivity, reader.acquireNextImage())); } };
Inside the ImageSaver class add a local Activity member and initialise it. Then in the ImageSaver run method set the Uri member to null so the app will run in stand alone mode, set the activity result to OK & close the main activity.
private static class ImageSaver implements Runnable { private final Image mImage; private final Activity mActivity; private ImageSaver(Activity activity, Image image) { mActivity = activity; mImage = image; } @Override public void run() { ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer(); byte[] bytes = new byte[byteBuffer.remaining()]; byteBuffer.get(bytes); FileOutputStream fileOutputStream = null; try { fileOutputStream = new FileOutputStream(mImageFile); fileOutputStream.write(bytes); } catch (IOException e) { e.printStackTrace(); } finally { mImage.close(); if(fileOutputStream != null) { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if(mRequestingAppUri != null) { mRequestingAppUri = null; mActivity.setResult(RESULT_OK); mActivity.finish(); } } } }
Inside the onCreate method get the Uri from the intent & initialise the mActivity member
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camara_intent); Intent intent = getIntent(); String action = intent.getAction(); if(MediaStore.ACTION_IMAGE_CAPTURE.equals(action)) { mRequestingAppUri = intent.getParcelableExtra(MediaStore.EXTRA_OUTPUT); } mActivity = this; createImageGallery(); mRecyclerView = (RecyclerView) findViewById(R.id.galleryRecyclerView); GridLayoutManager layoutManager = new GridLayoutManager(this, 1); layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); mRecyclerView.setLayoutManager(layoutManager); RecyclerView.Adapter imageAdapter = new ImageAdapter(sortFilesToLatest(mGalleryFolder), this); mRecyclerView.setAdapter(imageAdapter); final int maxMemorySize = (int) Runtime.getRuntime().maxMemory() / 1024; final int cacheSize = maxMemorySize / 10; mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { @Override protected int sizeOf(String key, Bitmap value) { return value.getByteCount() / 1024; } }; mTextureView = (TextureView) findViewById(R.id.textureView); }
In the takePhoto method check to see if an Uri has been sent and if so create a new file and assign it to mImageFile
public void takePhoto(View view) { try { if(mRequestingAppUri != null) { mImageFile = new File(mRequestingAppUri.getPath()); } else { mImageFile = createImageFile(); } } catch (IOException e) { e.printStackTrace(); } lockFocus(); }