[
  {
    "path": ".gitignore",
    "content": "# Android\nlocal.properties\n\n# IntelliJ\n*.iml\n.idea/\n\n# OS X\n.DS_Store\n\n# Gradle\nbuild\n/reports\n/.gradle"
  },
  {
    "path": ".travis.yml",
    "content": "language: android\njdk: oraclejdk8\nandroid:\n  components:\n    # Uncomment the lines below if you want to\n    # use the latest revision of Android SDK Tools\n    - platform-tools\n    - tools\n\n    # The BuildTools version used by your project\n    - build-tools-26.0.2\n\n    # The SDK version used to compile your project\n    - android-26\n\n    # Additional components\n    - extra-google-google_play_services\n    - extra-google-m2repository\n    - extra-android-m2repository\n    - addon-google_apis-google-19\n\n    # Specify at least one system image,\n    # if you need to run emulator(s) during your tests\n    # - sys-img-armeabi-v7a-android-19\n    # - sys-img-x86-android-17\nscript: ./gradlew assembleDebug\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Greyson Parrelli\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": "Permiso [![Build Status](https://travis-ci.org/greysonp/permiso.svg?branch=master)](https://travis-ci.org/greysonp/permiso) [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-Permiso-green.svg?style=true)](https://android-arsenal.com/details/1/2818) [![Join the chat at https://gitter.im/permiso/Lobby](https://badges.gitter.im/permiso/Lobby.svg)](https://gitter.im/permiso/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n=======\n\nPermiso is an Android library that makes requesting runtime permissions a whole lot easier.\n\nHave you seen the [docs](http://developer.android.com/training/permissions/requesting.html) for how to request runtime permissions? Who wants to do *that* every time you request a permission? Let's clean this up!\n\nFeatures\n--------\n* Localizes permission requests so you can handle everything using a simple callback mechanism.\n* Can easily make permission requests outside of the context of an Activity.\n* Simplifies showing the user your rationale for requesting a permission.\n* Can request multiple permissions at once.\n* Merges simultaneous requests for the same permission into a single request.\n\nUsage\n-----\nIf your Activity subclasses ```PermisoActivity```, requesting a permission is as simple as:\n\n```java\nPermiso.getInstance().requestPermissions(new Permiso.IOnPermissionResult() {\n    @Override\n    public void onPermissionResult(Permiso.ResultSet resultSet) {\n        if (resultSet.areAllPermissionsGranted()) {\n            // Permission granted!\n        } else {\n            // Permission denied.\n        }\n    }\n\n    @Override\n    public void onRationaleRequested(Permiso.IOnRationaleProvided callback, String... permissions) {\n        Permiso.getInstance().showRationaleInDialog(\"Title\", \"Message\", null, callback);\n    }\n}, Manifest.permission.READ_EXTERNAL_STORAGE);\n```\n\n### Requesting Multiple Permissions\nRequesting multiple permissions at once is just as easy.\n\n```java\nPermiso.getInstance().requestPermissions(new Permiso.IOnPermissionResult() {\n    @Override\n    public void onPermissionResult(Permiso.ResultSet resultSet) {\n        if (resultSet.isPermissionGranted(Manifest.permission.READ_CONTACTS)) {\n            // Contact permission granted!\n        }\n        if (resultSet.isPermissionGranted(Manifest.permission.READ_CALENDAR)) {\n            // Calendar permission granted!\n        }\n    }\n\n    @Override\n    public void onRationaleRequested(Permiso.IOnRationaleProvided callback, String... permissions) {\n        Permiso.getInstance().showRationaleInDialog(\"Title\", \"Message\", null, callback);\n    }\n}, Manifest.permission.READ_CONTACTS, Manifest.permission.READ_CALENDAR);\n```\n\nGradle\n------\n### Latest Stable Version\n```java\ndependencies {\n    compile 'com.greysonparrelli.permiso:permiso:0.3.0'\n}\n```\n\n### Latest Dev Version\n```java\n// In your top-level build.gradle\nrepositories {\n    maven { url \"https://www.jitpack.io\" }\n}\n// In your module's build.gradle\ndependencies {\n    compile 'com.github.greysonp:permiso:master-SNAPSHOT'\n}\n```\nFAQ\n---\n**I don't want my Activity to subclass ```PermisoActivity```. Do I have to?**\n\nOf course not! Permiso requires very little boilerplate, and therefore ```PermisoActivity``` does very little. If you don't want to subclass ```PermisoActivity```, all you have to do is make sure you do the two following things:\n\n* In ```onCreate()``` and ```onResume()```, invoke ```Permiso.getInstance().setActivity(this)```.\n* Forward the results of ```Activity.onRequestPermissionsResult()``` to ```Permiso.getInstance().onRequestPermissionResult()```.\n\nHere's an example:\n\n```java\n@Override\nprotected void onCreate(Bundle savedInstanceState) {\n    super.onCreate(savedInstanceState);\n    Permiso.getInstance().setActivity(this);\n}\n\n@Override\nprotected void onResume() {\n    super.onResume();\n    Permiso.getInstance().setActivity(this);\n}\n\n@Override\npublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {\n    super.onRequestPermissionsResult(requestCode, permissions, grantResults);\n    Permiso.getInstance().onRequestPermissionResult(requestCode, permissions, grantResults);\n}\n```\n\n**I don't want to show any rationale for my permissions.**\n\nAccording to the Android Guidelines you probably should, but there's no hard requirement. If you don't want to show a rationale, simply invoke the callback and do nothing else:\n\n```java\n@Override\npublic void onRationaleRequested(Permiso.IOnRationaleProvided callback, String... permissions) {\n    callback.onRationaleProvided();\n}\n```\n\n**I want to do some complicated logic with the results of my permission request, but the ResultSet doesn't let me.**\n\nFear not! The ```ResultSet``` object has a method called ```toMap()```, which will give you back a mapping of permissions -> ```Permiso.Result``` that you can iterate over to your heart's content.\n\n**What do you mean when you say that Permiso merges simultaneous requests for the same permission into a single request?**\n\nIf you request the same permission in two places simultaneously, Permiso will automatically merge them into one request. You might think this is a rare scenario, but before you know it, you have master and detail fragments that both need access to the user's contacts, and now you have to manage your permissions so their simultaneous requests don't cause two separate pop-ups! Don't worry, Permiso handles this for you.\n\n**I request a permission but nothing happens? What's up?**\n\nDid you make sure to declare your permissions in your ```AndroidManifest.xml```? If you don't, permission requests fail silently. That's an Android thing - not much Permiso can do there.\n"
  },
  {
    "path": "app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "app/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 26\n    buildToolsVersion '26.0.2'\n\n    defaultConfig {\n        applicationId \"com.greysonparrelli.permisodemo\"\n        minSdkVersion 14\n        targetSdkVersion 26\n        versionCode 1\n        versionName \"1.0\"\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    testCompile 'junit:junit:4.12'\n    compile 'com.android.support:appcompat-v7:26.1.0'\n    compile 'com.android.support:design:26.1.0'\n    compile project(':permiso')\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 /Users/greyson/Library/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/greysonparrelli/permisodemo/ApplicationTest.java",
    "content": "package com.greysonparrelli.permisodemo;\n\nimport android.app.Application;\nimport android.test.ApplicationTestCase;\n\n/**\n * <a href=\"http://d.android.com/tools/testing/testing_android.html\">Testing Fundamentals</a>\n */\npublic class ApplicationTest extends ApplicationTestCase<Application> {\n    public ApplicationTest() {\n        super(Application.class);\n    }\n}"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest package=\"com.greysonparrelli.permisodemo\"\n          xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />\n    <uses-permission android:name=\"android.permission.READ_CONTACTS\" />\n    <uses-permission android:name=\"android.permission.READ_CALENDAR\" />\n    <uses-permission android:name=\"android.permission.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=\".MainActivity\"\n            android:label=\"@string/app_name\"\n            android:theme=\"@style/AppTheme.NoActionBar\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\"/>\n\n                <category android:name=\"android.intent.category.LAUNCHER\"/>\n            </intent-filter>\n        </activity>\n\n        <activity\n            android:name=\".NonPermisoActivity\"\n            android:label=\"@string/app_name\"\n            android:theme=\"@style/AppTheme.NoActionBar\" />\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "app/src/main/java/com/greysonparrelli/permisodemo/MainActivity.java",
    "content": "package com.greysonparrelli.permisodemo;\n\nimport android.Manifest;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.view.View;\nimport android.widget.Toast;\n\nimport com.greysonparrelli.permiso.Permiso;\nimport com.greysonparrelli.permiso.PermisoActivity;\nimport com.greysonparrelli.permiso.PermisoDialogFragment;\n\n/**\n * An activity that demonstrates the features of {@link Permiso}. This activity extends {@link PermisoActivity} in order\n * to handle some boilerplate. If you don't want to extend {@link PermisoActivity}, check out\n * {@link NonPermisoActivity}.\n */\npublic class MainActivity extends PermisoActivity {\n\n    // =====================================================================\n    // Overrides\n    // =====================================================================\n\n    @SuppressWarnings(\"ConstantConditions\")\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n\n        // Set click listeners\n        findViewById(R.id.btn_single).setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                onSingleClick();\n            }\n        });\n        findViewById(R.id.btn_multiple).setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                onMultipleClick();\n            }\n        });\n        findViewById(R.id.btn_duplicate).setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                onDuplicateClick();\n            }\n        });\n        findViewById(R.id.btn_non_permiso).setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                onNonPermisoClick();\n            }\n        });\n    }\n\n\n    // =====================================================================\n    // Click Listeners\n    // =====================================================================\n\n    /**\n     * Request a single permission and display whether or not it was granted or denied.\n     */\n    private void onSingleClick() {\n        // A request for a single permission\n        Permiso.getInstance().requestPermissions(new Permiso.IOnPermissionResult() {\n            @Override\n            public void onPermissionResult(Permiso.ResultSet resultSet) {\n                if (resultSet.isPermissionGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {\n                    Toast.makeText(MainActivity.this, R.string.permission_granted, Toast.LENGTH_SHORT).show();\n                } else if (resultSet.isPermissionPermanentlyDenied(Manifest.permission.WRITE_EXTERNAL_STORAGE)){\n                    Toast.makeText(MainActivity.this, R.string.permission_permanently_denied, Toast.LENGTH_SHORT).show();\n                } else {\n                    Toast.makeText(MainActivity.this, R.string.permission_denied, Toast.LENGTH_SHORT).show();\n                }\n            }\n\n            @Override\n            public void onRationaleRequested(Permiso.IOnRationaleProvided callback, String... permissions) {\n                PermisoDialogFragment.Builder builder = new PermisoDialogFragment.Builder(\n                        R.string.permission_rationale,\n                        R.string.needed_for_html_demo_purposes,\n                        android.R.string.ok);\n                builder.setHtmlInterpretation(true);\n                Permiso.getInstance().showRationaleInDialog(builder, callback);\n            }\n        }, Manifest.permission.WRITE_EXTERNAL_STORAGE);\n    }\n\n    /**\n     * Request multiple permissions and display how many were granted.\n     */\n    private void onMultipleClick() {\n        // A request for two permissions\n        Permiso.getInstance().requestPermissions(new Permiso.IOnPermissionResult() {\n            @Override\n            public void onPermissionResult(Permiso.ResultSet resultSet) {\n                int numGranted = 0;\n                if (resultSet.isPermissionGranted(Manifest.permission.READ_CONTACTS)) {\n                    numGranted++;\n                }\n                if (resultSet.isPermissionGranted(Manifest.permission.READ_CALENDAR)) {\n                    numGranted++;\n                }\n                String message = getString(R.string.x_permissions_granted, numGranted);\n                Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();\n            }\n\n            @Override\n            public void onRationaleRequested(Permiso.IOnRationaleProvided callback, String... permissions) {\n                Permiso.getInstance().showRationaleInDialog(\n                        getString(R.string.permission_rationale),\n                        getString(R.string.needed_for_demo_purposes),\n                        null,\n                        callback);\n            }\n        }, Manifest.permission.READ_CONTACTS, Manifest.permission.READ_CALENDAR);\n    }\n\n    /**\n     * Make two simultaneous requests for the same permission. Only one dialog will pop up, and the results from that\n     * one request will be given to both callbacks.\n     */\n    private void onDuplicateClick() {\n        // First request\n        requestPermissions(\"1\");\n\n        // Second request for the same permission\n        requestPermissions(\"2\");\n    }\n\n    private void requestPermissions(final String requestNumber) {\n        Permiso.getInstance().requestPermissions(new Permiso.IOnPermissionResult() {\n            @Override\n            public void onPermissionResult(Permiso.ResultSet resultSet) {\n                if (resultSet.areAllPermissionsGranted()) {\n                    Toast.makeText(\n                            MainActivity.this,\n                            getString(R.string.permission_granted) + \" (\" + requestNumber + \")\",\n                            Toast.LENGTH_SHORT).show();\n                } else {\n                    Toast.makeText(\n                            MainActivity.this,\n                            getString(R.string.permission_denied) + \" (\" + requestNumber + \")\",\n                            Toast.LENGTH_SHORT).show();\n                }\n            }\n\n            @Override\n            public void onRationaleRequested(Permiso.IOnRationaleProvided callback, String... permissions) {\n                Permiso.getInstance().showRationaleInDialog(\n                        getString(R.string.permission_rationale),\n                        getString(R.string.needed_for_demo_purposes),\n                        null,\n                        callback);\n            }\n        }, Manifest.permission.CAMERA);\n    }\n\n    /**\n     * Starts {@link NonPermisoActivity}.\n     */\n    private void onNonPermisoClick() {\n        startActivity(new Intent(this, NonPermisoActivity.class));\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/greysonparrelli/permisodemo/NonPermisoActivity.java",
    "content": "package com.greysonparrelli.permisodemo;\n\nimport android.Manifest;\nimport android.os.Bundle;\nimport android.support.annotation.NonNull;\nimport android.support.v7.app.AppCompatActivity;\nimport android.view.View;\nimport android.widget.Toast;\n\nimport com.greysonparrelli.permiso.Permiso;\n\n/**\n * Created to demonstrate how to use Permiso without extending PermisoActivity.\n */\npublic class NonPermisoActivity extends AppCompatActivity {\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_non_permiso);\n\n        //\n        // First, tell Permiso that you're using this activity\n        //\n        Permiso.getInstance().setActivity(this);\n\n        findViewById(R.id.btn_request).setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                onRequestClick();\n            }\n        });\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n\n        //\n        // Second, we also have to set the activity here to handle transitioning between activities\n        //\n        Permiso.getInstance().setActivity(this);\n    }\n\n    @Override\n    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {\n        super.onRequestPermissionsResult(requestCode, permissions, grantResults);\n\n        //\n        // Third, forward the results of this method to Permiso\n        //\n        Permiso.getInstance().onRequestPermissionResult(requestCode, permissions, grantResults);\n    }\n\n    private void onRequestClick() {\n        //\n        // And that's it! Now you can make permission requests as usual\n        //\n        Permiso.getInstance().requestPermissions(new Permiso.IOnPermissionResult() {\n            @Override\n            public void onPermissionResult(Permiso.ResultSet resultSet) {\n                if (resultSet.isPermissionGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {\n                    Toast.makeText(NonPermisoActivity.this, R.string.permission_granted, Toast.LENGTH_SHORT).show();\n                } else if (resultSet.isPermissionPermanentlyDenied(Manifest.permission.WRITE_EXTERNAL_STORAGE)){\n                    Toast.makeText(NonPermisoActivity.this, R.string.permission_permanently_denied, Toast.LENGTH_SHORT).show();\n                } else {\n                    Toast.makeText(NonPermisoActivity.this, R.string.permission_denied, Toast.LENGTH_SHORT).show();\n                }\n            }\n\n            @Override\n            public void onRationaleRequested(Permiso.IOnRationaleProvided callback, String... permissions) {\n                Permiso.getInstance().showRationaleInDialog(getString(R.string.permission_rationale), getString(R.string.needed_for_demo_purposes), null, callback);\n            }\n        }, Manifest.permission.WRITE_EXTERNAL_STORAGE);\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:context=\"com.greysonparrelli.permisodemo.MainActivity\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    android:orientation=\"vertical\"\n    android:layout_gravity=\"center\">\n\n    <Button\n        android:id=\"@+id/btn_single\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"Request Single Permission\"/>\n\n    <Button\n        android:id=\"@+id/btn_multiple\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"Request Two Permissions\"/>\n\n    <Button\n        android:id=\"@+id/btn_duplicate\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"Request Duplicate Permissions\"/>\n\n    <Button\n        android:id=\"@+id/btn_non_permiso\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"Open Non-PermisoActivity Example\"/>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_non_permiso.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:context=\"com.greysonparrelli.permisodemo.MainActivity\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    android:orientation=\"vertical\"\n    android:layout_gravity=\"center\">\n\n    <Button\n        android:id=\"@+id/btn_request\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"Request a Permission\"/>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/menu/menu_main.xml",
    "content": "<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n      xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n      xmlns:tools=\"http://schemas.android.com/tools\"\n      tools:context=\"com.greysonparrelli.permisodemo.MainActivity\">\n    <item\n        android:id=\"@+id/action_settings\"\n        android:orderInCategory=\"100\"\n        android:title=\"@string/action_settings\"\n        app:showAsAction=\"never\"/>\n</menu>\n"
  },
  {
    "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    <dimen name=\"fab_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">Permiso Demo</string>\n    <string name=\"action_settings\">Settings</string>\n    <string name=\"permission_rationale\">Permission Rationale</string>\n    <string name=\"needed_for_html_demo_purposes\"><![CDATA[<u>Needed</u> for html demo <b>purposes.</b>]]></string>\n    <string name=\"needed_for_demo_purposes\">Needed for demo purposes.</string>\n    <string name=\"permission_granted\">Permission Granted!</string>\n    <string name=\"permission_permanently_denied\">Permission Permanently Denied.</string>\n    <string name=\"permission_denied\">Permission Denied.</string>\n    <string name=\"x_permissions_granted\">%1$d Permissions Granted.</string>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n    <style name=\"AppTheme.NoActionBar\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n    </style>\n\n    <style name=\"AppTheme.AppBarOverlay\" parent=\"ThemeOverlay.AppCompat.Dark.ActionBar\"/>\n\n    <style name=\"AppTheme.PopupOverlay\" parent=\"ThemeOverlay.AppCompat.Light\"/>\n\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values-v21/styles.xml",
    "content": "<resources>>\n\n    <style name=\"AppTheme.NoActionBar\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n        <item name=\"android:windowDrawsSystemBarBackgrounds\">true</item>\n        <item name=\"android:statusBarColor\">@android:color/transparent</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/greysonparrelli/permisodemo/ExampleUnitTest.java",
    "content": "package com.greysonparrelli.permisodemo;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * To work on unit tests, switch the Test Artifact in the Build Variants view.\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        // You need to add the following repository to download the new plugin.\n        maven { url 'https://maven.google.com' }\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:3.0.0'\n        classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'\n        classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'\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        maven { url 'https://maven.google.com' }\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "gradle/bintray.gradle",
    "content": "apply plugin: 'com.jfrog.bintray'\n\nversion = libraryVersion\n\ntask sourcesJar(type: Jar) {\n    from android.sourceSets.main.java.srcDirs\n    classifier = 'sources'\n}\n\ntask javadoc(type: Javadoc) {\n    source = android.sourceSets.main.java.srcDirs\n    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))\n}\n\ntask javadocJar(type: Jar, dependsOn: javadoc) {\n    classifier = 'javadoc'\n    from javadoc.destinationDir\n}\nartifacts {\n    archives javadocJar\n    archives sourcesJar\n}\n\n// Bintray\nProperties properties = new Properties()\nproperties.load(project.rootProject.file('local.properties').newDataInputStream())\n\nbintray {\n    user = properties.getProperty(\"bintray.user\")\n    key = properties.getProperty(\"bintray.apikey\")\n\n    configurations = ['archives']\n    pkg {\n        repo = bintrayRepo\n        name = bintrayName\n        desc = libraryDescription\n        websiteUrl = siteUrl\n        vcsUrl = gitUrl\n        licenses = allLicenses\n        publish = true\n        publicDownloadNumbers = true\n        version {\n            desc = libraryDescription\n            gpg {\n                sign = true //Determines whether to GPG sign the files. The default is false\n                passphrase = properties.getProperty(\"bintray.gpg.password\")\n                //Optional. The passphrase for GPG signing'\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "gradle/maven.gradle",
    "content": "apply plugin: 'com.github.dcendents.android-maven'\n\ngroup = publishedGroupId                               // Maven Group ID for the artifact\n\ninstall {\n    repositories.mavenInstaller {\n        // This generates POM.xml with proper parameters`\n        pom {\n            project {\n                packaging 'aar'\n                groupId publishedGroupId\n                artifactId artifact\n\n                // Add your description here\n                name libraryName\n                description libraryDescription\n                url siteUrl\n\n                // Set your license\n                licenses {\n                    license {\n                        name licenseName\n                        url licenseUrl\n                    }\n                }\n                developers {\n                    developer {\n                        id developerId\n                        name developerName\n                        email developerEmail\n                    }\n                }\n                scm {\n                    connection gitUrl\n                    developerConnection gitUrl\n                    url siteUrl\n\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Sun Oct 29 10:59:04 IST 2017\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-4.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.\n# Default value: -Xmx10248m -XX:MaxPermSize=256m\n# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8\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"
  },
  {
    "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# For Cygwin, ensure paths are in UNIX format before anything is touched.\nif $cygwin ; then\n    [ -n \"$JAVA_HOME\" ] && JAVA_HOME=`cygpath --unix \"$JAVA_HOME\"`\nfi\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\\\"`/\" >&-\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >&-\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\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\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:init\r\n@rem Get command-line arguments, handling Windowz variants\r\n\r\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\r\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\r\n\r\n:win9xME_args\r\n@rem Slurp the command line arguments.\r\nset CMD_LINE_ARGS=\r\nset _SKIP=2\r\n\r\n:win9xME_args_slurp\r\nif \"x%~1\" == \"x\" goto execute\r\n\r\nset CMD_LINE_ARGS=%*\r\ngoto execute\r\n\r\n:4NT_args\r\n@rem Get arguments from the 4NT Shell from JP Software\r\nset CMD_LINE_ARGS=%$\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n@rem Execute Gradle\r\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%\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "permiso/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "permiso/build.gradle",
    "content": "apply plugin: 'com.android.library'\n\next {\n    bintrayRepo = 'maven'\n    bintrayName = 'permiso'\n\n    publishedGroupId = 'com.greysonparrelli.permiso'\n    libraryName = 'Permiso'\n    artifact = 'permiso'\n\n    libraryDescription = 'An Android library to make handling runtime permissions a whole lot easier.'\n\n    siteUrl = 'https://github.com/greysonp/permiso'\n    gitUrl = 'https://github.com/greysonp/permiso.git'\n\n    libraryVersion = '0.3.0'\n\n    developerId = 'greysonp'\n    developerName = 'Greyson Parrelli'\n    developerEmail = 'greyson.parrelli@gmail.com'\n\n    licenseName = 'The MIT License (MIT)'\n    licenseUrl = 'https://opensource.org/licenses/MIT'\n    allLicenses = [\"MIT\"]\n}\n\nandroid {\n    compileSdkVersion 26\n    buildToolsVersion '26.0.2'\n\n    defaultConfig {\n        minSdkVersion 14\n        targetSdkVersion 26\n        versionCode 1\n        versionName \"1.0\"\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    testCompile 'junit:junit:4.12'\n    compile 'com.android.support:appcompat-v7:26.1.0'\n}\n\n// Only add in the bintray stuff if we're building locally\nif (!\"true\".equalsIgnoreCase(System.getenv(\"CI\"))) {\n    apply from: rootProject.file('gradle/maven.gradle')\n    apply from: rootProject.file('gradle/bintray.gradle')\n}\n"
  },
  {
    "path": "permiso/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 /Users/greyson/Library/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": "permiso/src/androidTest/java/com/greysonparrelli/permiso/ApplicationTest.java",
    "content": "package com.greysonparrelli.permiso;\n\nimport android.app.Application;\nimport android.test.ApplicationTestCase;\n\n/**\n * <a href=\"http://d.android.com/tools/testing/testing_android.html\">Testing Fundamentals</a>\n */\npublic class ApplicationTest extends ApplicationTestCase<Application> {\n    public ApplicationTest() {\n        super(Application.class);\n    }\n}"
  },
  {
    "path": "permiso/src/main/AndroidManifest.xml",
    "content": "<manifest package=\"com.greysonparrelli.permiso\"\n          xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <application\n        android:label=\"@string/app_name\">\n\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "permiso/src/main/java/com/greysonparrelli/permiso/Permiso.java",
    "content": "package com.greysonparrelli.permiso;\n\nimport android.app.Activity;\nimport android.app.FragmentManager;\nimport android.content.pm.PackageManager;\nimport android.os.Bundle;\nimport android.support.annotation.MainThread;\nimport android.support.annotation.NonNull;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.ActivityCompat;\nimport android.support.v4.content.ContextCompat;\nimport android.util.Log;\n\nimport java.lang.ref.WeakReference;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * A class to make permission-management easier. Provides methods to conveniently request permissions anywhere in your\n * app.\n */\npublic class Permiso {\n\n    private static final String TAG = \"Permiso\";\n\n    /**\n     * A map to keep track of our outstanding permission requests. The key is the request code sent when we call\n     * {@link ActivityCompat#requestPermissions(Activity, String[], int)}. The value is the {@link Permiso.RequestData}\n     * bundle that holds all of the request information.\n     */\n    private Map<Integer, RequestData> mCodesToRequests;\n\n    /**\n     * The active activity. Used to make permissions requests. This must be set by the library-user through\n     * {@link Permiso#setActivity(Activity)} or else bad things will happen.\n     */\n    private WeakReference<Activity> mActivity;\n\n    /**\n     * This is just a value we increment to generate new request codes for use with\n     * {@link ActivityCompat#requestPermissions(Activity, String[], int)}.\n     */\n    private int mActiveRequestCode = 1;\n\n    /**\n     * The singleton instance.\n     */\n    private static Permiso sInstance = new Permiso();\n\n\n    // =====================================================================\n    // Creation\n    // =====================================================================\n\n    /**\n     * @return An instance of {@link Permiso} to help you manage your permissions.\n     */\n    public static Permiso getInstance() {\n        return sInstance;\n    }\n\n    /**\n     * Implementing a singleton pattern, so this is private.\n     */\n    private Permiso() {\n        mCodesToRequests = new HashMap<>();\n    }\n\n\n    // =====================================================================\n    // Public\n    // =====================================================================\n\n    /**\n     * This method should be invoked in the {@link Activity#onCreate(Bundle)} in every activity that requests\n     * permissions. Even if you don't want to use Permiso in your current activity, you should call this method\n     * with a null activity to prevent leaking the previously-set activity.\n     * <p>\n     * <strong>Important: </strong> If your activity subclasses {@link PermisoActivity}, this is already handled for you.\n     * @param activity The activity that is currently active.\n     */\n    public void setActivity(@NonNull Activity activity) {\n        mActivity = new WeakReference<>(activity);\n    }\n\n    /**\n     * Request one or more permissions from the system. Make sure that you are either subclassing {@link PermisoActivity}\n     * or that you have set your current activity using {@link Permiso#setActivity(Activity)}!\n     * @param callback\n     *      A callback that will be triggered when the results of your permission request are available.\n     * @param permissions\n     *      A list of permission constants that you are requesting. Use constants from\n     *      {@link android.Manifest.permission}.\n     */\n    @MainThread\n    public void requestPermissions(@NonNull IOnPermissionResult callback, String... permissions) {\n        Activity activity = checkActivity();\n\n        final RequestData requestData = new RequestData(callback, permissions);\n\n        // Mark any permissions that are already granted\n        for (String permission : permissions) {\n            if (ContextCompat.checkSelfPermission(activity, permission) == PackageManager.PERMISSION_GRANTED) {\n                requestData.resultSet.grantPermissions(permission);\n            }\n        }\n\n        // If we had all of them, yay! No need to do anything else.\n        if (requestData.resultSet.areAllPermissionsGranted()) {\n            requestData.onResultListener.onPermissionResult(requestData.resultSet);\n        } else {\n            // If we have some unsatisfied ones, let's first see if they can be satisfied by an active request. If it\n            // can, we'll re-wire the callback of the active request to also trigger this new one.\n            boolean linkedToExisting = linkToExistingRequestIfPossible(requestData);\n\n            // If there was no existing request that can satisfy this one, then let's make a new permission request to\n            // the system\n            if (!linkedToExisting) {\n                // Mark the request as active\n                final int requestCode = markRequestAsActive(requestData);\n\n                // First check if there's any permissions for which we need to provide a rationale for using\n                String[] permissionsThatNeedRationale = requestData.resultSet.getPermissionsThatNeedRationale(activity);\n\n                // If there are some that need a rationale, show that rationale, then continue with the request\n                if (permissionsThatNeedRationale.length > 0) {\n                    requestData.onResultListener.onRationaleRequested(new IOnRationaleProvided() {\n                        @Override\n                        public void onRationaleProvided() {\n                            makePermissionRequest(requestCode, requestData);\n                        }\n                    }, permissionsThatNeedRationale);\n                } else {\n                    makePermissionRequest(requestCode, requestData);\n                }\n            }\n        }\n    }\n\n    /**\n     * This method needs to be called by your activity's {@link Activity#onRequestPermissionsResult(int, String[], int[])}.\n     * Simply forward the results of that method here.\n     * <p>\n     * <strong>Important: </strong> If your activity subclasses {@link PermisoActivity}, this is already handled for you.\n     * @param requestCode\n     *      The request code given to you by {@link Activity#onRequestPermissionsResult(int, String[], int[])}.\n     * @param permissions\n     *      The permissions given to you by {@link Activity#onRequestPermissionsResult(int, String[], int[])}.\n     * @param grantResults\n     *      The grant results given to you by {@link Activity#onRequestPermissionsResult(int, String[], int[])}.\n     */\n    @MainThread\n    public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) {\n        Activity activity = checkActivity();\n        if (mCodesToRequests.containsKey(requestCode)) {\n            RequestData requestData = mCodesToRequests.get(requestCode);\n            requestData.resultSet.parsePermissionResults(permissions, grantResults, activity);\n            requestData.onResultListener.onPermissionResult(requestData.resultSet);\n            mCodesToRequests.remove(requestCode);\n        } else {\n            Log.w(TAG, \"onRequestPermissionResult() was given an unrecognized request code.\");\n        }\n    }\n\n    /**\n     * A helper to show your rationale in a {@link android.app.DialogFragment} when implementing\n     * {@link IOnRationaleProvided#onRationaleProvided()}. Automatically invokes the rationale callback when the user\n     * dismisses the dialog.\n     * @param title\n     *      The title of the dialog. If null, there will be no title.\n     * @param message\n     *      The message displayed in the dialog.\n     * @param buttonText\n     *      The text you want the dismissal button to show. If null, defaults to {@link android.R.string#ok}.\n     * @param rationaleCallback\n     *      The callback to be trigger\n     */\n    @MainThread\n    public void showRationaleInDialog(\n            @Nullable String title,\n            @NonNull String message,\n            @Nullable String buttonText,\n            @NonNull final IOnRationaleProvided rationaleCallback) {\n        PermisoDialogFragment.Builder builder = new PermisoDialogFragment.Builder()\n                .setTitle(title)\n                .setMessage(message)\n                .setButtonText(buttonText);\n        showRationaleInDialog(builder, rationaleCallback);\n    }\n\n    /**\n     * A helper to show your rationale in a {@link android.app.DialogFragment} when implementing\n     * {@link IOnRationaleProvided#onRationaleProvided()}. Automatically invokes the rationale callback when the user\n     * dismisses the dialog.\n     * @param builder\n     *      A reference to PermisoDialogFragment.Builder containing parameters for displaying the Dialog.\n     * @param rationaleCallback\n     *      The callback to be trigger\n     */\n    @MainThread\n    public void showRationaleInDialog(\n            final PermisoDialogFragment.Builder builder,\n            final IOnRationaleProvided rationaleCallback) {\n        Activity activity = checkActivity();\n        FragmentManager fm = activity.getFragmentManager();\n\n        PermisoDialogFragment dialogFragment = (PermisoDialogFragment) fm.findFragmentByTag(PermisoDialogFragment.TAG);\n        if (dialogFragment != null) {\n            dialogFragment.dismiss();\n        }\n\n        dialogFragment = builder.build(activity);\n\n        // We show the rationale after the dialog is closed. We use setRetainInstance(true) in the dialog to ensure that\n        // it retains the listener after an app rotation.\n        dialogFragment.setOnCloseListener(new PermisoDialogFragment.IOnCloseListener() {\n            @Override\n            public void onClose() {\n                rationaleCallback.onRationaleProvided();\n            }\n        });\n        dialogFragment.show(fm, PermisoDialogFragment.TAG);\n    }\n\n    // =====================================================================\n    // Private\n    // =====================================================================\n\n    /**\n     * Checks to see if there are any active requests that are already requesting a superset of the permissions this\n     * new request is asking for. If so, this will wire up this new request's callback to be triggered when the\n     * existing request is completed and return true. Otherwise, this does nothing and returns false.\n     * @param newRequest The new request that is about to be made.\n     * @return True if a request was linked, otherwise false.\n     */\n    private boolean linkToExistingRequestIfPossible(final RequestData newRequest) {\n        boolean found = false;\n\n        // Go through all outstanding requests\n        for (final RequestData activeRequest : mCodesToRequests.values()) {\n            // If we find one that can satisfy all of the new request's permissions, we re-wire the active one's\n            // callback to also call this new one's callback\n            if (activeRequest.resultSet.containsAllUngrantedPermissions(newRequest.resultSet)) {\n                final IOnPermissionResult originalOnResultListener = activeRequest.onResultListener;\n                activeRequest.onResultListener = new IOnPermissionResult() {\n                    @Override\n                    public void onPermissionResult(ResultSet resultSet) {\n                        // First, call the active one's callback. It was added before this new one.\n                        originalOnResultListener.onPermissionResult(resultSet);\n\n                        // Next, copy over the results to the new one's resultSet\n                        String[] unsatisfied = newRequest.resultSet.getUngrantedPermissions();\n                        for (String permission : unsatisfied) {\n                            newRequest.resultSet.requestResults.put(permission, resultSet.requestResults.get(permission));\n                        }\n\n                        // Finally, trigger the new one's callback\n                        newRequest.onResultListener.onPermissionResult(newRequest.resultSet);\n                    }\n\n                    @Override\n                    public void onRationaleRequested(IOnRationaleProvided callback, String... permissions) {\n                        activeRequest.onResultListener.onRationaleRequested(callback, permissions);\n                    }\n                };\n                found = true;\n                break;\n            }\n        }\n        return found;\n    }\n\n    /**\n     * Puts the RequestData in the map of requests and gives back the request code.\n     * @return The request code generated for this request.\n     */\n    private int markRequestAsActive(RequestData requestData) {\n        int requestCode = mActiveRequestCode++;\n        mCodesToRequests.put(requestCode, requestData);\n        return requestCode;\n    }\n\n    /**\n     * Makes the permission request for the request that matches the provided request code.\n     * @param requestCode The request code of the request you want to run.\n     * @param requestData The {@link RequestData} representing the request you want to run.\n     */\n    private void makePermissionRequest(int requestCode, RequestData requestData) {\n        Activity activity = checkActivity();\n        ActivityCompat.requestPermissions(activity, requestData.resultSet.getUngrantedPermissions(), requestCode);\n    }\n\n    /**\n     * Ensures that our WeakReference to the Activity is still valid. If it isn't, throw an exception saying that the\n     * Activity needs to be set.\n     */\n    private Activity checkActivity() {\n        Activity activity = mActivity.get();\n        if (activity == null) {\n            throw new IllegalStateException(\"No activity set. Either subclass PermisoActivity or call Permiso.setActivity() in onCreate() and onResume() of your Activity.\");\n        }\n        return activity;\n    }\n\n\n    // =====================================================================\n    // Inner Classes\n    // =====================================================================\n\n    /**\n     * A callback interface for receiving the results of a permission request.\n     */\n    public interface IOnPermissionResult {\n        /**\n         * Invoked when the results of your permission request are ready.\n         * @param resultSet An object holding the result of your permission request.\n         */\n        void onPermissionResult(ResultSet resultSet);\n\n        /**\n         * Called when the system recommends that you provide a rationale for a permission. This typically happens when\n         * a user denies a permission, but they you request it again.\n         * @param callback    A callback to be triggered when you are finished showing the user the rationale.\n         * @param permissions The list of permissions for which the system recommends you provide a rationale.\n         */\n        void onRationaleRequested(IOnRationaleProvided callback, String... permissions);\n    }\n\n    /**\n     * Simple callback to let Permiso know that you have finished providing the user a rationale for a set of permissions.\n     * For easy handling of this callback, consider using\n     * {@link Permiso#showRationaleInDialog(String, String, String, IOnRationaleProvided)}.\n     */\n    public interface IOnRationaleProvided {\n        /**\n         * Invoke this method when you are done providing a rationale to the user in\n         * {@link IOnPermissionResult#onRationaleRequested(IOnRationaleProvided, String...)}. The permission request\n         * will not be made until this method is invoked.\n         */\n        void onRationaleProvided();\n    }\n\n    private static class RequestData {\n        IOnPermissionResult onResultListener;\n        ResultSet resultSet;\n\n        public RequestData(@NonNull IOnPermissionResult onResultListener, String... permissions) {\n            this.onResultListener = onResultListener;\n            resultSet = new ResultSet(permissions);\n        }\n    }\n\n    /**\n     * A class representing the results of a permission request.\n     */\n    public static class ResultSet {\n\n        private Map<String, Result> requestResults;\n\n        private ResultSet(String... permissions) {\n            requestResults = new HashMap<>(permissions.length);\n            for (String permission : permissions) {\n                requestResults.put(permission, Result.DENIED);\n            }\n        }\n\n        /**\n         * Checks if a permission was granted during your permission request.\n         * @param permission The permission you are inquiring about. This should be a constant from {@link android.Manifest.permission}.\n         * @return True if the permission was granted, otherwise false.\n         */\n        public boolean isPermissionGranted(String permission) {\n            return requestResults.containsKey(permission) && requestResults.get(permission) == Result.GRANTED;\n        }\n\n        /**\n         * Determines if all permissions in the request were granted.\n         * @return True if all permissions in the request were granted, otherwise false.\n         */\n        public boolean areAllPermissionsGranted() {\n            return !requestResults.containsValue(Result.DENIED) && !requestResults.containsValue(Result.PERMANENTLY_DENIED);\n        }\n\n        /**\n         * Checks if a permission was permanently denied by the user (i.e. they denied and selected \"Dont Ask Again\".)\n         * @param permission The permission you are inquiring about. This should be a constant from {@link android.Manifest.permission}.\n         * @return True if the permission was permanently denied, otherwise false.\n         */\n        public boolean isPermissionPermanentlyDenied(String permission) {\n            return requestResults.containsKey(permission) && requestResults.get(permission) == Result.PERMANENTLY_DENIED;\n        }\n\n        /**\n         * Returns a map representation of this result set. Useful if you'd like to do more complicated operations\n         * with the results.\n         * @return\n         *      A mapping of permission constants to {@link Result}.\n         */\n        public Map<String, Result> toMap() {\n            return new HashMap<>(requestResults);\n        }\n\n        private void grantPermissions(String... permissions) {\n            for (String permission : permissions) {\n                requestResults.put(permission, Result.GRANTED);\n            }\n        }\n\n        private void parsePermissionResults(String[] permissions, int[] grantResults, Activity activity) {\n            for (int i = 0; i < permissions.length; i++) {\n                if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {\n                    requestResults.put(permissions[i], Result.GRANTED);\n                } else if (!ActivityCompat.shouldShowRequestPermissionRationale(activity, permissions[i])) {\n                    requestResults.put(permissions[i], Result.PERMANENTLY_DENIED);\n                } else {\n                    requestResults.put(permissions[i], Result.DENIED);\n                }\n            }\n        }\n\n        private String[] getUngrantedPermissions() {\n            List<String> ungrantedList = new ArrayList<>(requestResults.size());\n            for (Map.Entry<String, Result> requestResultsEntry : requestResults.entrySet()) {\n                Result result = requestResultsEntry.getValue();\n                if (result == Result.DENIED || result == Result.PERMANENTLY_DENIED) {\n                    ungrantedList.add(requestResultsEntry.getKey());\n                }\n            }\n            return ungrantedList.toArray(new String[ungrantedList.size()]);\n        }\n\n        private boolean containsAllUngrantedPermissions(ResultSet set) {\n            List<String> ungranted = Arrays.asList(set.getUngrantedPermissions());\n            return requestResults.keySet().containsAll(ungranted);\n        }\n\n        private String[] getPermissionsThatNeedRationale(Activity activity) {\n            String[] ungranted = getUngrantedPermissions();\n            List<String> shouldShowRationale = new ArrayList<>(ungranted.length);\n            for (String permission : ungranted) {\n                if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {\n                    shouldShowRationale.add(permission);\n                }\n            }\n            return shouldShowRationale.toArray(new String[shouldShowRationale.size()]);\n        }\n    }\n\n    /**\n     * Describes the result of a permission request.\n     */\n    public enum Result {\n        /**\n         * The permission was granted.\n         */\n        GRANTED,\n\n        /**\n         * The permission was denied, but not permanently.\n         */\n        DENIED,\n\n        /**\n         * The permission was permanently denied.\n         */\n        PERMANENTLY_DENIED\n    }\n}\n"
  },
  {
    "path": "permiso/src/main/java/com/greysonparrelli/permiso/PermisoActivity.java",
    "content": "package com.greysonparrelli.permiso;\n\nimport android.app.Activity;\nimport android.os.Bundle;\nimport android.support.annotation.NonNull;\nimport android.support.v7.app.AppCompatActivity;\n\n/**\n * An Activity that handles the small amount of boilerplate that {@link Permiso} requires to run. If you'd rather not\n * use this as your base activity class, simply remember to do the following in each of your activities:\n * <ul>\n *     <li>Call {@link Permiso#setActivity(Activity)} in {@link Activity#onCreate(Bundle)} and {@link Activity#onResume()}</li>\n *     <li>Call {@link Permiso#onRequestPermissionResult(int, String[], int[])} in\n *      {@link Activity#onRequestPermissionsResult(int, String[], int[])}</li>\n * </ul>\n */\npublic class PermisoActivity extends AppCompatActivity {\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        Permiso.getInstance().setActivity(this);\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n        Permiso.getInstance().setActivity(this);\n    }\n\n    @Override\n    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {\n        super.onRequestPermissionsResult(requestCode, permissions, grantResults);\n        Permiso.getInstance().onRequestPermissionResult(requestCode, permissions, grantResults);\n    }\n}"
  },
  {
    "path": "permiso/src/main/java/com/greysonparrelli/permiso/PermisoDialogFragment.java",
    "content": "package com.greysonparrelli.permiso;\n\nimport android.app.Dialog;\nimport android.app.DialogFragment;\nimport android.content.Context;\nimport android.content.DialogInterface;\nimport android.os.Bundle;\nimport android.support.annotation.NonNull;\nimport android.support.annotation.Nullable;\nimport android.support.annotation.StringRes;\nimport android.support.v7.app.AlertDialog;\nimport android.text.Html;\nimport android.text.method.LinkMovementMethod;\nimport android.widget.TextView;\n\n/**\n * A DialogFragment created for convenience to show a simple message explaining why a certain permission is being\n * requested and trigger a listener when it has been closed. Intended to be used by\n * {@link Permiso#showRationaleInDialog(String, String, String, Permiso.IOnRationaleProvided)}.\n */\npublic class PermisoDialogFragment extends DialogFragment {\n\n    public static final String TAG = \"PermisoDialogFragment\";\n\n    private static final String KEY_TITLE = \"title\";\n    private static final String KEY_MESSAGE = \"message\";\n    private static final String KEY_BUTTON_TEXT = \"button_text\";\n    private static final String KEY_HAS_HTML = \"has_html\";\n    private static final String KEY_THEME_ID = \"theme_id\";\n\n    private String mTitle;\n    private String mMessage;\n    private String mButtonText;\n    private boolean mHasHtml;\n    private int mThemeId;\n\n    private IOnCloseListener mOnCloseListener;\n\n    /**\n     * Creates a new {@link PermisoDialogFragment}. Only intended to be used by\n     * {@link Permiso#showRationaleInDialog(String, String, String, Permiso.IOnRationaleProvided)}.\n     * @param title      The title of the dialog. If null, no title will be displayed.\n     * @param message    The message to be shown in the dialog.\n     * @param buttonText The text to label the dialog button. If null, defaults to {@link android.R.string#ok}.\n     * @return A new {@link PermisoDialogFragment}.\n     */\n    public static PermisoDialogFragment newInstance(\n            @Nullable String title,\n            @NonNull String message,\n            @Nullable String buttonText) {\n        return newInstance(new Builder()\n                .setTitle(title)\n                .setMessage(message)\n                .setButtonText(buttonText));\n    }\n\n    private static PermisoDialogFragment newInstance(@NonNull Builder builder) {\n        PermisoDialogFragment dialogFragment = new PermisoDialogFragment();\n        // Build arguments bundle\n        Bundle args = new Bundle();\n        args.putBoolean(KEY_HAS_HTML, builder.isHtml());\n        args.putString(KEY_TITLE, builder.getTitle());\n        args.putString(KEY_MESSAGE, builder.getMessage());\n        args.putString(KEY_BUTTON_TEXT, builder.getButtonText());\n        args.putInt(KEY_THEME_ID, builder.getThemeId());\n        dialogFragment.setArguments(args);\n\n        return dialogFragment ;\n    }\n\n    @Override\n    public void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n\n        // Retain instance state so we can keep our listeners registered after a rotation\n        setRetainInstance(true);\n\n        mTitle = getArguments().getString(KEY_TITLE);\n        mMessage = getArguments().getString(KEY_MESSAGE);\n        mButtonText = getArguments().getString(KEY_BUTTON_TEXT);\n        mHasHtml = getArguments().getBoolean(KEY_HAS_HTML);\n        mThemeId = getArguments().getInt(KEY_THEME_ID);\n    }\n\n    @Override\n    public void onDestroyView() {\n        // If we don't do this, the DialogFragment is not recreated after a rotation. See bug:\n        // https://code.google.com/p/android/issues/detail?id=17423\n        if (getDialog() != null && getRetainInstance()) {\n            getDialog().setDismissMessage(null);\n        }\n        super.onDestroyView();\n    }\n\n    @NonNull\n    @Override\n    public Dialog onCreateDialog(Bundle savedInstanceState) {\n        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), mThemeId);\n\n        // Title\n        if (mTitle != null) {\n            builder.setTitle(mTitle);\n        }\n\n        // Message\n        if (mHasHtml) {\n            TextView msg = new TextView(getActivity());\n            msg.setText(Html.fromHtml(mMessage));\n            msg.setMovementMethod(LinkMovementMethod.getInstance());\n            builder.setView(msg);\n        } else if (mMessage != null) {\n            builder.setMessage(mMessage);\n        }\n\n        // Button text\n        String buttonText;\n        if (mButtonText != null) {\n            buttonText = mButtonText;\n        } else {\n            buttonText = getString(android.R.string.ok);\n        }\n        builder.setPositiveButton(buttonText, new DialogInterface.OnClickListener() {\n            @Override\n            public void onClick(DialogInterface dialog, int which) {\n                if (mOnCloseListener != null) {\n                    mOnCloseListener.onClose();\n                }\n            }\n        });\n        return builder.create();\n    }\n\n    @Override\n    public void onCancel(DialogInterface dialog) {\n        super.onCancel(dialog);\n        if (mOnCloseListener != null) {\n            mOnCloseListener.onClose();\n        }\n    }\n\n    /**\n     * Sets the listener that will be triggered when this dialog is closed by a user action. This includes clicking\n     * the dismissal button as well as clicking in the area outside of the dialog. NOT triggered by rotation.\n     * @param listener Listener you want triggered when this dialog is closed by a user action.\n     */\n    public void setOnCloseListener(IOnCloseListener listener) {\n        mOnCloseListener = listener;\n    }\n\n    /**\n     * A simple listener that will be triggered when this dialog is closed by a user action.\n     */\n    public interface IOnCloseListener {\n        /**\n         * Called when the dialog is closed by a user action. This includes clicking the dismissal button as well as\n         * clicking in the area outside of the dialog. NOT triggered by rotation.\n         */\n        void onClose();\n    }\n\n    /**\n     * Build a {@link PermisoDialogFragment}. Gives the opportunity to set strings using either a raw string or a\n     * resource id.\n     */\n    public static class Builder {\n        private int titleId = 0;\n        private String title = null;\n        private int buttonTextId = 0;\n        private String message = null;\n        private int messageId = 0;\n        private boolean interpretHtml = false;\n        private String buttonText = null;\n        private int themeId = 0;\n\n        public Builder() {}\n\n        public Builder(int titleId, int msgBody, int buttonTextId) {\n            this.titleId = titleId;\n            this.messageId = msgBody;\n            this.buttonTextId = buttonTextId;\n        }\n\n        // =====================================================================\n        // Getters\n        // =====================================================================\n\n        public String getTitle() {\n            return title;\n        }\n\n        public String getMessage() {\n            return message;\n        }\n\n        public String getButtonText() {\n            return buttonText;\n        }\n\n        public boolean isHtml() {\n            return interpretHtml;\n        }\n\n        public int getThemeId() {\n            return themeId;\n        }\n\n\n        // =====================================================================\n        // Setters\n        // =====================================================================\n\n        /**\n         * Set the title that will appear at the top of the dialog.\n         */\n        public Builder setTitle(@StringRes int resId) {\n            titleId = resId;\n            return this;\n        }\n\n        /**\n         * Set the title that will appear at the top of the dialog.\n         */\n        public Builder setTitle(String val) {\n            title = val;\n            return this;\n        }\n\n        /**\n         * Set the message that will appear in the body of the dialog.\n         */\n        public Builder setMessage(@StringRes int resId) {\n            messageId = resId;\n            return this;\n        }\n\n        /**\n         * Set the message that will appear in the body of the dialog.\n         */\n        public Builder setMessage(String val) {\n            message = val;\n            return this;\n        }\n\n        /**\n         * Set the text that will appear as dismissal button in the corner of the dialog.\n         */\n        public Builder setButtonText(@StringRes int resId) {\n            buttonTextId = resId;\n            return this;\n        }\n\n        /**\n         * Set the text that will appear as dismissal button in the corner of the dialog.\n         */\n        public Builder setButtonText(String string) {\n            buttonText = string;\n            return this;\n        }\n\n        /**\n         * Set whether or not you want the message text to be interpreted as HTML.\n         */\n        public Builder setHtmlInterpretation(boolean interpretHtml) {\n            this.interpretHtml = interpretHtml;\n            return this;\n        }\n\n        /**\n         * Set theme id that the {@link AlertDialog} will use.\n         */\n        public Builder setThemeId(int themeId) {\n            this.themeId = themeId;\n            return this;\n        }\n\n        public PermisoDialogFragment build(Context context) {\n            if (titleId > 0) { title = context.getString(titleId); }\n            if (messageId > 0) { message = context.getString(messageId); }\n            if (buttonTextId > 0) { buttonText = context.getString(buttonTextId); }\n            return PermisoDialogFragment.newInstance(this);\n        }\n    }\n}\n"
  },
  {
    "path": "permiso/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">Permiso</string>\n</resources>\n"
  },
  {
    "path": "permiso/src/test/java/com/greysonparrelli/permiso/ExampleUnitTest.java",
    "content": "package com.greysonparrelli.permiso;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * To work on unit tests, switch the Test Artifact in the Build Variants view.\n */\npublic class ExampleUnitTest {\n    @Test\n    public void addition_isCorrect() throws Exception {\n        assertEquals(4, 2 + 2);\n    }\n}"
  },
  {
    "path": "settings.gradle",
    "content": "include ':app', ':permiso'\n\nrootProject.name = 'permiso-root'\n"
  }
]