[
  {
    "path": ".gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n.externalNativeBuild\n# User-specific configurations\n.idea/libraries/\n.idea/workspace.xml\n.idea/tasks.xml\n.idea/.name\n.idea/compiler.xml\n.idea/copyright/profiles_settings.xml\n.idea/encodings.xml\n.idea/misc.xml\n.idea/modules.xml\n.idea/scopes/scope_settings.xml\n.idea/dictionaries\n.idea/vcs.xml\n.idea/jsLibraryMappings.xml\n.idea/datasources.xml\n.idea/dataSources.ids\n.idea/sqlDataSources.xml\n.idea/dynamic.xml\n.idea/uiDesigner.xml\n"
  },
  {
    "path": ".idea/gradle.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"GradleSettings\">\n    <option name=\"linkedExternalProjectsSettings\">\n      <GradleProjectSettings>\n        <option name=\"distributionType\" value=\"DEFAULT_WRAPPED\" />\n        <option name=\"externalProjectPath\" value=\"$PROJECT_DIR$\" />\n        <option name=\"modules\">\n          <set>\n            <option value=\"$PROJECT_DIR$\" />\n            <option value=\"$PROJECT_DIR$/app\" />\n          </set>\n        </option>\n        <option name=\"resolveModulePerSourceSet\" value=\"false\" />\n      </GradleProjectSettings>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/runConfigurations.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"RunConfigurationProducerService\">\n    <option name=\"ignoredProducers\">\n      <set>\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer\" />\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer\" />\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer\" />\n      </set>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".travis.yml",
    "content": "language: android\njdk: oraclejdk8\nenv:\nandroid:\n  components:\n  - tools\n  - build-tools-25.0.2\n  - android-25\n  - platform-tools\n  - extra-android-m2repository\nbefore_install:\n  - chmod +x gradlew\ninstall:\n  - echo y | android update sdk -u -a -t tools\n  - echo y | android update sdk -u -a -t platform-tools\n  - echo y | android update sdk -u -a -t build-tools-25.0.2\n  - echo y | android update sdk -u -a -t android-25\n  - echo y | android update sdk -u -a -t extra-google-m2repository\n  - echo y | android update sdk -u -a -t extra-android-m2repository\nscript:\n  - ./gradlew assembleRelease\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019 Hamed ZITOUN <zitoun.hamed@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<img align=\"right\" width=\"200\" height=\"200\" src=\"https://user-images.githubusercontent.com/34313493/44617202-8d051180-a880-11e8-8788-b52580aea56e.jpg\">\n\n[![Build Status](https://travis-ci.org/hzitoun/android-camera2-secret-picture-taker.svg?branch=master)](https://travis-ci.org/hzitoun/android-camera2-secret-picture-taker)\n\n# 📸 Android Camera2 Secret Picture Taker (AC2SPT) \n\nTake pictures secretly (without preview or launching device's camera app) from all available cameras using Android CAMERA2 API.\nThe <a href=\"https://developer.android.com/reference/android/hardware/camera2/package-summary.html\">Camera2 API</a> replaces the deprecated Camera class.\n___\n\n## How can I support this project?\n- If you have enjoyed the project and it helped you creating a project, building an app, starting a business. You could encourage and support me on patreon https://www.patreon.com/hzitoun 🤗 !  \n- Star this GitHub repo :star:\n- Create pull requests, submit bugs, suggest new features or documentation updates :wrench:\n\n## Usage\n\n1. Implement the interface <a href=\"https://github.com/hzitoun/android-camera2-secret-picture-taker/blob/master/app/src/main/java/com/hzitoun/camera2SecretPictureTaker/listeners/PictureCapturingListener.java\">```PictureCapturingListener```</a> (your capture listener) and override the following methods:\n    -  **void onDoneCapturingAllPhotos(TreeMap<String, byte[]> picturesTaken)** which is called when we've done taking pictures from ALL available cameras OR when NO camera was detected on the device;\n    -  **void onCaptureDone(String pictureUrl, byte[] pictureData)** to get a couple (picture Url, picture Data). Use this method if you don't want to wait for ALL pictures to be ready;\n2. Create a new instance of <a href=\"https://github.com/hzitoun/android-camera2-secret-picture-taker/blob/master/app/src/main/java/com/hzitoun/camera2SecretPictureTaker/services/APictureCapturingService.java\">```APictureCapturingService``` </a> using <a href=\"https://github.com/hzitoun/android-camera2-secret-picture-taker/blob/master/app/src/main/java/com/hzitoun/camera2SecretPictureTaker/services/PictureCapturingServiceImpl.java\">```PictureCapturingServiceImpl#getInstance()```</a> method;\n3. **Start capture** by calling the method ```APictureCapturingService#startCapturing(PictureCapturingListener listener) ``` and pass the listener you've just implemented (**step 1**)\n\n## Sample\n\nHere, I've chosen to just  display the two pictures taken within a vertical linear layout. Here is a code snippet of how to use the service:\n\n```java\npublic class MainActivity extends AppCompatActivity implements PictureCapturingListener, ActivityCompat.OnRequestPermissionsResultCallback {\n     private APictureCapturingService pictureService;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n        //check for camera and external storage permissions\n        checkPermissions();\n        final Button btn = (Button) findViewById(R.id.startCaptureBtn);\n        pictureService = PictureCapturingServiceImpl.getInstance(this);\n        //start capturing when clicking on the button\n        btn.setOnClickListener(v ->\n                pictureService.startCapturing(this)\n        );\n    }\n\n    @Override\n    public void onDoneCapturingAllPhotos(TreeMap<String, byte[]> picturesTaken) {\n        if (picturesTaken != null && !picturesTaken.isEmpty()) {\n            picturesTaken.forEach((pictureUrl, pictureData) -> {\n               //convert the byte array 'pictureData' to a bitmap (no need to read the file from the external storage) but in case you\n               //You can also use 'pictureUrl' which stores the picture's location on the device\n                final Bitmap bitmap = BitmapFactory.decodeByteArray(pictureData, 0, pictureData.length);\n            });\n            showToast(\"Done capturing all photos!\");\n            return;\n        }\n        showToast(\"No camera detected!\");\n    }\n\n    @Override\n    public void onCaptureDone(String pictureUrl, byte[] pictureData) {\n        if (pictureData != null && pictureUrl != null) {\n            runOnUiThread(() -> {\n                //convert byte array 'pictureData' to a bitmap (no need to read the file from the external storage)\n                final Bitmap bitmap = BitmapFactory.decodeByteArray(pictureData, 0, pictureData.length);\n                //scale image to avoid POTENTIAL \"Bitmap too large to be uploaded into a texture\" when displaying into an ImageView\n                final int nh = (int) (bitmap.getHeight() * (512.0 / bitmap.getWidth()));\n                final Bitmap scaled = Bitmap.createScaledBitmap(bitmap, 512, nh, true);\n               //do whatever you want with the bitmap or the scaled one...\n            });\n            showToast(\"Picture saved to \" + pictureUrl);\n        }\n    }\n    \n    private void showToast(final String text) {\n        runOnUiThread(() ->\n                Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show()\n        );\n    }\n\n}\n```\n\nThanks to [maaudrana](https://github.com/maaudrana) for the logo :)\n\n## Contributors\n\nHamed ZITOUN <zitoun.hamed@gmail.com>\n\n## Help\n\nIf you run into issues, please don't hesitate to find help on the GitHub project.\n\n## License\n\nThe android-camera2-secret-picture-taker is covered by the MIT License.\n\nThe MIT License (MIT)\n\nCopyright (c) 2022 Hamed ZITOUN and contributors to the android-camera2-secret-picture-taker project.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n"
  },
  {
    "path": "app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "app/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 25\n    buildToolsVersion \"25.0.2\"\n    defaultConfig {\n        applicationId \"com.hzitoun.camera2secretpicturetaker\"\n        minSdkVersion 21\n        targetSdkVersion 25\n        versionCode 2\n        versionName \"1.0.1\"\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n        jackOptions {\n            enabled true\n        }\n    }\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n}\n\ndependencies {\n    compile fileTree(dir: 'libs', include: ['*.jar'])\n    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {\n        exclude group: 'com.android.support', module: 'support-annotations'\n    })\n    compile 'com.android.support:appcompat-v7:25.1.0'\n    testCompile 'junit:junit:4.12'\n}\n"
  },
  {
    "path": "app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in C:\\Users\\hamed\\AppData\\Local\\Android\\Sdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "app/src/androidTest/java/com/hzitoun/camera2SecretPictureTaker/ExampleInstrumentedTest.java",
    "content": "package com.hzitoun.camera2SecretPictureTaker;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistry;\nimport android.support.test.runner.AndroidJUnit4;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport static org.junit.Assert.*;\n\n/**\n * Instrumentation test, which will execute on an Android device.\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\n@RunWith(AndroidJUnit4.class)\npublic class ExampleInstrumentedTest {\n    @Test\n    public void useAppContext() throws Exception {\n        // Context of the app under test.\n        Context appContext = InstrumentationRegistry.getTargetContext();\n\n        assertEquals(\"com.hzitoun.camera2secretpicturetaker\", appContext.getPackageName());\n    }\n}\n"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.hzitoun.camera2SecretPictureTaker\">\n\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />\n    <uses-permission android:name=\"android.permission.CAMERA\" />\n\n    <uses-feature android:name=\"android.hardware.camera\" />\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\">\n        <activity\n            android:name=\"com.hzitoun.camera2SecretPictureTaker.activities.MainActivity\"\n            android:configChanges=\"keyboardHidden|orientation|screenSize\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>"
  },
  {
    "path": "app/src/main/java/com/hzitoun/camera2SecretPictureTaker/activities/MainActivity.java",
    "content": "package com.hzitoun.camera2SecretPictureTaker.activities;\n\nimport android.Manifest;\nimport android.annotation.TargetApi;\nimport android.content.pm.PackageManager;\nimport android.graphics.Bitmap;\nimport android.graphics.BitmapFactory;\nimport android.os.Build;\nimport android.os.Bundle;\nimport android.support.annotation.NonNull;\nimport android.support.v4.app.ActivityCompat;\nimport android.support.v4.content.ContextCompat;\nimport android.support.v7.app.AppCompatActivity;\nimport android.widget.Button;\nimport android.widget.ImageView;\nimport android.widget.Toast;\n\nimport com.hzitoun.camera2SecretPictureTaker.R;\nimport com.hzitoun.camera2SecretPictureTaker.listeners.PictureCapturingListener;\nimport com.hzitoun.camera2SecretPictureTaker.services.APictureCapturingService;\nimport com.hzitoun.camera2SecretPictureTaker.services.PictureCapturingServiceImpl;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.TreeMap;\n\n\n/**\n * App's Main Activity showing a simple usage of the picture taking service.\n * @author hzitoun (zitoun.hamed@gmail.com)\n */\npublic class MainActivity extends AppCompatActivity implements PictureCapturingListener, ActivityCompat.OnRequestPermissionsResultCallback {\n\n    private static final String[] requiredPermissions = {\n                Manifest.permission.WRITE_EXTERNAL_STORAGE,\n                Manifest.permission.CAMERA,\n    };\n    private static final int MY_PERMISSIONS_REQUEST_ACCESS_CODE = 1;\n\n    private ImageView uploadBackPhoto;\n    private ImageView uploadFrontPhoto;\n    \n     //The capture service          \n    private APictureCapturingService pictureService;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n        checkPermissions();\n        uploadBackPhoto = (ImageView) findViewById(R.id.backIV);\n        uploadFrontPhoto = (ImageView) findViewById(R.id.frontIV);\n        final Button btn = (Button) findViewById(R.id.startCaptureBtn);\n        // getting instance of the Service from PictureCapturingServiceImpl\n        pictureService = PictureCapturingServiceImpl.getInstance(this);\n        btn.setOnClickListener(v -> {\n               showToast(\"Starting capture!\");\n               pictureService.startCapturing(this);\n        });\n    }\n    \n    private void showToast(final String text) {\n        runOnUiThread(() ->\n                Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show()\n        );\n    }\n\n    /**\n    * We've finished taking pictures from all phone's cameras\n    */    \n    @Override\n    public void onDoneCapturingAllPhotos(TreeMap<String, byte[]> picturesTaken) {\n        if (picturesTaken != null && !picturesTaken.isEmpty()) {\n            showToast(\"Done capturing all photos!\");\n            return;\n        }\n        showToast(\"No camera detected!\");\n    }\n\n    /**\n    * Displaying the pictures taken.\n    */             \n    @Override\n    public void onCaptureDone(String pictureUrl, byte[] pictureData) {\n        if (pictureData != null && pictureUrl != null) {\n            runOnUiThread(() -> {\n                final Bitmap bitmap = BitmapFactory.decodeByteArray(pictureData, 0, pictureData.length);\n                final int nh = (int) (bitmap.getHeight() * (512.0 / bitmap.getWidth()));\n                final Bitmap scaled = Bitmap.createScaledBitmap(bitmap, 512, nh, true);\n                if (pictureUrl.contains(\"0_pic.jpg\")) {\n                    uploadBackPhoto.setImageBitmap(scaled);\n                } else if (pictureUrl.contains(\"1_pic.jpg\")) {\n                    uploadFrontPhoto.setImageBitmap(scaled);\n                }\n            });\n            showToast(\"Picture saved to \" + pictureUrl);\n        }\n    }\n\n    @Override\n    public void onRequestPermissionsResult(int requestCode,\n                                           @NonNull String permissions[], @NonNull int[] grantResults) {\n        switch (requestCode) {\n            case MY_PERMISSIONS_REQUEST_ACCESS_CODE: {\n                if (!(grantResults.length > 0\n                        && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {\n                    checkPermissions();\n                }\n            }\n        }\n    }\n\n    /**\n     * checking  permissions at Runtime.\n     */\n    @TargetApi(Build.VERSION_CODES.M)\n    private void checkPermissions() {\n        final List<String> neededPermissions = new ArrayList<>();\n        for (final String permission : requiredPermissions) {\n            if (ContextCompat.checkSelfPermission(getApplicationContext(),\n                    permission) != PackageManager.PERMISSION_GRANTED) {\n                neededPermissions.add(permission);\n            }\n        }\n        if (!neededPermissions.isEmpty()) {\n            requestPermissions(neededPermissions.toArray(new String[]{}),\n                    MY_PERMISSIONS_REQUEST_ACCESS_CODE);\n        }\n    }\n}\n\n"
  },
  {
    "path": "app/src/main/java/com/hzitoun/camera2SecretPictureTaker/listeners/PictureCapturingListener.java",
    "content": "package com.hzitoun.camera2SecretPictureTaker.listeners;\n\nimport java.util.TreeMap;\n\n/**\n * Picture capturing listener\n *\n * @author hzitoun (zitoun.hamed@gmail.com)\n */\npublic interface PictureCapturingListener {\n\n    /**\n     * a callback called when we've done taking a picture from a single camera\n     * (use this method if you don't want to wait for ALL taken pictures to be ready @see onDoneCapturingAllPhotos)\n     *\n     * @param pictureUrl  taken picture's location on the device\n     * @param pictureData taken picture's data as a byte array\n     */\n    void onCaptureDone(String pictureUrl, byte[] pictureData);\n\n    /**\n     * a callback called when we've done taking pictures from ALL AVAILABLE cameras\n     * OR when NO camera was detected on the device\n     *\n     * @param picturesTaken : a  Map<PictureUrl, PictureData>\n     */\n    void onDoneCapturingAllPhotos(TreeMap<String, byte[]> picturesTaken);\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/hzitoun/camera2SecretPictureTaker/services/APictureCapturingService.java",
    "content": "package com.hzitoun.camera2SecretPictureTaker.services;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.hardware.camera2.CameraManager;\nimport android.util.SparseIntArray;\nimport android.view.Surface;\n\nimport com.hzitoun.camera2SecretPictureTaker.listeners.PictureCapturingListener;\n\n/**\n * Abstract Picture Taking Service.\n *\n * @author hzitoun (zitoun.hamed@gmail.com)\n */\npublic abstract class APictureCapturingService {\n\n    private static final SparseIntArray ORIENTATIONS = new SparseIntArray();\n\n    static {\n        ORIENTATIONS.append(Surface.ROTATION_0, 90);\n        ORIENTATIONS.append(Surface.ROTATION_90, 0);\n        ORIENTATIONS.append(Surface.ROTATION_180, 270);\n        ORIENTATIONS.append(Surface.ROTATION_270, 180);\n    }\n\n    private final Activity activity;\n    final Context context;\n    final CameraManager manager;\n\n    /***\n     * constructor.\n     *\n     * @param activity the activity used to get display manager and the application context\n     */\n    APictureCapturingService(final Activity activity) {\n        this.activity = activity;\n        this.context = activity.getApplicationContext();\n        this.manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);\n    }\n\n    /***\n     * @return  orientation\n     */\n    int getOrientation() {\n        final int rotation = this.activity.getWindowManager().getDefaultDisplay().getRotation();\n        return ORIENTATIONS.get(rotation);\n    }\n\n\n    /**\n     * starts pictures capturing process.\n     *\n     * @param listener picture capturing listener\n     */\n    public abstract void startCapturing(final PictureCapturingListener listener);\n}\n"
  },
  {
    "path": "app/src/main/java/com/hzitoun/camera2SecretPictureTaker/services/PictureCapturingServiceImpl.java",
    "content": "package com.hzitoun.camera2SecretPictureTaker.services;\n\nimport android.Manifest;\nimport android.annotation.TargetApi;\nimport android.app.Activity;\nimport android.content.pm.PackageManager;\nimport android.graphics.ImageFormat;\nimport android.hardware.camera2.CameraAccessException;\nimport android.hardware.camera2.CameraCaptureSession;\nimport android.hardware.camera2.CameraCharacteristics;\nimport android.hardware.camera2.CameraDevice;\nimport android.hardware.camera2.CameraMetadata;\nimport android.hardware.camera2.CaptureRequest;\nimport android.hardware.camera2.TotalCaptureResult;\nimport android.hardware.camera2.params.StreamConfigurationMap;\nimport android.media.Image;\nimport android.media.ImageReader;\nimport android.os.Build;\nimport android.os.Environment;\nimport android.os.Handler;\nimport android.support.annotation.NonNull;\nimport android.support.v4.app.ActivityCompat;\nimport android.util.Log;\nimport android.util.Size;\nimport android.view.Surface;\n\nimport com.hzitoun.camera2SecretPictureTaker.listeners.PictureCapturingListener;\n\nimport java.io.File;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.OutputStream;\nimport java.nio.ByteBuffer;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Queue;\nimport java.util.TreeMap;\nimport java.util.UUID;\n\n\n/**\n * The aim of this service is to secretly take pictures (without preview or opening device's camera app)\n * from all available cameras using Android Camera 2 API\n *\n * @author hzitoun (zitoun.hamed@gmail.com)\n */\n\n@TargetApi(Build.VERSION_CODES.LOLLIPOP) //NOTE: camera 2 api was added in API level 21\npublic class PictureCapturingServiceImpl extends APictureCapturingService {\n\n    private static final String TAG = PictureCapturingServiceImpl.class.getSimpleName();\n\n    private CameraDevice cameraDevice;\n    private ImageReader imageReader;\n    /***\n     * camera ids queue.\n     */\n    private Queue<String> cameraIds;\n    \n    private String currentCameraId;\n    private boolean cameraClosed;\n    /**\n     * stores a sorted map of (pictureUrlOnDisk, PictureData).\n     */\n    private TreeMap<String, byte[]> picturesTaken;\n    private PictureCapturingListener capturingListener;\n\n    /***\n     * private constructor, meant to force the use of {@link #getInstance}  method\n     */\n    private PictureCapturingServiceImpl(final Activity activity) {\n        super(activity);\n    }\n\n    /**\n     * @param activity the activity used to get the app's context and the display manager\n     * @return a new instance\n     */\n    public static APictureCapturingService getInstance(final Activity activity) {\n        return new PictureCapturingServiceImpl(activity);\n    }\n\n    /**\n     * Starts pictures capturing treatment.\n     *\n     * @param listener picture capturing listener\n     */\n    @Override\n    public void startCapturing(final PictureCapturingListener listener) {\n        this.picturesTaken = new TreeMap<>();\n        this.capturingListener = listener;\n        this.cameraIds = new LinkedList<>();\n        try {\n            final String[] cameraIds = manager.getCameraIdList();\n            if (cameraIds.length > 0) {\n                this.cameraIds.addAll(Arrays.asList(cameraIds));\n                this.currentCameraId = this.cameraIds.poll();\n                openCamera();\n            } else {\n                //No camera detected!\n                capturingListener.onDoneCapturingAllPhotos(picturesTaken);\n            }\n        } catch (final CameraAccessException e) {\n            Log.e(TAG, \"Exception occurred while accessing the list of cameras\", e);\n        }\n    }\n\n    private void openCamera() {\n        Log.d(TAG, \"opening camera \" + currentCameraId);\n        try {\n            if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CAMERA)\n                    == PackageManager.PERMISSION_GRANTED\n                    && ActivityCompat.checkSelfPermission(context,\n                    Manifest.permission.WRITE_EXTERNAL_STORAGE)\n                    == PackageManager.PERMISSION_GRANTED) {\n                manager.openCamera(currentCameraId, stateCallback, null);\n            }\n        } catch (final CameraAccessException e) {\n            Log.e(TAG, \" exception occurred while opening camera \" + currentCameraId, e);\n        }\n    }\n\n    private final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {\n        @Override\n        public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request,\n                                       @NonNull TotalCaptureResult result) {\n            super.onCaptureCompleted(session, request, result);\n            if (picturesTaken.lastEntry() != null) {\n                capturingListener.onCaptureDone(picturesTaken.lastEntry().getKey(), picturesTaken.lastEntry().getValue());\n                Log.i(TAG, \"done taking picture from camera \" + cameraDevice.getId());\n            }\n            closeCamera();\n        }\n    };\n\n\n    private final ImageReader.OnImageAvailableListener onImageAvailableListener = (ImageReader imReader) -> {\n        final Image image = imReader.acquireLatestImage();\n        final ByteBuffer buffer = image.getPlanes()[0].getBuffer();\n        final byte[] bytes = new byte[buffer.capacity()];\n        buffer.get(bytes);\n        saveImageToDisk(bytes);\n        image.close();\n    };\n\n    private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {\n        @Override\n        public void onOpened(@NonNull CameraDevice camera) {\n            cameraClosed = false;\n            Log.d(TAG, \"camera \" + camera.getId() + \" opened\");\n            cameraDevice = camera;\n            Log.i(TAG, \"Taking picture from camera \" + camera.getId());\n            //Take the picture after some delay. It may resolve getting a black dark photos.\n            new Handler().postDelayed(() -> {\n                try {\n                    takePicture();\n                } catch (final CameraAccessException e) {\n                    Log.e(TAG, \" exception occurred while taking picture from \" + currentCameraId, e);\n                }\n            }, 500);\n        }\n\n        @Override\n        public void onDisconnected(@NonNull CameraDevice camera) {\n            Log.d(TAG, \" camera \" + camera.getId() + \" disconnected\");\n            if (cameraDevice != null && !cameraClosed) {\n                cameraClosed = true;\n                cameraDevice.close();\n            }\n        }\n\n        @Override\n        public void onClosed(@NonNull CameraDevice camera) {\n            cameraClosed = true;\n            Log.d(TAG, \"camera \" + camera.getId() + \" closed\");\n            //once the current camera has been closed, start taking another picture\n            if (!cameraIds.isEmpty()) {\n                takeAnotherPicture();\n            } else {\n                capturingListener.onDoneCapturingAllPhotos(picturesTaken);\n            }\n        }\n\n\n        @Override\n        public void onError(@NonNull CameraDevice camera, int error) {\n            Log.e(TAG, \"camera in error, int code \" + error);\n            if (cameraDevice != null && !cameraClosed) {\n                cameraDevice.close();\n            }\n        }\n    };\n\n\n    private void takePicture() throws CameraAccessException {\n        if (null == cameraDevice) {\n            Log.e(TAG, \"cameraDevice is null\");\n            return;\n        }\n        final CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId());\n        Size[] jpegSizes = null;\n        StreamConfigurationMap streamConfigurationMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);\n        if (streamConfigurationMap != null) {\n            jpegSizes = streamConfigurationMap.getOutputSizes(ImageFormat.JPEG);\n        }\n        final boolean jpegSizesNotEmpty = jpegSizes != null && 0 < jpegSizes.length;\n        int width = jpegSizesNotEmpty ? jpegSizes[0].getWidth() : 640;\n        int height = jpegSizesNotEmpty ? jpegSizes[0].getHeight() : 480;\n        final ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);\n        final List<Surface> outputSurfaces = new ArrayList<>();\n        outputSurfaces.add(reader.getSurface());\n        final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);\n        captureBuilder.addTarget(reader.getSurface());\n        captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);\n        captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation());\n        reader.setOnImageAvailableListener(onImageAvailableListener, null);\n        cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {\n                    @Override\n                    public void onConfigured(@NonNull CameraCaptureSession session) {\n                        try {\n                            session.capture(captureBuilder.build(), captureListener, null);\n                        } catch (final CameraAccessException e) {\n                            Log.e(TAG, \" exception occurred while accessing \" + currentCameraId, e);\n                        }\n                    }\n\n                    @Override\n                    public void onConfigureFailed(@NonNull CameraCaptureSession session) {\n                    }\n                }\n                , null);\n    }\n\n\n    private void saveImageToDisk(final byte[] bytes) {\n        final String cameraId = this.cameraDevice == null ? UUID.randomUUID().toString() : this.cameraDevice.getId();\n        final File file = new File(Environment.getExternalStorageDirectory() + \"/\" + cameraId + \"_pic.jpg\");\n        try (final OutputStream output = new FileOutputStream(file)) {\n            output.write(bytes);\n            this.picturesTaken.put(file.getPath(), bytes);\n        } catch (final IOException e) {\n            Log.e(TAG, \"Exception occurred while saving picture to external storage \", e);\n        }\n    }\n\n    private void takeAnotherPicture() {\n        this.currentCameraId = this.cameraIds.poll();\n        openCamera();\n    }\n\n    private void closeCamera() {\n        Log.d(TAG, \"closing camera \" + cameraDevice.getId());\n        if (null != cameraDevice && !cameraClosed) {\n            cameraDevice.close();\n            cameraDevice = null;\n        }\n        if (null != imageReader) {\n            imageReader.close();\n            imageReader = null;\n        }\n    }\n\n\n}\n"
  },
  {
    "path": "app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ScrollView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:fillViewport=\"true\">\n\n    <LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:tools=\"http://schemas.android.com/tools\"\n        android:id=\"@+id/activity_main\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:orientation=\"vertical\"\n        android:paddingBottom=\"@dimen/activity_vertical_margin\"\n        android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n        android:paddingRight=\"@dimen/activity_horizontal_margin\"\n        android:paddingTop=\"@dimen/activity_vertical_margin\"\n        tools:context=\"com.hzitoun.camera2SecretPictureTaker.activities.MainActivity\">\n\n        <RelativeLayout\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_weight=\"1\"\n            android:background=\"@drawable/bg_shadow\">\n\n            <ImageView\n                android:id=\"@+id/backIV\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                android:layout_weight=\"1\"\n                android:contentDescription=\"@string/back_picture\" />\n        </RelativeLayout>\n\n\n        <RelativeLayout\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_weight=\"1\"\n            android:background=\"@drawable/bg_shadow\">\n\n            <ImageView\n                android:id=\"@+id/frontIV\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                android:contentDescription=\"@string/front_picture\" />\n\n        </RelativeLayout>\n\n        <Button\n            android:id=\"@+id/startCaptureBtn\"\n            android:background=\"@drawable/bg_shadow\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"center\"\n            android:text=\"@string/take_pic_btn_label\" />\n\n    </LinearLayout>\n</ScrollView>"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">Camera 2 Secret Picture Taker</string>\n    <string name=\"take_pic_btn_label\">Take photos</string>\n    <string name=\"front_picture\">Front Camera Picture</string>\n    <string name=\"back_picture\">Back Camera Picture</string>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "content": "<resources>\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "app/src/test/java/com/hzitoun/camera2SecretPictureTaker/ExampleUnitTest.java",
    "content": "package com.hzitoun.camera2SecretPictureTaker;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit test, which will execute on the development machine (host).\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\npublic class ExampleUnitTest {\n    @Test\n    public void addition_isCorrect() throws Exception {\n        assertEquals(4, 2 + 2);\n    }\n}"
  },
  {
    "path": "build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:2.2.3'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        jcenter()\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Mon Dec 28 10:00:20 PST 2015\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-2.14.1-all.zip\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\norg.gradle.jvmargs=-Xmx1536m\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windowz variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\ngoto execute\n\n:4NT_args\n@rem Get arguments from the 4NT Shell from JP Software\nset CMD_LINE_ARGS=%$\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "settings.gradle",
    "content": "include ':app'\n"
  }
]