[
  {
    "path": ".gitignore",
    "content": "# Created by https://www.gitignore.io\n\n### Android ###\n# Built application files\n*.apk\n*.ap_\n\n# Files for the Dalvik VM\n*.dex\n\n# Java class files\n*.class\n\n# Generated files\nbin/\ngen/\n\n# Gradle files\n.gradle/\nbuild/\n/*/build/\ngradle.properties\n\n# Local configuration file (sdk path, etc)\nlocal.properties\n\n# Proguard folder generated by Eclipse\nproguard/\n\n# Log Files\n*.log\n\n\n### Intellij ###\n# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm\n\n*.iml\n\n## Directory-based project format:\n.idea/\n# if you remove the above rule, at least ignore the following:\n\n# User-specific stuff:\n# .idea/workspace.xml\n# .idea/tasks.xml\n# .idea/dictionaries\n\n# Sensitive or high-churn files:\n# .idea/dataSources.ids\n# .idea/dataSources.xml\n# .idea/sqlDataSources.xml\n# .idea/dynamic.xml\n# .idea/uiDesigner.xml\n\n# Gradle:\n# .idea/gradle.xml\n# .idea/libraries\n\n# Mongo Explorer plugin:\n# .idea/mongoSettings.xml\n\n## File-based project format:\n*.ipr\n*.iws\n\n## Plugin-specific files:\n\n# IntelliJ\nout/\n\n# mpeltonen/sbt-idea plugin\n.idea_modules/\n\n# JIRA plugin\natlassian-ide-plugin.xml\n\n# Crashlytics plugin (for Android Studio and IntelliJ)\ncom_crashlytics_export_strings.xml\ncrashlytics.properties\ncrashlytics-build.properties\n\n\n### Java ###\n*.class\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# Package Files #\n*.war\n*.ear\n\n# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml\nhs_err_pid*\n.DS_Store\n\n# fabric\nfabric.properties\n"
  },
  {
    "path": "README.md",
    "content": "IntentShare\n==================\n\n[![Maven Central](http://img.shields.io/maven-central/v/fr.tvbarthel.intentshare/library.svg)](http://search.maven.org/#search%7Cga%7C1%7Cintentshare)\n\n\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-IntentShare-brightgreen.svg?style=flat)](http://android-arsenal.com/details/1/3551)\n\nThis project is a light open-source library that improves the sharing experience on Android.\n\n* [Motivations](#motivations)\n* [Gradle dependency](#gradle-dependency)\n* [Sample app](#sample-app)\n* [Usage](#usage)\n  * [Simple usage](#simple-usage)\n  * [Dialog label](#dialog-label)\n  * [Image](#image)\n* [Extra Provider](#extra-provider)\n  * [Build-in extra provider](#build-in-extra-provider)\n  * [Custom extra provider](#custom-extra-provider)\n* [Listener](#listener)\n* [Icon Loader](#icon-loader)\n  * [Picasso](#picasso)\n  * [Glide](#glide)\n  * [Custom icon loader](#custom-icon-loader)\n* [Comparator Provider](#comparator-provider)\n* [Release Note](#release-note)\n* [What's next](#whats-next)\n* [Contributing](#contributing)\n* [License](#license)\n* [Special Thanks](#special-thanks-to-)\n\nMotivations\n=======\n\nNowadays, sharing content is part of our daily life. Unfortunately, the Android framework tools do not provide a sharing experience which reaches all of our expectations. We decided to implement our own tool, IntentShare, that might improve the user experience of a sharing action by :\n\n* providing different extras according to the chosen target activity in order to take advantages of each target's specificities.\n* providing an easy way to track the selected target activities in order to improve/adapt the extras for a specific target.\n* providing a sorted target activity list based on the context of your app in order to take advantages of how people use it.\n\nFind more about our motivations [here](http://tvbarthel.fr/IntentShare/).\n\n# Sample app\n[Sample app available on the PlayStore](https://play.google.com/store/apps/details?id=fr.tvbarthel.intentsharesample)\n\n# Gradle dependency\navailable on jcenter.\n```groovy\ncompile 'fr.tvbarthel.intentshare:library:0.0.4'\n```\n\ndependencies\n```groovy\ncompile 'com.android.support:appcompat-v7:25.0.0'\ncompile 'com.android.support:recyclerview-v7:25.0.0'\n```\n\n# Usage\n\n## Simple usage\n```java\nIntentShare.with(context)\n    .text(\"Default text you would like to share.\")\n    .deliver();\n```\n\n## Dialog label\n```java\nIntentShare.with(context)\n    .chooserTitle(\"Select a sharing target : \")\n    .text(\"Default text you would like to share.\")\n    .deliver();\n```\n\n## Image\n```java\nIntentShare.with(context)\n    .chooserTitle(\"Select a sharing target : \")\n    .text(\"Default text you would like to share.\")\n    .image(Uri.parse(\"content://com.example.test.fileprovider/data/img.png\"))\n    .deliver();\n```\n\n# Extra Provider\nAn extra provider can specify shared content for a given target activity.\n\n## Build-in extra provider\n\n### Facebook\n```java\nIntentShare.with(context)\n    .chooserTitle(\"Select a sharing target : \")\n    .text(\"Default text you would like to share.\")\n    .image(Uri.parse(\"content://com.example.test.fileprovider/data/img.png\"))\n    .facebookBody(Uri.parse(\"http://tvbarthel.fr\"))\n    .deliver();\n```\n\n### Twitter\n```java\nIntentShare.with(context)\n    .chooserTitle(\"Select a sharing target : \")\n    .text(\"Default text you would like to share.\")\n    .image(Uri.parse(\"content://com.example.test.fileprovider/data/img.png\"))\n    .twitterBody(\"Tweet can only have 140 char!\")\n    .deliver();\n```\n\n### Mail clients\n```java\nIntentShare.with(context)\n    .chooserTitle(\"Select a sharing target : \")\n    .text(\"Default text you would like to share.\")\n    .image(Uri.parse(\"content://com.example.test.fileprovider/data/img.png\"))\n    .mailSubject(\"Mail subject.\")\n    .mailBody(\"Extended text you would like to share in mail body.\")\n    .deliver();\n```\n\n## Custom extra provider\n```java\nIntentShare.with(context)\n    .chooserTitle(\"Select a sharing target : \")\n    .text(\"Default text you would like to share.\")\n    .image(Uri.parse(\"content://com.example.test.fileprovider/data/img.png\"))\n    .addExtraProvider(\n        new IntentShare.ExtraProvider(\"com.google.android.gm\")\n            .disableText()\n            .overrideSubject(\"Gmail subject, no mail body.\")\n            .disableImage()\n    )\n    .deliver();\n```\n\nBy default, an ExtraProvider will copy the default shared content.\nReplace default shared content :\n```java\n/**\n * Provide a specific text for the linked package name.\n *\n * @param text text which will be used as {@link android.content.Intent#EXTRA_TEXT}\n * @return {@link ExtraProvider} for chaining.\n */\npublic ExtraProvider overrideText(String text);\n\n/**\n * Provide a specific subject for the linked package name.\n *\n * @param subject subject which will be used as {@link android.content.Intent#EXTRA_SUBJECT}\n * @return {@link ExtraProvider} for chaining.\n */\npublic ExtraProvider overrideSubject(String subject);\n\n/**\n * Provide a specific image for the linked package name.\n *\n * @param image image which will be used as {@link android.content.Intent#EXTRA_STREAM}\n * @return {@link ExtraProvider} for chaining.\n */\npublic ExtraProvider overrideImage(Uri image);\n```\nAvoid copying default shared content without overriding:\n```java\n/**\n * Disable the extra {@link android.content.Intent#EXTRA_TEXT} for the linked package\n * to avoid a copy from the default {@link IntentShare} text.\n *\n * @return {@link ExtraProvider} for chaining.\n */\npublic ExtraProvider disableText();\n\n/**\n * Disable the extra {@link android.content.Intent#EXTRA_SUBJECT} for the linked package\n * to avoid a copy from the default {@link IntentShare} subject.\n *\n * @return {@link ExtraProvider} for chaining.\n */\npublic ExtraProvider disableSubject();\n\n/**\n * Disable the extra {@link android.content.Intent#EXTRA_STREAM} for the linked package\n * to avoid a copy from the default {@link IntentShare} image.\n *\n * @return {@link ExtraProvider} for chaining.\n */\npublic ExtraProvider disableImage();\n```\n\n# Listener\n\n```java\nintentShareListener = new IntentShareListener() {\n    @Override\n    public void onCompleted(String packageName) {\n        Log.d(TAG, \"onCompleted : \" + packageName);\n    }\n\n    @Override\n    public void onCanceled() {\n        Log.d(TAG, \"onCanceled\");\n    }\n};\n\nIntentShare.with(context)\n    .chooserTitle(\"Select a sharing target : \")\n    .text(\"Default text you would like to share.\")\n    .listener(intentShareListener)\n    .deliver();\n```\n\n# Icon loader\nDefault icon loader used to load target activities icons is based on AsyncTask.\n\n## Picasso\nIf your are already using Picasso, you may want to consider using PicassoIconLoader:\n```groovy\ncompile 'fr.tvbarthel.intentshare:picasso-loader:0.0.4'\n```\n\n```java\nIntentShare.with(context)\n    .chooserTitle(\"Select a sharing target : \")\n    .text(\"Default text you would like to share.\")\n    .iconLoader(new PicassoIconLoader())\n    .deliver();\n```\n\n## Glide\nIf your are already using Glide, you may want to consider using GlideIconLoader:\n```groovy\ncompile 'fr.tvbarthel.intentshare:glide-loader:0.0.4'\n```\n\n```java\nIntentShare.with(context)\n    .chooserTitle(\"Select a sharing target : \")\n    .text(\"Default text you would like to share.\")\n    .iconLoader(new GlideIconLoader())\n    .deliver();\n```\n\n## Custom icon loader\nImplement your own IconLoader:\n```java\nIntentShare.with(context)\n    .chooserTitle(\"Select a sharing target : \")\n    .text(\"Default text you would like to share.\")\n    .iconLoader(new IconLoader() {\n        @Override\n        public void load(Uri iconUri, ImageView imageView) {\n\n        }\n\n        @Override\n        public void cancel(ImageView imageView) {\n\n        }\n    })\n    .deliver();\n```\n# Comparator provider\nBy default, target activities are sorted based on the recency of their selection from your app.\n```java\n        /**\n         * Comparator used to sort {@link TargetActivity} based on the recency of their previous\n         * selection and their default order as fallback when they have never been selected.\n         * <p/>\n         * The ordering imposed by this comparator on a set of {@link TargetActivity}\n         * is not consistent with equals since c.compare(e1, e2)==0 has not the same boolean\n         * value as e1.equals(e2).\n         */\n        public RecencyComparatorProvider() {\n\n        }\n```\nInstead of using the default comparator, you can implement your own comparator provider in order to customize the target activities order display to the user:\n```java\n/**\n * ˙Interface which allow to define which comparator will be provided for sorting the\n * target activity inside the {@link TargetChooserActivity}.\n */\npublic interface TargetActivityComparatorProvider extends Parcelable {\n\n    /**\n     * Provide the comparator used to sort {@link TargetActivity} displayed to the user.\n     *\n     * @return comparator used to sort {@link TargetActivity} displayed to the user.\n     */\n    Comparator<TargetActivity> provideComparator();\n}\n```\n```java\nIntentShare.with(context)\n    .chooserTitle(\"Select a sharing target : \")\n    .text(\"Default text you would like to share.\")\n    .comparatorProvider(customComparatorProvider)\n    .deliver();\n```\nAn example from the sample can be found here : [SocialTargetActivityComparatorProvider.java](https://github.com/tvbarthel/IntentShare/blob/develop/sample/src/main/java/fr/tvbarthel/intentsharesample/SocialTargetActivityComparatorProvider.java)\n\n# Release Note\n\n* 0.0.4: min sdk set to 14.\n* 0.0.3: Tweet length check no longer performed (see #39). `allowbackup` disable by default.\n\n# What's next\n * Providing easier way to share images.\n * Removing dependencies on support libraries.\n * Sample : implementing image selection for extra provider.\n\n# Contributing\nContributions are very welcome (: You can contribute through GitHub by forking the repository and sending a pull request.\n\nWhen submitting code, please make sure ./gradlew check succeed.\n\n\n# License\n```\nCopyright (C) 2016 tvbarthel\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n\n# Special Thanks to ...\nVincent Brison [https://github.com/vincentbrison](https://github.com/vincentbrison) , for his precious advice.\nStéphane Guérin [https://github.com/guerwan](https://github.com/guerwan) , for his helpful feedback.\nRomain Zanon [https://github.com/romainz](https://github.com/romainz) , for his early day support.\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.2'\n        classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.1'\n        classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'\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\n\next {\n    buildToolsVersion = \"25.0.0\"\n    compileSdkVersion = 25\n    targetSdkVersion = 25\n    minSdkVersion = 14\n    versionCode = 4\n    versionName = \"0.0.4\"\n}\n"
  },
  {
    "path": "config/quality/checkstyle/checkstyle.xml",
    "content": "<?xml version=\"1.0\"?><!DOCTYPE module PUBLIC\n    \"-//Puppy Crawl//DTD Check Configuration 1.1//EN\"\n    \"http://www.puppycrawl.com/dtds/configuration_1_1.dtd\">\n\n\n<module name=\"Checker\">\n    <module name=\"FileLength\">\n        <property name=\"max\" value=\"700\" />\n        <property name=\"fileExtensions\" value=\"\" />\n    </module>\n\n    <module name=\"SuppressionFilter\">\n        <property name=\"file\" value=\"${checkstyleSuppressionsPath}\" />\n    </module>\n\n    <module name=\"TreeWalker\">\n\n        <!-- See http://checkstyle.sf.net/config_sizes.html !-->\n        <!-- Checks for long lines. !-->\n        <module name=\"LineLength\">\n            <property name=\"ignorePattern\" value=\"^$\" />\n            <property name=\"max\" value=\"120\" />\n        </module>\n\n        <!-- Checks the number of methods declared in each type. This includes the number of each scope !-->\n        <!-- (private, package, protected and public) as well as an overall total. !-->\n        <!-- See http://checkstyle.sourceforge.net/config_sizes.html#MethodCount !-->\n        <module name=\"MethodCount\">\n            <property name=\"maxTotal\" value=\"100\" />\n            <property name=\"maxPrivate\" value=\"100\" />\n            <property name=\"maxPackage\" value=\"100\" />\n            <property name=\"maxProtected\" value=\"100\" />\n            <property name=\"maxPublic\" value=\"100\" />\n        </module>\n\n        <!-- Checks for long methods and constructors. !-->\n        <!-- See http://checkstyle.sf.net/config_sizes.html !-->\n        <module name=\"MethodLength\">\n            <property name=\"max\" value=\"120\" />\n            <property name=\"countEmpty\" value=\"true\" />\n            <property name=\"tokens\" value=\"METHOD_DEF, CTOR_DEF\" />\n        </module>\n\n        <!-- Checks for the number of types declared at the outer (or root) level in a file. !-->\n        <!-- See http://checkstyle.sourceforge.net/config_sizes.html#OuterTypeNumber !-->\n        <module name=\"OuterTypeNumber\">\n            <property name=\"max\" value=\"1\" />\n        </module>\n\n        <!-- Checks the number of parameters of a method or constructor. !-->\n        <!-- See http://checkstyle.sf.net/config_sizes.html !-->\n        <module name=\"ParameterNumber\">\n            <!-- ReplacementSpan draw from AOSP is 9 parameters... !-->\n            <property name=\"max\" value=\"9\" />\n            <property name=\"tokens\" value=\"METHOD_DEF, CTOR_DEF\" />\n        </module>\n\n    </module>\n    <module name=\"TreeWalker\">\n\n        <!-- Checks the padding of an empty for initializer. !-->\n        <!-- See http://checkstyle.sf.net/config_whitespace.html !-->\n        <module name=\"EmptyForInitializerPad\">\n            <property name=\"option\" value=\"nospace\" />\n        </module>\n\n        <!-- Checks the padding of an empty for iterator. !-->\n        <!-- See http://checkstyle.sf.net/config_whitespace.html !-->\n        <module name=\"EmptyForIteratorPad\">\n            <property name=\"option\" value=\"nospace\" />\n        </module>\n\n        <!-- Checks that the whitespace around the Generic tokens < and > is correct to the typical convention. !-->\n        <!-- See http://checkstyle.sourceforge.net/config_whitespace.html#GenericWhitespace !-->\n        <module name=\"GenericWhitespace\" />\n\n        <!-- Checks the padding between the identifier of a method definition, !-->\n        <!-- constructor definition, method call, or constructor invocation; and the left parenthesis of the parameter list. !-->\n        <!-- See http://checkstyle.sf.net/config_whitespace.html !-->\n        <module name=\"MethodParamPad\">\n            <property name=\"allowLineBreaks\" value=\"false\" />\n            <property name=\"option\" value=\"nospace\" />\n            <property name=\"tokens\"\n                value=\"CTOR_DEF, LITERAL_NEW, METHOD_CALL, METHOD_DEF, SUPER_CTOR_CALL \" />\n        </module>\n\n        <!-- Checks that there is no whitespace after a token. !-->\n        <!-- See http://checkstyle.sf.net/config_whitespace.html !-->\n        <module name=\"NoWhitespaceAfter\">\n            <property name=\"allowLineBreaks\" value=\"true\" />\n            <property name=\"tokens\"\n                value=\"ARRAY_INIT, BNOT, DEC, DOT, INC, LNOT, UNARY_MINUS, UNARY_PLUS\" />\n        </module>\n\n        <!-- Checks that there is no whitespace before a token. !-->\n        <!-- See http://checkstyle.sf.net/config_whitespace.html !-->\n        <module name=\"NoWhitespaceBefore\">\n            <property name=\"allowLineBreaks\" value=\"false\" />\n            <property name=\"tokens\" value=\"SEMI, POST_DEC, POST_INC\" />\n        </module>\n\n        <!-- Checks the policy on how to wrap lines on operators. !-->\n        <!-- See http://checkstyle.sf.net/config_whitespace.html !-->\n        <module name=\"OperatorWrap\">\n            <property name=\"option\" value=\"nl\" />\n            <property name=\"tokens\" value=\"ASSIGN, BAND, BOR, BSR, BXOR, COLON, DIV,\n                                           EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF,\n                                           LOR, LT, MINUS, MOD, NOT_EQUAL,\n                                           PLUS, QUESTION, SL, SR, STAR\" />\n        </module>\n\n        <!-- Checks the policy on the padding of parentheses. !-->\n        <!-- See http://checkstyle.sf.net/config_whitespace.html !-->\n        <module name=\"ParenPad\">\n            <property name=\"option\" value=\"nospace\" />\n            <property name=\"tokens\"\n                value=\"CTOR_CALL, LPAREN, METHOD_CALL, RPAREN, SUPER_CTOR_CALL\" />\n        </module>\n\n        <!-- Checks the policy on the padding of parentheses for typecasts. !-->\n        <!-- See http://checkstyle.sf.net/config_whitespace.html !-->\n        <module name=\"TypecastParenPad\">\n            <property name=\"option\" value=\"nospace\" />\n            <property name=\"tokens\" value=\"TYPECAST, RPAREN\" />\n        </module>\n\n        <!-- Checks that a token is followed by whitespace. !-->\n        <!-- See http://checkstyle.sf.net/config_whitespace.html !-->\n        <module name=\"WhitespaceAfter\">\n            <property name=\"tokens\" value=\"COMMA, SEMI, TYPECAST\" />\n        </module>\n\n        <!-- Checks that a token is surrounded by whitespace. !-->\n        <!-- See http://checkstyle.sf.net/config_whitespace.html !-->\n        <module name=\"WhitespaceAround\">\n            <property name=\"tokens\" value=\"ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN,\n                                           BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, EQUAL, GE, GT, LAND,\n                                           LCURLY, LE, LITERAL_ASSERT, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE,\n                                           LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_RETURN,\n                                           LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, LOR, LT,\n                                           MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL, PLUS, PLUS_ASSIGN,\n                                           QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR, SR_ASSIGN, STAR, STAR_ASSIGN\" />\n            <property name=\"allowEmptyConstructors\" value=\"false\" />\n            <property name=\"allowEmptyMethods\" value=\"false\" />\n        </module>\n\n        <!-- The following checks are actually not whitespace checks, but still fit here quite well. !-->\n\n        <!-- Checks that there is only one statement per line. !-->\n        <!-- See http://checkstyle.sourceforge.net/config_coding.html#OneStatementPerLine !-->\n        <module name=\"OneStatementPerLine\" />\n\n        <!-- Checks that each variable declaration is in its own statement and on its own line. !-->\n        <!-- See http://checkstyle.sf.net/config_coding.html !-->\n        <module name=\"MultipleVariableDeclarations\" />\n\n    </module>\n\n    <!-- Checks that there are no tabs in the source file !-->\n    <!-- http://checkstyle.sourceforge.net/config_whitespace.html#FileTabCharacter !-->\n    <module name=\"FileTabCharacter\" />\n    <module name=\"TreeWalker\">\n        <!-- Checks that the outer type name and the file name match. !-->\n        <!-- See http://checkstyle.sourceforge.net/config_misc.html#OuterTypeFilename !-->\n        <module name=\"OuterTypeFilename\" />\n\n        <!-- Checks for class type parameter name naming conventions. !-->\n        <!-- See http://checkstyle.sourceforge.net/config_naming.html#ClassTypeParameterName !-->\n        <module name=\"ClassTypeParameterName\">\n            <property name=\"format\" value=\"^[A-Z]$\" />\n        </module>\n\n        <!-- Checks for constant name naming conventions. !-->\n        <!-- See http://checkstyle.sf.net/config_naming.html !-->\n        <module name=\"ConstantName\">\n            <property name=\"format\" value=\"^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$\" />\n            <property name=\"applyToPublic\" value=\"true\" />\n            <property name=\"applyToProtected\" value=\"true\" />\n            <property name=\"applyToPackage\" value=\"true\" />\n            <property name=\"applyToPrivate\" value=\"true\" />\n        </module>\n\n        <!-- Checks for local final variable name naming conventions. !-->\n        <!-- See http://checkstyle.sf.net/config_naming.html !-->\n        <module name=\"LocalFinalVariableName\">\n            <property name=\"format\" value=\"^[a-z][a-zA-Z0-9]*$\" />\n            <property name=\"tokens\" value=\"VARIABLE_DEF, PARAMETER_DEF\" />\n        </module>\n\n        <!-- Checks for local variable name naming conventions. !-->\n        <!-- See http://checkstyle.sf.net/config_naming.html !-->\n        <module name=\"LocalVariableName\">\n            <property name=\"format\" value=\"^[a-z][a-zA-Z0-9]*$\" />\n            <property name=\"tokens\" value=\"VARIABLE_DEF, PARAMETER_DEF\" />\n        </module>\n\n        <!-- Checks for member variable name naming conventions. !-->\n        <!-- See http://checkstyle.sf.net/config_naming.html !-->\n        <module name=\"MemberName\">\n            <property name=\"format\" value=\"^[a-z][a-zA-Z0-9]*$\" />\n            <property name=\"applyToPublic\" value=\"true\" />\n            <property name=\"applyToProtected\" value=\"true\" />\n            <property name=\"applyToPackage\" value=\"true\" />\n            <property name=\"applyToPrivate\" value=\"true\" />\n        </module>\n\n        <!-- Checks for method name naming conventions. !-->\n        <!-- See http://checkstyle.sf.net/config_naming.html !-->\n        <module name=\"MethodName\">\n            <property name=\"format\" value=\"^[a-z][a-zA-Z0-9]*$\" />\n        </module>\n\n        <!-- Checks for method type parameter name naming conventions. !-->\n        <!-- See http://checkstyle.sourceforge.net/config_naming.html#MethodTypeParameterName !-->\n        <module name=\"MethodTypeParameterName\">\n            <property name=\"format\" value=\"^[A-Z]$\" />\n        </module>\n\n        <!-- Checks for package name naming conventions. !-->\n        <!-- See http://checkstyle.sf.net/config_naming.html !-->\n        <module name=\"PackageName\">\n            <property name=\"format\" value=\"^[a-z][a-z0-9]*(\\.[a-zA-Z_][a-zA-Z0-9_]*)*$\" />\n        </module>\n\n        <!-- Checks for parameter name naming conventions. !-->\n        <!-- See http://checkstyle.sf.net/config_naming.html !-->\n        <module name=\"ParameterName\">\n            <property name=\"format\" value=\"^[a-z][a-zA-Z0-9]*$\" />\n        </module>\n\n        <!-- Checks for static variable name naming conventions. !-->\n        <!-- See http://checkstyle.sf.net/config_naming.html !-->\n        <module name=\"StaticVariableName\">\n            <property name=\"format\" value=\"^[a-z][a-zA-Z0-9]*$\" />\n            <property name=\"applyToPublic\" value=\"true\" />\n            <property name=\"applyToProtected\" value=\"true\" />\n            <property name=\"applyToPackage\" value=\"true\" />\n            <property name=\"applyToPrivate\" value=\"true\" />\n        </module>\n\n        <!-- Checks for type name naming conventions. !-->\n        <!-- See http://checkstyle.sf.net/config_naming.html !-->\n        <module name=\"TypeName\">\n            <property name=\"format\" value=\"^[A-Z][a-zA-Z0-9]*$\" />\n            <property name=\"tokens\" value=\"CLASS_DEF, INTERFACE_DEF\" />\n            <property name=\"applyToPublic\" value=\"true\" />\n            <property name=\"applyToProtected\" value=\"true\" />\n            <property name=\"applyToPackage\" value=\"true\" />\n            <property name=\"applyToPrivate\" value=\"true\" />\n        </module>\n\n    </module>\n    <module name=\"TreeWalker\">\n\n        <!-- Validates Javadoc comments to help ensure they are well formed. !-->\n        <!-- See http://checkstyle.sf.net/config_javadoc.html#JavadocStyle !-->\n        <module name=\"JavadocStyle\">\n            <property name=\"scope\" value=\"private\" />\n            <!--\n            <property name=\"excludeScope\"        value=\"\"/>\n            !-->\n            <property name=\"checkFirstSentence\" value=\"false\" />\n            <property name=\"endOfSentenceFormat\" value=\"([.?!][ \\t\\n\\r\\f&lt;])|([.?!]$)\" />\n            <property name=\"checkEmptyJavadoc\" value=\"false\" />\n            <property name=\"checkHtml\" value=\"true\" />\n            <property name=\"tokens\"\n                value=\"INTERFACE_DEF, CLASS_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF\" />\n        </module>\n\n        <!-- Checks Javadoc comments for class and interface definitions. !-->\n        <!-- See http://checkstyle.sf.net/config_javadoc.html#JavadocType !-->\n        <module name=\"JavadocType\">\n            <property name=\"scope\" value=\"package\" />\n            <!--\n            <property name=\"excludeScope\"          value=\"\"/>\n            !-->\n            <!--<property name=\"authorFormat\"          value=\"\"/>!-->\n            <!--<property name=\"versionFormat\"         value=\"\"/>!-->\n            <property name=\"allowMissingParamTags\" value=\"false\" />\n            <property name=\"allowUnknownTags\" value=\"false\" />\n            <property name=\"tokens\" value=\"INTERFACE_DEF, CLASS_DEF\" />\n        </module>\n\n        <!-- Checks to ensure that the javadoc tags exist (if required) !-->\n        <!-- See http://checkstyle.sf.net/config_javadoc.html#JavadocMethod !-->\n        <module name=\"JavadocMethod\">\n            <property name=\"scope\" value=\"package\" />\n            <!--\n            <property name=\"excludeScope\"                 value=\"\"/>\n            !-->\n            <property name=\"allowUndeclaredRTE\" value=\"false\" />\n            <property name=\"allowThrowsTagsForSubclasses\" value=\"false\" />\n            <property name=\"allowMissingParamTags\" value=\"false\" />\n            <property name=\"allowMissingThrowsTags\" value=\"false\" />\n            <property name=\"allowMissingReturnTag\" value=\"false\" />\n            <property name=\"allowMissingJavadoc\" value=\"false\" />\n            <property name=\"allowMissingPropertyJavadoc\" value=\"false\" />\n            <property name=\"logLoadErrors\" value=\"true\" />\n            <property name=\"suppressLoadErrors\" value=\"false\" />\n            <property name=\"tokens\" value=\"METHOD_DEF, CTOR_DEF\" />\n        </module>\n\n        <!-- Checks that variables have Javadoc comments. !-->\n        <!-- See http://checkstyle.sf.net/config_javadoc.html#JavadocVariable !-->\n        <module name=\"JavadocVariable\">\n            <property name=\"scope\" value=\"package\" />\n            <!--\n            <property name=\"excludeScope\" value=\"\"/>\n            !-->\n        </module>\n\n    </module>\n    <module name=\"TreeWalker\">\n\n        <!-- Ensure a class has a package declaration. !-->\n        <!-- See http://checkstyle.sf.net/config_coding.html !-->\n        <module name=\"PackageDeclaration\">\n            <property name=\"ignoreDirectoryName\" value=\"true\" />\n        </module>\n\n    </module>\n    <module name=\"TreeWalker\">\n\n        <!-- Checks visibility of class members. !-->\n        <!-- See http://checkstyle.sf.net/config_design.html !-->\n        <module name=\"VisibilityModifier\">\n            <property name=\"packageAllowed\" value=\"true\" />\n            <property name=\"protectedAllowed\" value=\"true\" />\n            <property name=\"publicMemberPattern\" value=\"^serialVersionUID$\" />\n        </module>\n\n        <!-- Checks that classes (except abtract one) define a ctor and don't rely on the default one. !-->\n        <!-- See http://checkstyle.sf.net/config_coding.html !-->\n        <!--<module name=\"MissingCtor\"/>!-->\n\n        <!-- Make sure that utility classes (classes that contain only static methods) do not have a public constructor. !-->\n        <!-- See http://checkstyle.sf.net/config_design.html !-->\n        <module name=\"HideUtilityClassConstructor\" />\n\n    </module>\n    <module name=\"TreeWalker\">\n\n        <!-- Checks that the order of modifiers conforms to the suggestions in the Java Language specification, !-->\n        <!-- sections 8.1.1, 8.3.1 and 8.4.3. !-->\n        <!-- See http://checkstyle.sf.net/config_modifiers.html !-->\n        <module name=\"ModifierOrder\" />\n\n        <!-- Checks that there are no redundant modifiers. !-->\n        <!-- See http://checkstyle.sf.net/config_modifiers.html\n        <module name=\"RedundantModifier\">\n            <property name=\"tokens\" value=\"METHOD_DEF, VARIABLE_DEF, ANNOTATION_FIELD_DEF\"/>\n        </module>\n         !-->\n\n        <!-- Checks that a class which has only private constructors is declared as final. !-->\n        <!-- See http://checkstyle.sf.net/config_design.html !-->\n        <module name=\"FinalClass\" />\n\n        <!-- Check nested (internal) classes/interfaces are declared at the bottom of the class after all method and field declarations. !-->\n        <!-- See http://checkstyle.sourceforge.net/config_design.html#InnerTypeLast !-->\n        <module name=\"InnerTypeLast\" />\n\n        <!-- Implements Bloch, Effective Java, Item 17 - Use Interfaces only to define types. !-->\n        <!-- See http://checkstyle.sf.net/config_design.html !-->\n        <module name=\"InterfaceIsType\">\n            <property name=\"allowMarkerInterfaces\" value=\"true\" />\n        </module>\n\n        <!-- Restricts throws statements to a specified count. !-->\n        <!-- See http://checkstyle.sf.net/config_design.html !-->\n        <module name=\"ThrowsCount\">\n            <property name=\"max\" value=\"2\" />\n        </module>\n\n        <!-- Checks that classes that define a covariant equals() method also override method equals(java.lang.Object). !-->\n        <!-- See http://checkstyle.sf.net/config_coding.html !-->\n        <module name=\"CovariantEquals\" />\n\n        <!-- Checks declaration order according to Code Conventions for the Java Programming Language. !-->\n        <!-- See http://checkstyle.sf.net/config_coding.html !-->\n        <module name=\"DeclarationOrder\">\n            <property name=\"ignoreConstructors\" value=\"false\" />\n            <property name=\"ignoreMethods\" value=\"false\" />\n            <property name=\"ignoreModifiers\" value=\"false\" />\n        </module>\n\n        <!-- Check that the default is after all the cases in a switch statement. !-->\n        <!-- See http://checkstyle.sf.net/config_coding.html !-->\n        <module name=\"DefaultComesLast\" />\n\n        <!-- Detects empty statements (standalone ;). !-->\n        <!-- See http://checkstyle.sf.net/config_coding.html !-->\n        <module name=\"EmptyStatement\" />\n\n        <!-- Catching java.lang.Exception, java.lang.Error or java.lang.RuntimeException is almost never acceptable. !-->\n        <!-- See http://checkstyle.sf.net/config_coding.html !-->\n        <module name=\"IllegalCatch\">\n            <property name=\"illegalClassNames\"\n                value=\"java.lang.Throwable, java.lang.RuntimeException\" />\n        </module>\n\n        <!-- This check can be used to ensure that types are not declared to be thrown. !-->\n        <!-- Declaring to throw java.lang.Error or java.lang.RuntimeException is almost never acceptable. !-->\n        <!-- See http://checkstyle.sourceforge.net/config_coding.html#IllegalThrows !-->\n        <module name=\"IllegalThrows\">\n            <property name=\"illegalClassNames\"\n                value=\"java.lang.Throwable, java.lang.Error, java.lang.RuntimeException\" />\n        </module>\n\n        <!-- Checks for assignments in subexpressions, such as in String s = Integer.toString(i = 2);. !-->\n        <!-- See http://checkstyle.sf.net/config_coding.html !-->\n        <module name=\"InnerAssignment\">\n            <property name=\"tokens\" value=\"ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BSR_ASSIGN, BXOR_ASSIGN,\n                                           DIV_ASSIGN, MINUS_ASSIGN, MOD_ASSIGN, PLUS_ASSIGN, SL_ASSIGN,\n                                           SR_ASSIGN, STAR_ASSIGN\" />\n        </module>\n\n        <!-- Checks that switch statement has \"default\" clause. !-->\n        <!-- See http://checkstyle.sf.net/config_coding.html !-->\n        <module name=\"MissingSwitchDefault\" />\n\n        <!-- Check for ensuring that for loop control variables are not modified inside the for block. !-->\n        <!-- See http://checkstyle.sourceforge.net/config_coding.html#ModifiedControlVariable !-->\n        <module name=\"ModifiedControlVariable\" />\n\n        <!-- Disallow assignment of parameters. !-->\n        <!-- See http://checkstyle.sf.net/config_coding.html !-->\n        <module name=\"ParameterAssignment\" />\n\n        <!-- this got moved here from the import checks !-->\n        <!-- Checks for unused import statements. !-->\n        <!-- See http://checkstyle.sf.net/config_import.html !-->\n        <module name=\"UnusedImports\" />\n\n    </module>\n\n\n</module>\n"
  },
  {
    "path": "config/quality/checkstyle/suppressions.xml",
    "content": "<?xml version=\"1.0\"?>\n\n<!DOCTYPE suppressions PUBLIC\n    \"-//Puppy Crawl//DTD Suppressions 1.1//EN\"\n    \"http://www.puppycrawl.com/dtds/suppressions_1_1.dtd\">\n\n<suppressions>\n    <suppress checks=\"[a-zA-Z0-9]*\" files=\"R.java\"/>\n    <suppress checks=\"[a-zA-Z0-9]*\" files=\"BuildConfig.java\"/>\n    <suppress checks=\"[a-zA-Z0-9]*\" files=\"Test\"/>\n</suppressions>"
  },
  {
    "path": "config/quality/findbugs/findbugs-filter.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<FindBugsFilter>\n    <!-- http://stackoverflow.com/questions/7568579/eclipsefindbugs-exclude-filter-files-doesnt-work -->\n    <Match>\n        <Class name=\"~.*\\.R\\$.*\" />\n    </Match>\n    <Match>\n        <Class name=\"~.*\\.Manifest\\$.*\" />\n    </Match>\n    <!-- All bugs in test classes, except for JUnit-specific bugs -->\n    <Match>\n        <Class name=\"~.*\\.*Test\" />\n        <Not>\n            <Bug code=\"IJU\" />\n        </Not>\n    </Match>\n    <Match>\n        <Bug pattern=\"ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD\"/>\n    </Match>\n</FindBugsFilter>"
  },
  {
    "path": "config/quality/lint/lint.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<lint>\n    <issue id=\"AdapterViewChildren\" severity=\"ignore\" />\n    <issue id=\"AllowBackup\" severity=\"ignore\" />\n    <issue id=\"AlwaysShowAction\" severity=\"ignore\" />\n    <issue id=\"ButtonCase\" severity=\"ignore\" />\n    <issue id=\"ButtonOrder\" severity=\"ignore\" />\n    <issue id=\"ButtonStyle\" severity=\"ignore\" />\n    <issue id=\"CommitPrefEdits\" severity=\"ignore\" />\n    <issue id=\"CommitTransaction\" severity=\"ignore\" />\n    <issue id=\"ContentDescription\" severity=\"ignore\" />\n    <issue id=\"CutPasteId\" severity=\"ignore\" />\n    <issue id=\"DalvikOverride\" severity=\"ignore\" />\n    <issue id=\"DefaultLocale\" severity=\"ignore\" />\n    <issue id=\"Deprecated\" severity=\"ignore\" />\n    <issue id=\"DeviceAdmin\" severity=\"ignore\" />\n    <issue id=\"DisableBaselineAlignment\" severity=\"ignore\" />\n    <issue id=\"DrawAllocation\" severity=\"ignore\" />\n    <issue id=\"DuplicateActivity\" severity=\"ignore\" />\n    <issue id=\"DuplicateDefinition\" severity=\"ignore\" />\n    <issue id=\"DuplicateIds\" severity=\"ignore\" />\n    <issue id=\"DuplicateIncludedIds\" severity=\"ignore\" />\n    <issue id=\"DuplicateUsesFeature\" severity=\"ignore\" />\n    <issue id=\"EnforceUTF8\" severity=\"ignore\" />\n    <issue id=\"ExportedContentProvider\" severity=\"ignore\" />\n    <issue id=\"ExportedReceiver\" severity=\"ignore\" />\n    <issue id=\"ExportedService\" severity=\"ignore\" />\n    <issue id=\"ExtraText\" severity=\"ignore\" />\n    <issue id=\"ExtraTranslation\" severity=\"ignore\" />\n    <issue id=\"FloatMath\" severity=\"ignore\" />\n    <issue id=\"GifUsage\" severity=\"ignore\" />\n    <issue id=\"GradleOverrides\" severity=\"ignore\" />\n    <issue id=\"GrantAllUris\" severity=\"ignore\" />\n    <issue id=\"GridLayout\" severity=\"ignore\" />\n    <issue id=\"HandlerLeak\" severity=\"ignore\" />\n    <issue id=\"HardcodedDebugMode\" severity=\"ignore\" />\n    <issue id=\"HardcodedText\" severity=\"ignore\" />\n    <issue id=\"IconColors\" severity=\"ignore\" />\n    <issue id=\"IconDensities\" severity=\"error\" />\n    <issue id=\"IconDipSize\" severity=\"error\" />\n    <issue id=\"IconDuplicates\" severity=\"ignore\" />\n    <issue id=\"IconDuplicatesConfig\" severity=\"ignore\" />\n    <issue id=\"IconExtension\" severity=\"ignore\" />\n    <issue id=\"IconLauncherShape\" severity=\"ignore\" />\n    <issue id=\"IconLocation\" severity=\"ignore\" />\n    <issue id=\"IconMissingDensityFolder\" severity=\"ignore\" />\n    <issue id=\"IconMixedNinePatch\" severity=\"ignore\" />\n    <issue id=\"IconNoDpi\" severity=\"ignore\" />\n    <issue id=\"IconXmlAndPng\" severity=\"ignore\" />\n    <issue id=\"IllegalResourceRef\" severity=\"ignore\" />\n    <issue id=\"InOrMmUsage\" severity=\"ignore\" />\n    <issue id=\"InconsistentArrays\" severity=\"ignore\" />\n    <issue id=\"InconsistentLayout\" severity=\"ignore\" />\n    <issue id=\"InefficientWeight\" severity=\"ignore\" />\n    <issue id=\"InlinedApi\" severity=\"ignore\" />\n    <issue id=\"InnerclassSeparator\" severity=\"ignore\" />\n    <issue id=\"Instantiatable\" severity=\"ignore\" />\n    <issue id=\"InvalidId\" severity=\"ignore\" />\n    <issue id=\"InvalidPackage\" severity=\"ignore\" />\n    <issue id=\"JavascriptInterface\" severity=\"ignore\" />\n    <issue id=\"LabelFor\" severity=\"ignore\" />\n    <issue id=\"LibraryCustomView\" severity=\"ignore\" />\n    <issue id=\"LocalSuppress\" severity=\"ignore\" />\n    <issue id=\"MangledCRLF\" severity=\"ignore\" />\n    <issue id=\"ManifestOrder\" severity=\"ignore\" />\n    <issue id=\"ManifestTypo\" severity=\"ignore\" />\n    <issue id=\"MenuTitle\" severity=\"ignore\" />\n    <issue id=\"MergeRootFrame\" severity=\"ignore\" />\n    <issue id=\"MissingApplicationIcon\" severity=\"ignore\" />\n    <issue id=\"MissingId\" severity=\"ignore\" />\n    <issue id=\"MissingPrefix\" severity=\"ignore\" />\n    <issue id=\"MissingQuantity\" severity=\"ignore\" />\n    <issue id=\"MissingRegistered\" severity=\"ignore\" />\n    <issue id=\"MissingSuperCall\" severity=\"ignore\" />\n    <issue id=\"MissingTranslation\" severity=\"ignore\" />\n    <issue id=\"MissingVersion\" severity=\"ignore\" />\n    <issue id=\"MockLocation\" severity=\"ignore\" />\n    <issue id=\"MultipleUsesSdk\" severity=\"ignore\" />\n    <issue id=\"NamespaceTypo\" severity=\"ignore\" />\n    <issue id=\"NestedScrolling\" severity=\"ignore\" />\n    <issue id=\"NestedWeights\" severity=\"ignore\" />\n    <issue id=\"NewApi\" severity=\"ignore\" />\n    <issue id=\"NotSibling\" severity=\"ignore\" />\n    <issue id=\"ObsoleteLayoutParam\" severity=\"ignore\" />\n    <issue id=\"OldTargetApi\" severity=\"ignore\" />\n    <issue id=\"OnClick\" severity=\"ignore\" />\n    <issue id=\"Orientation\" severity=\"ignore\" />\n    <issue id=\"Overdraw\" severity=\"ignore\" />\n    <issue id=\"Override\" severity=\"ignore\" />\n    <issue id=\"PackagedPrivateKey\" severity=\"ignore\" />\n    <issue id=\"ParcelCreator\" severity=\"ignore\" />\n    <issue id=\"PrivateResource\" severity=\"ignore\" />\n    <issue id=\"Proguard\" severity=\"ignore\" />\n    <issue id=\"ProguardSplit\" severity=\"ignore\" />\n    <issue id=\"ProtectedPermissions\" severity=\"ignore\" />\n    <issue id=\"PxUsage\" severity=\"ignore\" />\n    <issue id=\"Recycle\" severity=\"ignore\" />\n    <issue id=\"Registered\" severity=\"ignore\" />\n    <issue id=\"RequiredSize\" severity=\"ignore\" />\n    <issue id=\"ResAuto\" severity=\"ignore\" />\n    <issue id=\"ResourceAsColor\" severity=\"ignore\" />\n    <issue id=\"ScrollViewCount\" severity=\"ignore\" />\n    <issue id=\"ScrollViewSize\" severity=\"ignore\" />\n    <issue id=\"SdCardPath\" severity=\"ignore\" />\n    <issue id=\"SecureRandom\" severity=\"ignore\" />\n    <issue id=\"ServiceCast\" severity=\"ignore\" />\n    <issue id=\"SetJavaScriptEnabled\" severity=\"ignore\" />\n    <issue id=\"ShowToast\" severity=\"ignore\" />\n    <issue id=\"SimpleDateFormat\" severity=\"ignore\" />\n    <issue id=\"SmallSp\" severity=\"ignore\" />\n    <issue id=\"SpUsage\" severity=\"ignore\" />\n    <issue id=\"StateListReachable\" severity=\"ignore\" />\n    <issue id=\"StringFormatCount\" severity=\"ignore\" />\n    <issue id=\"StringFormatInvalid\" severity=\"ignore\" />\n    <issue id=\"StringFormatMatches\" severity=\"ignore\" />\n    <issue id=\"StyleCycle\" severity=\"ignore\" />\n    <issue id=\"Suspicious0dp\" severity=\"ignore\" />\n    <issue id=\"SuspiciousImport\" severity=\"ignore\" />\n    <issue id=\"TextFields\" severity=\"ignore\" />\n    <issue id=\"TextViewEdits\" severity=\"ignore\" />\n    <issue id=\"TooDeepLayout\" severity=\"ignore\" />\n    <issue id=\"TooManyViews\" severity=\"ignore\" />\n    <issue id=\"TrulyRandom\" severity=\"ignore\" />\n    <issue id=\"TypographyDashes\" severity=\"ignore\" />\n    <issue id=\"TypographyEllipsis\" severity=\"ignore\" />\n    <issue id=\"TypographyFractions\" severity=\"ignore\" />\n    <issue id=\"TypographyOther\" severity=\"ignore\" />\n    <issue id=\"Typos\" severity=\"ignore\" />\n    <issue id=\"UniquePermission\" severity=\"ignore\" />\n    <issue id=\"UnknownId\" severity=\"ignore\" />\n    <issue id=\"UnknownIdInLayout\" severity=\"ignore\" />\n    <issue id=\"UnlocalizedSms\" severity=\"ignore\" />\n    <issue id=\"UnusedNamespace\" severity=\"ignore\" />\n    <issue id=\"UnusedQuantity\" severity=\"ignore\" />\n    <issue id=\"UnusedResources\" severity=\"ignore\" />\n    <issue id=\"UseCheckPermission\" severity=\"ignore\" />\n    <issue id=\"UseCompoundDrawables\" severity=\"ignore\" />\n    <issue id=\"UseSparseArrays\" severity=\"ignore\" />\n    <issue id=\"UseValueOf\" severity=\"ignore\" />\n    <issue id=\"UselessLeaf\" severity=\"ignore\" />\n    <issue id=\"UselessParent\" severity=\"ignore\" />\n    <issue id=\"UsesMinSdkAttributes\" severity=\"ignore\" />\n    <issue id=\"ValidFragment\" severity=\"ignore\" />\n    <issue id=\"ViewConstructor\" severity=\"ignore\" />\n    <issue id=\"ViewTag\" severity=\"ignore\" />\n    <issue id=\"Wakelock\" severity=\"ignore\" />\n    <issue id=\"WorldReadableFiles\" severity=\"ignore\" />\n    <issue id=\"WorldWriteableFiles\" severity=\"ignore\" />\n    <issue id=\"WrongCall\" severity=\"ignore\" />\n    <issue id=\"WrongCase\" severity=\"ignore\" />\n    <issue id=\"WrongFolder\" severity=\"ignore\" />\n    <issue id=\"WrongManifestParent\" severity=\"ignore\" />\n    <issue id=\"WrongViewCast\" severity=\"ignore\" />\n</lint>"
  },
  {
    "path": "config/quality/pmd/pmd-ruleset.xml",
    "content": "<?xml version=\"1.0\"?>\n<ruleset xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" name=\"Android Application Rules\"\n    xmlns=\"http://pmd.sf.net/ruleset/1.0.0\"\n    xsi:noNamespaceSchemaLocation=\"http://pmd.sf.net/ruleset_xml_schema.xsd\"\n    xsi:schemaLocation=\"http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd\">\n\n    <description>Custom ruleset for Android application</description>\n\n    <exclude-pattern>.*/R.java</exclude-pattern>\n    <exclude-pattern>.*/gen/.*</exclude-pattern>\n\n    <!-- exclude test files !-->\n    <exclude-pattern>.*Test.java</exclude-pattern>\n\n    <rule ref=\"rulesets/java/android.xml\"/>\n    <rule ref=\"rulesets/java/clone.xml\" />\n    <rule ref=\"rulesets/java/finalizers.xml\" />\n    <rule ref=\"rulesets/java/imports.xml\" />\n    <rule ref=\"rulesets/java/logging-java.xml\" />\n    <rule ref=\"rulesets/java/braces.xml\" />\n    <rule ref=\"rulesets/java/strings.xml\">\n        <exclude name=\"AvoidDuplicateLiterals\" />\n        <exclude name=\"AvoidStringBufferField\"/>\n    </rule>\n    <rule ref=\"rulesets/java/basic.xml\" >\n        <exclude name=\"CollapsibleIfStatements\" />\n        <exclude name=\"AvoidBranchingStatementAsLastInLoop\" />\n    </rule>\n    <rule ref=\"rulesets/java/naming.xml\">\n        <exclude name=\"AbstractNaming\" />\n        <exclude name=\"LongVariable\" />\n        <exclude name=\"ShortMethodName\" />\n        <exclude name=\"ShortVariable\" />\n        <exclude name=\"VariableNamingConventions\" />\n        <exclude name=\"ShortClassName\" />\n        <exclude name=\"AvoidFieldNameMatchingMethodName\" />\n    </rule>\n</ruleset>"
  },
  {
    "path": "config/quality.gradle",
    "content": "apply plugin: 'checkstyle'\napply plugin: 'findbugs'\napply plugin: 'pmd'\n\n// Add checkstyle, findbugs, pmd and lint to the check task.\ncheck.dependsOn 'checkstyle', 'findbugs', 'pmd', 'lint'\n\n\ntask checkstyle(type: Checkstyle) {\n    configFile file(\"${project.rootDir}/config/quality/checkstyle/checkstyle.xml\")\n    configProperties.checkstyleSuppressionsPath = file(\"${project.rootDir}/config/quality/checkstyle/suppressions.xml\").absolutePath\n    source 'src'\n    include '**/*.java'\n    exclude '**/gen/**'\n\n    classpath = files()\n}\n\n\ntask findbugs(type: FindBugs) {\n    ignoreFailures = false\n    effort = \"max\"\n    reportLevel = \"high\"\n    excludeFilter = new File(\"${project.rootDir}/config/quality/findbugs/findbugs-filter.xml\")\n    classes = files(\"${project.rootDir}/library/build/intermediates/classes\")\n\n    source 'src'\n    include '**/*.java'\n    exclude '**/gen/**'\n\n    reports {\n        xml.enabled = false\n        html.enabled = true\n        xml {\n            destination \"$project.buildDir/reports/findbugs/findbugs.xml\"\n        }\n        html {\n            destination \"$project.buildDir/reports/findbugs/findbugs.html\"\n        }\n    }\n\n    classpath = files()\n}\n\ntask pmd(type: Pmd) {\n    ruleSetFiles = files(\"${project.rootDir}/config/quality/pmd/pmd-ruleset.xml\")\n    ignoreFailures = false\n    ruleSets = []\n\n    source 'src'\n    include '**/*.java'\n    exclude '**/gen/**'\n\n    reports {\n        xml.enabled = false\n        html.enabled = true\n        xml {\n            destination \"$project.buildDir/reports/pmd/pmd.xml\"\n        }\n        html {\n            destination \"$project.buildDir/reports/pmd/pmd.html\"\n        }\n    }\n}\n\nandroid {\n    lintOptions {\n        abortOnError false\n\n        lintConfig file(\"${project.rootDir}/config/quality/lint/lint.xml\")\n\n        // if true, generate an HTML report (with issue explanations, sourcecode, etc)\n        htmlReport true\n        // optional path to report (default will be lint-results.html in the builddir)\n        htmlOutput file(\"$project.buildDir/reports/lint/lint.html\")\n\n\n    }\n}\n"
  },
  {
    "path": "glide-loader/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "glide-loader/build.gradle",
    "content": "apply plugin: 'com.android.library'\napply plugin: 'com.github.dcendents.android-maven'\napply plugin: 'com.jfrog.bintray'\napply from: '../config/quality.gradle'\n\ngroup = 'fr.tvbarthel.intentshare'\nversion = rootProject.ext.versionName\n\nandroid {\n    compileSdkVersion rootProject.ext.compileSdkVersion\n    buildToolsVersion rootProject.ext.buildToolsVersion\n\n    defaultConfig {\n        minSdkVersion rootProject.ext.minSdkVersion\n        targetSdkVersion rootProject.ext.targetSdkVersion\n        versionCode rootProject.ext.versionCode\n        versionName rootProject.ext.versionName\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\n    compile project(':library')\n\n    compile 'com.github.bumptech.glide:glide:3.7.0'\n}\n\nProperties properties = new Properties()\nproperties.load(project.rootProject.file('local.properties').newDataInputStream())\ndef bintrayUser = properties.getProperty('bintray.user')\ndef bintrayKey = properties.getProperty('bintray.apikey')\n\nbintray {\n    user = bintrayUser\n    key = bintrayKey\n\n\n    configurations = ['archives'] //When uploading configuration files\n\n    dryRun = false //Whether to run this as dry-run, without deploying\n    publish = true //If version should be auto published after an upload\n    //Package configuration. The plugin will use the repo and name properties to check if the package already exists. In that case, there's no need to configure the other package properties (like userOrg, desc, etc).\n    pkg {\n        repo = 'maven'\n        name = 'GlideLoader'\n        desc = 'Icon loader based on Glide for IntentShare library.'\n        websiteUrl = 'https://github.com/tvbarthel/IntentShare'\n        issueTrackerUrl = 'https://github.com/tvbarthel/IntentShare/issues'\n        vcsUrl = 'https://github.com/tvbarthel/IntentShare.git'\n        licenses = ['Apache-2.0']\n        labels = ['android', 'intent', 'sharing', 'share', 'glide']\n        publicDownloadNumbers = true\n        version {\n            gpg {\n                sign = true //Determines whether to GPG sign the files. The default is false\n            }\n        }\n\n    }\n}\n\ninstall {\n    repositories.mavenInstaller {\n        pom {\n            project {\n                packaging 'aar'\n                name 'GlideLoader'\n                url 'https://github.com/tvbarthel/IntentShare'\n                description 'Icon loader based on Glide for IntentShare library.'\n                licenses {\n                    license {\n                        name 'The Apache Software License, Version 2.0'\n                        url 'http://www.apache.org/licenses/LICENSE-2.0.txt'\n                    }\n                }\n                developers {\n                    developer {\n                        id 'tbarthel-fr'\n                        name 'Thomas Barthelemy'\n                        email 'thomas.barthelemy.utc@gmail.com'\n                    }\n                    developer {\n                        id 'vbarthel-fr'\n                        name 'Vincent Barthelemy'\n                        email 'vincent.barthelemy.perso@gmail.com'\n                    }\n                }\n                scm {\n                    connection 'https://github.com/tvbarthel/IntentShare.git'\n                    developerConnection 'https://github.com/tvbarthel/IntentShare.git'\n                    url 'https://github.com/tvbarthel/IntentShare'\n\n                }\n            }\n        }\n    }\n}\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    failOnError = false\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"
  },
  {
    "path": "glide-loader/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/thomasbarthelemy/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": "glide-loader/src/main/AndroidManifest.xml",
    "content": "<manifest package=\"fr.tvbarthel.intentshare.loader.glide\">\n\n    <application  />\n\n</manifest>\n"
  },
  {
    "path": "glide-loader/src/main/java/fr/tvbarthel/intentshare/loader/glide/GlideIconLoader.java",
    "content": "package fr.tvbarthel.intentshare.loader.glide;\n\nimport android.net.Uri;\nimport android.os.Parcel;\nimport android.widget.ImageView;\n\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.load.engine.DiskCacheStrategy;\n\nimport fr.tvbarthel.intentshare.IconLoader;\n\n/**\n * {@link fr.tvbarthel.intentshare.IconLoader} based on {@link com.bumptech.glide.Glide}\n */\npublic class GlideIconLoader implements IconLoader {\n\n    /**\n     * Parcelable\n     */\n    public static final Creator<GlideIconLoader> CREATOR = new Creator<GlideIconLoader>() {\n        @Override\n        public GlideIconLoader createFromParcel(Parcel source) {\n            return new GlideIconLoader(source);\n        }\n\n        @Override\n        public GlideIconLoader[] newArray(int size) {\n            return new GlideIconLoader[size];\n        }\n    };\n\n    /**\n     * {@link fr.tvbarthel.intentshare.IconLoader} based on {@link com.bumptech.glide.Glide}\n     */\n    public GlideIconLoader() {\n    }\n\n    /**\n     * {@link fr.tvbarthel.intentshare.IconLoader} based on {@link com.bumptech.glide.Glide}\n     *\n     * @param in parcel.\n     */\n    protected GlideIconLoader(Parcel in) {\n    }\n\n    @Override\n    public void load(Uri iconUri, ImageView imageView) {\n        Glide.with(imageView.getContext())\n                .load(iconUri)\n                .fitCenter()\n                .diskCacheStrategy(DiskCacheStrategy.RESULT)\n                .into(imageView);\n    }\n\n    @Override\n    public void cancel(ImageView imageView) {\n        Glide.clear(imageView);\n    }\n\n    @Override\n    public int describeContents() {\n        return 0;\n    }\n\n    @Override\n    public void writeToParcel(Parcel dest, int flags) {\n    }\n\n}\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Fri Nov 11 10:54:16 CET 2016\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": "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": "library/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "library/build.gradle",
    "content": "apply plugin: 'com.android.library'\napply plugin: 'com.github.dcendents.android-maven'\napply plugin: 'com.jfrog.bintray'\napply from: '../config/quality.gradle'\n\ngroup = 'fr.tvbarthel.intentshare'\nversion = rootProject.ext.versionName\n\nandroid {\n    compileSdkVersion rootProject.ext.compileSdkVersion\n    buildToolsVersion rootProject.ext.buildToolsVersion\n\n    resourcePrefix 'isl_'\n\n    defaultConfig {\n        minSdkVersion rootProject.ext.minSdkVersion\n        targetSdkVersion rootProject.ext.targetSdkVersion\n        versionCode rootProject.ext.versionCode\n        versionName rootProject.ext.versionName\n    }\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    testCompile 'org.mockito:mockito-core:1.9.5'\n    testCompile 'org.robolectric:robolectric:3.0'\n    compile 'com.android.support:appcompat-v7:25.0.0'\n    compile 'com.android.support:recyclerview-v7:25.0.0'\n}\n\nProperties properties = new Properties()\nproperties.load(project.rootProject.file('local.properties').newDataInputStream())\ndef bintrayUser = properties.getProperty('bintray.user')\ndef bintrayKey = properties.getProperty('bintray.apikey')\n\nbintray {\n    user = bintrayUser\n    key = bintrayKey\n\n\n    configurations = ['archives'] //When uploading configuration files\n\n    dryRun = false //Whether to run this as dry-run, without deploying\n    publish = true //If version should be auto published after an upload\n    //Package configuration. The plugin will use the repo and name properties to check if the package already exists. In that case, there's no need to configure the other package properties (like userOrg, desc, etc).\n    pkg {\n        repo = 'maven'\n        name = 'IntentShare'\n        desc = 'IntentShare is a light open-source library that improves the sharing experience of their Android applications.'\n        websiteUrl = 'https://github.com/tvbarthel/IntentShare'\n        issueTrackerUrl = 'https://github.com/tvbarthel/IntentShare/issues'\n        vcsUrl = 'https://github.com/tvbarthel/IntentShare.git'\n        licenses = ['Apache-2.0']\n        labels = ['android', 'intent', 'sharing', 'share']\n        publicDownloadNumbers = true\n        version {\n            gpg {\n                sign = true //Determines whether to GPG sign the files. The default is false\n            }\n        }\n\n    }\n}\n\ninstall {\n    repositories.mavenInstaller {\n        pom {\n            project {\n                packaging 'aar'\n                name 'IntentShare'\n                url 'https://github.com/tvbarthel/IntentShare'\n                description 'IntentShare is a light open-source library that improves the sharing experience of their Android applications.'\n                licenses {\n                    license {\n                        name 'The Apache Software License, Version 2.0'\n                        url 'http://www.apache.org/licenses/LICENSE-2.0.txt'\n                    }\n                }\n                developers {\n                    developer {\n                        id 'tbarthel-fr'\n                        name 'Thomas Barthelemy'\n                        email 'thomas.barthelemy.utc@gmail.com'\n                    }\n                    developer {\n                        id 'vbarthel-fr'\n                        name 'Vincent Barthelemy'\n                        email 'vincent.barthelemy.perso@gmail.com'\n                    }\n                }\n                scm {\n                    connection 'https://github.com/tvbarthel/IntentShare.git'\n                    developerConnection 'https://github.com/tvbarthel/IntentShare.git'\n                    url 'https://github.com/tvbarthel/IntentShare'\n\n                }\n            }\n        }\n    }\n}\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    failOnError = false\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"
  },
  {
    "path": "library/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 /home/thomas/Documents/android-sdk-linux/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": "library/src/androidTest/java/fr/tvbarthel/intentshare/ApplicationTest.java",
    "content": "package fr.tvbarthel.intentshare;\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": "library/src/main/AndroidManifest.xml",
    "content": "<manifest package=\"fr.tvbarthel.intentshare\"\n    xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <application>\n\n        <activity\n            android:name=\".TargetChooserActivity\"\n            android:theme=\"@style/IntentShareTheme\" />\n\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "library/src/main/java/fr/tvbarthel/intentshare/AsyncIconLoader.java",
    "content": "package fr.tvbarthel.intentshare;\n\nimport android.content.pm.PackageManager;\nimport android.content.res.Resources;\nimport android.graphics.Bitmap;\nimport android.graphics.BitmapFactory;\nimport android.net.Uri;\nimport android.os.AsyncTask;\nimport android.os.Parcel;\nimport android.util.Log;\nimport android.util.SparseArray;\nimport android.widget.ImageView;\n\nimport java.util.HashMap;\nimport java.util.List;\n\n/**\n * Icon loader based on an {@link AsyncTask}.\n * <p/>\n * No cashing is performed for decoded {@link Bitmap}.\n */\nclass AsyncIconLoader implements IconLoader {\n\n    /**\n     * Parcelable.\n     */\n    public static final Creator<AsyncIconLoader> CREATOR = new Creator<AsyncIconLoader>() {\n        @Override\n        public AsyncIconLoader createFromParcel(Parcel source) {\n            return new AsyncIconLoader(source);\n        }\n\n        @Override\n        public AsyncIconLoader[] newArray(int size) {\n            return new AsyncIconLoader[size];\n        }\n    };\n\n    private SparseArray<AsyncIconLoaderTask> task;\n    private HashMap<Uri, Bitmap> cachedIcons;\n\n    /**\n     * Icon loader based on an {@link AsyncTask}\n     * <p/>\n     * No cashing is performed for decoded {@link Bitmap}.\n     *\n     * @param in parcel.\n     */\n    protected AsyncIconLoader(Parcel in) {\n        this();\n    }\n\n    /**\n     * Icon loader based on an {@link AsyncTask}\n     * <p/>\n     * No cashing is performed for decoded {@link Bitmap}.\n     */\n    public AsyncIconLoader() {\n        task = new SparseArray<>();\n        cachedIcons = new HashMap<>();\n    }\n\n    @Override\n    public int describeContents() {\n        return 0;\n    }\n\n    @Override\n    public void writeToParcel(Parcel dest, int flags) {\n    }\n\n    @Override\n    public void load(Uri iconUri, ImageView imageView) {\n        Bitmap bitmap = cachedIcons.get(iconUri);\n        if (bitmap != null) {\n            imageView.setImageBitmap(bitmap);\n        } else {\n            AsyncIconLoaderTask asyncIconLoaderTask\n                    = new AsyncIconLoaderTask(iconUri, imageView, cachedIcons);\n            task.put(imageView.hashCode(), asyncIconLoaderTask);\n            asyncIconLoaderTask.execute();\n        }\n    }\n\n    @Override\n    public void cancel(ImageView imageView) {\n        int key = imageView.hashCode();\n        AsyncIconLoaderTask asyncIconLoaderTask = task.get(key);\n        if (asyncIconLoaderTask != null) {\n            asyncIconLoaderTask.cancel(true);\n            task.remove(key);\n        }\n    }\n\n    /**\n     * {@link AsyncTask} used to load an icon off the ui thread.\n     */\n    private static final class AsyncIconLoaderTask extends AsyncTask<Void, Void, Bitmap> {\n\n        private static final String TAG = AsyncIconLoaderTask.class.getSimpleName();\n\n        private final ImageView imageTarget;\n        private final PackageManager packageManager;\n        private final String targetPackage;\n        private final HashMap<Uri, Bitmap> cachedIcons;\n        private final Uri uri;\n        private int iconResId;\n        private int targetSize;\n\n        /**\n         * {@link AsyncTask} used to load an icon off the ui thread.\n         *\n         * @param uri         uri of the icon to load.\n         * @param imageView   image view in which the icon should be loaded.\n         * @param cachedIcons list of bitmap to which the new decoded one will be added.\n         */\n        public AsyncIconLoaderTask(Uri uri, ImageView imageView, HashMap<Uri, Bitmap> cachedIcons) {\n            packageManager = imageView.getContext().getPackageManager();\n            this.uri = uri;\n            targetPackage = uri.getAuthority();\n            iconResId = 0;\n\n            List<String> pathSegments = uri.getPathSegments();\n            if (pathSegments.size() != 1) {\n                Log.e(TAG, \"Can't find the icon res id for : \" + uri.toString());\n            } else {\n                try {\n                    iconResId = Integer.parseInt(pathSegments.get(0));\n                } catch (NumberFormatException e) {\n                    Log.e(TAG, \"Can't parse the icon res id : \" + pathSegments.get(0));\n                }\n            }\n\n            imageTarget = imageView;\n            targetSize = imageView.getContext().getResources()\n                    .getDimensionPixelSize(R.dimen.isl_target_activity_view_icon_size);\n            this.cachedIcons = cachedIcons;\n        }\n\n        @Override\n        protected Bitmap doInBackground(Void... params) {\n            Resources resources;\n            try {\n                resources = packageManager.getResourcesForApplication(targetPackage);\n            } catch (PackageManager.NameNotFoundException e) {\n                Log.e(TAG, \"Wrong package name, can't access to the resources : \" + targetPackage);\n                return null;\n            }\n\n            if (isCancelled()) {\n                return null;\n            }\n\n            final BitmapFactory.Options options = new BitmapFactory.Options();\n            options.inJustDecodeBounds = true;\n            options.inPreferredConfig = Bitmap.Config.RGB_565;\n            BitmapFactory.decodeResource(resources, iconResId, options);\n\n            if (isCancelled()) {\n                return null;\n            }\n\n            options.inSampleSize = calculateInSampleSize(options, targetSize, targetSize);\n            options.inJustDecodeBounds = false;\n\n            if (isCancelled()) {\n                return null;\n            } else {\n                return BitmapFactory.decodeResource(resources, iconResId, options);\n            }\n        }\n\n        @Override\n        protected void onPostExecute(Bitmap bitmap) {\n            super.onPostExecute(bitmap);\n            if (bitmap != null) {\n                imageTarget.setImageBitmap(bitmap);\n                cachedIcons.put(uri, bitmap);\n            } else {\n                Log.e(TAG, \"Failed to load icon from uri : \" + uri);\n            }\n        }\n\n        private int calculateInSampleSize(\n                BitmapFactory.Options options,\n                int reqWidth,\n                int reqHeight) {\n            final int height = options.outHeight;\n            final int width = options.outWidth;\n\n            if (reqWidth == 0 || reqHeight == 0) {\n                return 1;\n            } else {\n                int heightRatio = (int) Math.floor((float) height / (float) reqHeight);\n                int widthRatio = (int) Math.floor((float) width / (float) reqWidth);\n                return Math.min(heightRatio, widthRatio);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/fr/tvbarthel/intentshare/BottomRecyclerView.java",
    "content": "package fr.tvbarthel.intentshare;\n\nimport android.content.Context;\nimport android.support.v7.widget.RecyclerView;\nimport android.util.AttributeSet;\nimport android.view.MotionEvent;\nimport android.view.View;\n\n/**\n * Simple RecyclerView on which top padding could be assigned and enable touch on view under.\n */\nclass BottomRecyclerView extends RecyclerView {\n\n    /**\n     * Simple RecyclerView on which top padding could be assigned and enable touch on view under.\n     *\n     * @param context holding context.\n     */\n    public BottomRecyclerView(Context context) {\n        super(context);\n    }\n\n    /**\n     * Simple RecyclerView on which top padding could be assigned and enable touch on view under.\n     *\n     * @param context holding context.\n     * @param attrs   attr from xml.\n     */\n    public BottomRecyclerView(Context context, AttributeSet attrs) {\n        super(context, attrs);\n    }\n\n    /**\n     * Simple RecyclerView on which top padding could be assigned and enable touch on view under.\n     *\n     * @param context      holding context.\n     * @param attrs        attr from xml.\n     * @param defStyleAttr style.\n     */\n    public BottomRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n    }\n\n    @Override\n    public boolean onTouchEvent(MotionEvent ev) {\n        boolean handled = super.onTouchEvent(ev);\n        View child = getChildAt(0);\n        if (child == null || ev.getY() < child.getY()) {\n            handled = false;\n        }\n        return handled;\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/fr/tvbarthel/intentshare/IconLoader.java",
    "content": "package fr.tvbarthel.intentshare;\n\nimport android.net.Uri;\nimport android.os.Parcelable;\nimport android.widget.ImageView;\n\n/**\n * Interface which define the contract of a loader used to load\n * {@link TargetActivity} icons.\n */\npublic interface IconLoader extends Parcelable {\n\n    /**\n     * Called when the icon should be load into the imageView.\n     * <p/>\n     * See also : {@link IconLoader#cancel(ImageView)}\n     *\n     * @param iconUri   uri of the icon to load.\n     * @param imageView image view in which the icon should be loaded.\n     */\n    void load(Uri iconUri, ImageView imageView);\n\n    /**\n     * Called when the icon doesn't need to be loaded anymore.\n     * Should cancel any async loading started previously.\n     * <p/>\n     * See also : {@link IconLoader#load(Uri, ImageView)}\n     *\n     * @param imageView image view for which the async loading should be canceled.\n     */\n    void cancel(ImageView imageView);\n}\n"
  },
  {
    "path": "library/src/main/java/fr/tvbarthel/intentshare/IntentShare.java",
    "content": "package fr.tvbarthel.intentshare;\n\nimport android.content.Context;\nimport android.net.Uri;\nimport android.os.Parcel;\nimport android.os.Parcelable;\nimport android.support.annotation.NonNull;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * {@link IntentShare} is designed to enhance the sharing experience by allowing to share\n * different content according to the application the user will choose to share with.\n */\npublic final class IntentShare implements Parcelable {\n\n    /**\n     * Parcelable.\n     */\n    public static final Parcelable.Creator<IntentShare> CREATOR = new Parcelable.Creator<IntentShare>() {\n        public IntentShare createFromParcel(Parcel source) {\n            return new IntentShare(source);\n        }\n\n        public IntentShare[] newArray(int size) {\n            return new IntentShare[size];\n        }\n    };\n\n    /**\n     * Facebook package.\n     */\n    public static final String FACEBOOK = \"com.facebook.katana\";\n\n    /**\n     * Twitter package.\n     */\n    public static final String TWITTER = \"com.twitter.android\";\n\n    /**\n     * Text which will be shared by default.\n     */\n    String text;\n\n    /**\n     * Uri of the image add as {@link android.content.Intent#EXTRA_STREAM}\n     */\n    Uri imageUri;\n\n    /**\n     * Text used as mail body if the targeted application is a mail one.\n     */\n    String mailBody;\n\n    /**\n     * Text used as mail subject if the targeted application is a mail one.\n     */\n    String mailSubject;\n\n    /**\n     * Specific extra provider for some package.\n     */\n    ArrayList<ExtraProvider> extraProviders;\n\n    /**\n     * Keep a track on package with a specific\n     * {@link fr.tvbarthel.intentshare.IntentShare.ExtraProvider} in order to warn the user when\n     * two provider are added for the same package.\n     */\n    List<String> packageWithExtraProvider;\n\n\n    /**\n     * Icon loader used to load icons.\n     */\n    IconLoader iconLoader;\n\n    /**\n     * Provide the comparator used to sort the target activities.\n     */\n    TargetActivityComparatorProvider comparatorProvider;\n\n    /**\n     * Title that will be displayed in the chooser.\n     */\n    String chooserTitle;\n\n    /**\n     * Context used to start the activity used to choose a target one.\n     */\n    private Context context;\n    private IntentShareListener listener;\n\n    /**\n     * {@link IntentShare} is designed to enhance the sharing experience by allowing to share\n     * different content according to the application the user will choose to share with.\n     *\n     * @param context context used send the {@link android.content.Intent}\n     */\n    private IntentShare(Context context) {\n        this.context = context;\n        extraProviders = new ArrayList<>();\n        packageWithExtraProvider = new ArrayList<>();\n        this.listener = null;\n        this.iconLoader = new AsyncIconLoader();\n        this.comparatorProvider = new TargetActivity.RecencyComparatorProvider();\n        this.chooserTitle = context.getString(R.string.isl_default_sharing_label);\n    }\n\n    /**\n     * {@link IntentShare} is designed to enhance the sharing experience by allowing to share\n     * different content according to the application the user will choose to share with.\n     *\n     * @param in parcel.\n     */\n    protected IntentShare(Parcel in) {\n        this.text = in.readString();\n        this.imageUri = in.readParcelable(Uri.class.getClassLoader());\n        this.mailBody = in.readString();\n        this.mailSubject = in.readString();\n        this.extraProviders = in.createTypedArrayList(ExtraProvider.CREATOR);\n        this.iconLoader = in.readParcelable(IconLoader.class.getClassLoader());\n        this.comparatorProvider = in.readParcelable(TargetActivityComparatorProvider.class.getClassLoader());\n        this.chooserTitle = in.readString();\n    }\n\n    @Override\n    public int describeContents() {\n        return 0;\n    }\n\n    @Override\n    public void writeToParcel(Parcel dest, int flags) {\n        dest.writeString(this.text);\n        dest.writeParcelable(this.imageUri, 0);\n        dest.writeString(this.mailBody);\n        dest.writeString(this.mailSubject);\n        dest.writeTypedList(this.extraProviders);\n        dest.writeParcelable(this.iconLoader, flags);\n        dest.writeParcelable(this.comparatorProvider, flags);\n        dest.writeString(this.chooserTitle);\n    }\n\n    /**\n     * {@link IntentShare} is designed to enhance the sharing experience by allowing to share\n     * different content according to the application the user will choose to share with.\n     *\n     * @param context context from which the sharing is initiated.\n     * @return new instance.\n     */\n    @NonNull\n    public static IntentShare with(@NonNull Context context) {\n        return new IntentShare(context);\n    }\n\n    /**\n     * Title that will be displayed in the chooser.\n     * <p/>\n     * Will be displayed on a single line.\n     *\n     * @param title title that will be displayed in the chooser.\n     * @return current {@link IntentShare} for method chaining.\n     */\n    public IntentShare chooserTitle(@NonNull String title) {\n        this.chooserTitle = title;\n        return this;\n    }\n\n    /**\n     * Set the {@link IconLoader} used to load target activities icon.\n     *\n     * @param iconLoader icon loader.\n     * @return current {@link IntentShare} for method chaining.\n     */\n    public IntentShare iconLoader(@NonNull IconLoader iconLoader) {\n        this.iconLoader = iconLoader;\n        return this;\n    }\n\n    /**\n     * Provide a custom {@link java.util.Comparator} in order to sort the {@link TargetActivity}\n     * displayed to the user.\n     * <p/>\n     * By default, TargetActivities are sorted by the recentness of their selection. If it's the\n     * behaviour that you are looking for, don't use this method and let the default comparator\n     * bring the magic.\n     *\n     * @param comparatorProvider comparator used to sort the TargetActivities displayed to the user.\n     *                           Will override the default sorting by recentness.\n     * @return current {@link IntentShare} for method chaining.\n     */\n    public IntentShare comparatorProvider(@NonNull TargetActivityComparatorProvider comparatorProvider) {\n        if (comparatorProvider == null) {\n            throw new NullPointerException(\"Custom comparator provider can't be null.\");\n        }\n        this.comparatorProvider = comparatorProvider;\n        return this;\n    }\n\n    /**\n     * Text which will be shared.\n     * <p/>\n     * Will be used as {@link android.content.Intent#EXTRA_TEXT}\n     *\n     * @param text text to share.\n     * @return current {@link IntentShare} for method chaining.\n     */\n    @NonNull\n    public IntentShare text(@NonNull String text) {\n        this.text = text;\n        return this;\n    }\n\n    /**\n     * Image which will be set as {@link android.content.Intent#EXTRA_STREAM} if the\n     * target application can handle it.\n     *\n     * @param imageUri Uri of the image.\n     * @return current {@link IntentShare} for method chaining.\n     */\n    @NonNull\n    public IntentShare image(@NonNull Uri imageUri) {\n        String lastPathSegment = imageUri.getLastPathSegment();\n        if (!lastPathSegment.endsWith(\".png\") && !lastPathSegment.endsWith(\".jpg\")) {\n            throw new IllegalArgumentException(\"Invalid image uri : only .png and .jpg file supported : \"\n                    + imageUri);\n        } else if (!\"content\".equals(imageUri.getScheme())) {\n            throw new IllegalArgumentException(\"Invalid image uri : only content scheme supported : \"\n                    + imageUri);\n        } else {\n            this.imageUri = imageUri;\n        }\n        return this;\n    }\n\n    /**\n     * Text which will be shared by any application marked as mail client\n     * (application which can handle \"message/rfc822\").\n     * <p/>\n     * Override {@link IntentShare#text(String)} for every mail application.\n     *\n     * @param mailBody text set as text body for mail application.\n     * @return current {@link IntentShare} for method chaining.\n     */\n    @NonNull\n    public IntentShare mailBody(@NonNull String mailBody) {\n        this.mailBody = mailBody;\n        return this;\n    }\n\n    /**\n     * Text which will be displayed inside the subject field of any application marked as mail\n     * client (applcation which can handle \"message/rfc822\").\n     * <p/>\n     * See also : {@link IntentShare#mailBody(String)}\n     *\n     * @param mailSubject subject of the mail.\n     * @return current {@link IntentShare} for method chaining.\n     */\n    @NonNull\n    public IntentShare mailSubject(@NonNull String mailSubject) {\n        this.mailSubject = mailSubject;\n        return this;\n    }\n\n    /**\n     * Link which will be used as single shared content if target application is the facebook\n     * since facebook app don't handle {@link android.content.Intent#EXTRA_TEXT}\n     * <p/>\n     * Override {@link IntentShare#text(String)} for the Facebook application.\n     *\n     * @param link link to the content.\n     * @return current {@link IntentShare} for method chaining.\n     */\n    @NonNull\n    public IntentShare facebookBody(@NonNull Uri link) {\n        String scheme = link.getScheme();\n        if (!\"http\".equals(scheme) && !\"https\".equals(scheme)) {\n            throw new IllegalArgumentException(\"Invalid facebook link : un handled scheme : \"\n                    + scheme);\n        } else if (packageWithExtraProvider.contains(IntentShare.FACEBOOK)) {\n            throw new IllegalArgumentException(\"Facebook link can only be set once.\");\n        } else {\n            packageWithExtraProvider.add(IntentShare.FACEBOOK);\n            extraProviders.add(\n                    new ExtraProvider(IntentShare.FACEBOOK)\n                            .overrideText(link.toString())\n                            .disableImage()\n                            .disableSubject()\n            );\n        }\n        return this;\n    }\n\n    /**\n     * Text which will be used as tweet body if target application is the Twitter one.\n     * <p/>\n     * Override {@link IntentShare#text(String)} for the Twitter application.\n     * <p>\n     * Note that length compliancy (140 char) isn't handle by the library anymore since\n     * tweet lenght can't be easily deduced from the text length directly.\n     * <p>\n     * Please refer to the following link if you want to ensure the length check on your side:\n     * https://blog.twitter.com/2016/doing-more-with-140-characters\n     *\n     * @param tweet tweet body.\n     * @return current {@link IntentShare} for method chaining.\n     */\n    @NonNull\n    public IntentShare twitterBody(@NonNull String tweet) {\n        if (packageWithExtraProvider.contains(IntentShare.TWITTER)) {\n            throw new IllegalArgumentException(\"Twitter body can only be set once.\");\n        } else {\n            packageWithExtraProvider.add(IntentShare.TWITTER);\n            extraProviders.add(\n                    new ExtraProvider(TWITTER)\n                            .overrideText(tweet)\n            );\n        }\n        return this;\n    }\n\n    /**\n     * Allow to set a listener to be notified on chosen target activity.\n     * <p/>\n     * Listener will be automatically unregister once a result is delivered.\n     *\n     * @param listener listener to register.\n     * @return current {@link IntentShare} for method chaining.\n     */\n    public IntentShare listener(@NonNull IntentShareListener listener) {\n        this.listener = listener;\n        return this;\n    }\n\n    /**\n     * Allow to add a specific intent for a given\n     *\n     * @param extraProvider extra provider for a given package;\n     * @return current {@link IntentShare} for method chaining.\n     */\n    public IntentShare addExtraProvider(@NonNull ExtraProvider extraProvider) {\n        if (extraProvider == null) {\n            throw new IllegalArgumentException(\"Extra provider can't be null\");\n        } else if (packageWithExtraProvider.contains(extraProvider.packageName)) {\n            throw new IllegalArgumentException(\"Extra provider already provided for the package : \"\n                    + extraProvider.packageName);\n        }\n        extraProviders.add(extraProvider);\n        return this;\n    }\n\n    /**\n     * Deliver the intent to the system.\n     * <p/>\n     * This will lead to the display of every applications that can handle the build intent.\n     * Target activity field will be then filled according to the params.\n     */\n    public void deliver() {\n        if (this.listener != null) {\n            this.listener.register(context);\n        }\n        TargetChooserActivity.start(context, this);\n    }\n\n    /**\n     * Used to provide specific extras for a given package name\n     */\n    public static class ExtraProvider implements Parcelable {\n\n        /**\n         * Parcelable.\n         */\n        public static final Creator<ExtraProvider> CREATOR = new Creator<ExtraProvider>() {\n            @Override\n            public ExtraProvider createFromParcel(Parcel source) {\n                return new ExtraProvider(source);\n            }\n\n            @Override\n            public ExtraProvider[] newArray(int size) {\n                return new ExtraProvider[size];\n            }\n        };\n        /**\n         * Package for which specific extras must be provided.\n         */\n        String packageName;\n\n        /**\n         * Specific text to provide.\n         */\n        String overriddenText;\n\n        /**\n         * Specific mail subject to provide.\n         */\n        String overriddenSubject;\n\n        /**\n         * Specific image to provide.\n         */\n        Uri overriddenImage;\n\n        /**\n         * Used to know if default text must be removed.\n         */\n        boolean textDisabled;\n\n        /**\n         * Used to know if default subject must be removed.\n         */\n        boolean subjectDisabled;\n\n        /**\n         * Used to know if default image must be removed.\n         */\n        boolean imageDisabled;\n\n        /**\n         * Used to provide specific extras for a given package name.\n         * <p/>\n         * By default, every extras are going to be copied from the {@link IntentShare}.\n         * <p/>\n         * To override extras :\n         * {@link ExtraProvider#overrideText(String)}\n         * {@link ExtraProvider#overrideSubject(String)}\n         * {@link ExtraProvider#overrideImage(Uri)}\n         *\n         * @param packageName package for which the extras are going to be applied;\n         */\n        public ExtraProvider(String packageName) {\n            this.packageName = packageName;\n            this.overriddenText = null;\n            this.overriddenSubject = null;\n            this.overriddenImage = null;\n            this.textDisabled = false;\n            this.subjectDisabled = false;\n            this.imageDisabled = false;\n        }\n\n        /**\n         * Used to provide specific extras for a given package name.\n         * <p/>\n         * By default, every extras are going to be copied from the {@link IntentShare}.\n         * <p/>\n         * To override extras :\n         * {@link ExtraProvider#overrideText(String)}\n         * {@link ExtraProvider#overrideSubject(String)}\n         * {@link ExtraProvider#overrideImage(Uri)}\n         *\n         * @param in parcel.\n         */\n        protected ExtraProvider(Parcel in) {\n            this.packageName = in.readString();\n            this.overriddenText = in.readString();\n            this.overriddenSubject = in.readString();\n            this.overriddenImage = in.readParcelable(Uri.class.getClassLoader());\n            this.textDisabled = in.readByte() != 0;\n            this.subjectDisabled = in.readByte() != 0;\n            this.imageDisabled = in.readByte() != 0;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) {\n                return true;\n            }\n            if (o == null || getClass() != o.getClass()) {\n                return false;\n            }\n\n            ExtraProvider that = (ExtraProvider) o;\n\n            if (textDisabled != that.textDisabled) {\n                return false;\n            }\n            if (subjectDisabled != that.subjectDisabled) {\n                return false;\n            }\n            if (imageDisabled != that.imageDisabled) {\n                return false;\n            }\n            if (packageName != null ? !packageName.equals(that.packageName)\n                    : that.packageName != null) {\n                return false;\n            }\n            if (overriddenText != null ? !overriddenText.equals(that.overriddenText)\n                    : that.overriddenText != null) {\n                return false;\n            }\n            if (overriddenSubject != null ? !overriddenSubject.equals(that.overriddenSubject)\n                    : that.overriddenSubject != null) {\n                return false;\n            }\n            return !(overriddenImage != null ? !overriddenImage.equals(that.overriddenImage)\n                    : that.overriddenImage != null);\n\n        }\n\n        @Override\n        public int hashCode() {\n            int result = packageName != null ? packageName.hashCode() : 0;\n            result = 31 * result + (overriddenText != null ? overriddenText.hashCode() : 0);\n            result = 31 * result + (overriddenSubject != null ? overriddenSubject.hashCode() : 0);\n            result = 31 * result + (overriddenImage != null ? overriddenImage.hashCode() : 0);\n            result = 31 * result + (textDisabled ? 1 : 0);\n            result = 31 * result + (subjectDisabled ? 1 : 0);\n            result = 31 * result + (imageDisabled ? 1 : 0);\n            return result;\n        }\n\n        @Override\n        public int describeContents() {\n            return 0;\n        }\n\n        @Override\n        public void writeToParcel(Parcel dest, int flags) {\n            dest.writeString(this.packageName);\n            dest.writeString(this.overriddenText);\n            dest.writeString(this.overriddenSubject);\n            dest.writeParcelable(this.overriddenImage, flags);\n            dest.writeByte(textDisabled ? (byte) 1 : (byte) 0);\n            dest.writeByte(subjectDisabled ? (byte) 1 : (byte) 0);\n            dest.writeByte(imageDisabled ? (byte) 1 : (byte) 0);\n        }\n\n        /**\n         * Provide a specific text for the linked package name.\n         *\n         * @param text text which will be used as {@link android.content.Intent#EXTRA_TEXT}\n         * @return {@link ExtraProvider} for chaining.\n         */\n        public ExtraProvider overrideText(String text) {\n            this.overriddenText = text;\n            return this;\n        }\n\n        /**\n         * Provide a specific subject for the linked package name.\n         *\n         * @param subject subject which will be used as {@link android.content.Intent#EXTRA_SUBJECT}\n         * @return {@link ExtraProvider} for chaining.\n         */\n        public ExtraProvider overrideSubject(String subject) {\n            this.overriddenSubject = subject;\n            return this;\n        }\n\n        /**\n         * Provide a specific image for the linked package name.\n         *\n         * @param image image which will be used as {@link android.content.Intent#EXTRA_STREAM}\n         * @return {@link ExtraProvider} for chaining.\n         */\n        public ExtraProvider overrideImage(Uri image) {\n            this.overriddenImage = image;\n            return this;\n        }\n\n        /**\n         * Disable the extra {@link android.content.Intent#EXTRA_TEXT} for the linked package\n         * to avoid a copy from the default {@link IntentShare} text.\n         *\n         * @return {@link ExtraProvider} for chaining.\n         */\n        public ExtraProvider disableText() {\n            this.textDisabled = true;\n            return this;\n        }\n\n        /**\n         * Disable the extra {@link android.content.Intent#EXTRA_SUBJECT} for the linked package\n         * to avoid a copy from the default {@link IntentShare} subject.\n         *\n         * @return {@link ExtraProvider} for chaining.\n         */\n        public ExtraProvider disableSubject() {\n            this.subjectDisabled = true;\n            return this;\n        }\n\n        /**\n         * Disable the extra {@link android.content.Intent#EXTRA_STREAM} for the linked package\n         * to avoid a copy from the default {@link IntentShare} image.\n         *\n         * @return {@link ExtraProvider} for chaining.\n         */\n        public ExtraProvider disableImage() {\n            this.imageDisabled = true;\n            return this;\n        }\n\n        /**\n         * Get package name of the target activity for which the extra provider has been build.\n         *\n         * @return package name of the target activity for which the extra provider has been build.\n         */\n        public String getPackageName() {\n            return packageName;\n        }\n\n        /**\n         * Retrieve the specific text which is going to override the default one.\n         *\n         * @return the specific text which is going to override the default one.\n         */\n        public String getOverriddenText() {\n            return overriddenText;\n        }\n\n        /**\n         * Retrieve the subject which is going to override the default one.\n         *\n         * @return the subject which is going to override the default one.\n         */\n        public String getOverriddenSubject() {\n            return overriddenSubject;\n        }\n\n        /**\n         * Retrieve the {@link Uri} which is going to override the default one.\n         *\n         * @return the {@link Uri} which is going to override the default one.\n         */\n        public Uri getOverriddenImage() {\n            return overriddenImage;\n        }\n\n        /**\n         * Used to know if the default text must be ignored.\n         *\n         * @return true if the default text must be ignored.\n         */\n        public boolean isTextDisabled() {\n            return textDisabled;\n        }\n\n        /**\n         * Used to know if the default subject must be ignored.\n         *\n         * @return true if the default subject must be ignored.\n         */\n        public boolean isSubjectDisabled() {\n            return subjectDisabled;\n        }\n\n        /**\n         * Used to know if the default image must be ignored.\n         *\n         * @return true if the default image must be ignored.\n         */\n        public boolean isImageDisabled() {\n            return imageDisabled;\n        }\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/fr/tvbarthel/intentshare/IntentShareListener.java",
    "content": "package fr.tvbarthel.intentshare;\n\nimport android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.IntentFilter;\nimport android.support.v4.content.LocalBroadcastManager;\n\n/**\n * Simple listener used to catch which activity the user choose.\n */\npublic abstract class IntentShareListener {\n\n    /**\n     * Action used to inform that the user as complete the sharing.\n     */\n    private static final String ACTION_ON_COMPLETED = \"fr.tvbarthel.intentshare.oncompleted\";\n\n    /**\n     * Action used to inform that the user as cancel the sharing.\n     */\n    private static final String ACTION_ON_CANCELED = \"fr.tvbarthel.intentshare.oncanceled\";\n\n    /**\n     * Bundle key used to pass the package name.\n     */\n    private static final String EXTRA_PACKAGE_NAME = \"fr.tvbarthel.intentshare.package\";\n\n    /**\n     * Internal receiver.\n     */\n    private final InternalReceiver internalReceiver;\n\n    /**\n     * Simple listener used to catch which activity the user chosen.\n     */\n    public IntentShareListener() {\n\n        internalReceiver = new InternalReceiver() {\n            @Override\n            public void onCanceled() {\n                super.onCanceled();\n                IntentShareListener.this.onCanceled();\n            }\n\n            @Override\n            public void onCompleted(String packageName) {\n                super.onCompleted(packageName);\n                IntentShareListener.this.onCompleted(packageName);\n            }\n        };\n    }\n\n    /**\n     * Called when the user chose an activity to complete the sharing.\n     *\n     * @param packageName package name of the selected activity.\n     */\n    public abstract void onCompleted(String packageName);\n\n    /**\n     * Called when the user cancel the sharing without selecting any target activity.\n     */\n    public abstract void onCanceled();\n\n    /**\n     * Notify all registered listener that sharing has been completed.\n     * <p/>\n     * private package.\n     *\n     * @param context     context used to send the broadcast.\n     * @param packageName package name of the selected target activity.\n     */\n    static void notifySharingCompleted(Context context, String packageName) {\n        Intent intent = new Intent(ACTION_ON_COMPLETED);\n        intent.putExtra(EXTRA_PACKAGE_NAME, packageName);\n        LocalBroadcastManager.getInstance(context.getApplicationContext()).sendBroadcast(intent);\n    }\n\n    /**\n     * Notify all registered listener that sharing has been canceled\n     * <p/>\n     * private package.\n     *\n     * @param context context used to send the broadcast.\n     */\n    static void notifySharingCanceled(Context context) {\n        Intent intent = new Intent(ACTION_ON_CANCELED);\n        LocalBroadcastManager.getInstance(context.getApplicationContext()).sendBroadcast(intent);\n    }\n\n    /**\n     * Used to register the internal listener.\n     * <p/>\n     * private package.\n     *\n     * @param context context used to register the listener.\n     */\n    void register(Context context) {\n        IntentFilter filter = new IntentFilter();\n        filter.addAction(ACTION_ON_COMPLETED);\n        filter.addAction(ACTION_ON_CANCELED);\n        LocalBroadcastManager.getInstance(context.getApplicationContext())\n                .registerReceiver(internalReceiver, filter);\n    }\n\n    /**\n     * Receiver used internally to catch event.\n     */\n    private static class InternalReceiver extends BroadcastReceiver {\n\n        @Override\n        public void onReceive(Context context, Intent intent) {\n            switch (intent.getAction()) {\n                case ACTION_ON_COMPLETED:\n                    onCompleted(intent.getStringExtra(EXTRA_PACKAGE_NAME));\n                    break;\n                case ACTION_ON_CANCELED:\n                    onCanceled();\n                    break;\n                default:\n                    throw new IllegalArgumentException(\"Action unknown : \" + intent.getAction());\n            }\n\n            // unregister receiver.\n            LocalBroadcastManager.getInstance(context.getApplicationContext()).unregisterReceiver(this);\n        }\n\n        /**\n         * Called when the user chose an activity to complete the sharing.\n         *\n         * @param packageName package name of the selected activity.\n         */\n        public void onCompleted(String packageName) {\n\n        }\n\n        /**\n         * Called when the user cancel the sharing without selecting any target activity.\n         */\n        public void onCanceled() {\n\n        }\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/fr/tvbarthel/intentshare/LayoutManagerFactory.java",
    "content": "package fr.tvbarthel.intentshare;\n\nimport android.content.Context;\nimport android.os.Build;\nimport android.support.v7.widget.GridLayoutManager;\nimport android.support.v7.widget.LinearLayoutManager;\nimport android.support.v7.widget.RecyclerView;\n\n/**\n * Factory used to handle layout manager according to the device android version seamlessly\n */\nfinal class LayoutManagerFactory {\n\n    private static final int MARSHMALLOW_SPAN_COUNT = 4;\n\n    /**\n     * Non instantiable class.\n     */\n    private LayoutManagerFactory() {\n\n    }\n\n    /**\n     * Build the layout manager for the {@link TargetActivity} list displayed to the user\n     * during the target activity selection.\n     *\n     * @param context context used to instantiate layout manager.\n     * @return layout manager matching the native look and feel linked to the device SDK version.\n     */\n    public static RecyclerView.LayoutManager buildLayoutManager(Context context) {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {\n            GridLayoutManager gridLayoutManager = new GridLayoutManager(context, MARSHMALLOW_SPAN_COUNT);\n            gridLayoutManager.setSpanSizeLookup(new MarshmallowSpanSizeLookup());\n            return gridLayoutManager;\n        } else {\n            return new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false);\n        }\n    }\n\n    /**\n     * SpanSizeLookup used to fit the native look and feel provided by\n     * {@link android.content.Intent#createChooser(android.content.Intent, CharSequence)}\n     */\n    private static final class MarshmallowSpanSizeLookup extends GridLayoutManager.SpanSizeLookup {\n\n        @Override\n        public int getSpanSize(int position) {\n            if (position == 0) {\n                return MARSHMALLOW_SPAN_COUNT; // header taking the full width;\n            } else {\n                return 1;                      // target activity taking one unit;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/fr/tvbarthel/intentshare/StyledAttributesUtils.java",
    "content": "package fr.tvbarthel.intentshare;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.util.TypedValue;\n\n/**\n * Util used to retrieved attributes of the current style.\n */\nfinal class StyledAttributesUtils {\n\n    /**\n     * non instantiable class.\n     */\n    private StyledAttributesUtils() {\n\n    }\n\n    /**\n     * Retrieve the selectable background of the current style.\n     *\n     * @param context context used to retrieve the styled attributes.\n     * @return selectable item background res id.\n     */\n    public static int getSelectableItemBackground(Context context) {\n        int selectableItemBackgroundResId;\n        int[] attrs = new int[]{android.R.attr.selectableItemBackground};\n        TypedValue values = new TypedValue();\n        TypedArray array = context.obtainStyledAttributes(values.data, attrs);\n        selectableItemBackgroundResId = array.getResourceId(0, 0);\n        array.recycle();\n        return selectableItemBackgroundResId;\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/fr/tvbarthel/intentshare/TargetActivity.java",
    "content": "package fr.tvbarthel.intentshare;\n\nimport android.content.Context;\nimport android.content.pm.ResolveInfo;\nimport android.net.Uri;\nimport android.os.Parcel;\n\nimport java.io.File;\nimport java.util.Comparator;\n\n/**\n * Plain java model for a sharing target activity.\n */\npublic class TargetActivity {\n\n    private final int activityLabelResId;\n    private final Uri iconUri;\n    private final boolean isMail;\n    private final long lastSelection;\n    private ResolveInfo resolveInfo;\n    private CharSequence label;\n\n    /**\n     * Plain java model for a sharing target activity.\n     *\n     * @param context       context used to load target activity label.\n     * @param resolveInfo   {@link ResolveInfo} linked to the target activity.\n     * @param lastSelection time stamp in milli of  last selection.\n     */\n    public TargetActivity(Context context, ResolveInfo resolveInfo, long lastSelection) {\n        this.lastSelection = lastSelection;\n        this.resolveInfo = resolveInfo;\n\n        int icon = resolveInfo.activityInfo.icon;\n        if (icon == 0) {\n            icon = resolveInfo.activityInfo.applicationInfo.icon;\n        }\n        this.iconUri = Uri.parse(\n                \"android.resource://\"\n                        + resolveInfo.activityInfo.applicationInfo.packageName\n                        + File.separator\n                        + icon\n        );\n\n        this.activityLabelResId = resolveInfo.labelRes;\n        this.isMail = resolveInfo.filter.hasDataType(\"message/rfc822\");\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        TargetActivity that = (TargetActivity) o;\n        return resolveInfo.equals(that.resolveInfo);\n\n    }\n\n    @Override\n    public int hashCode() {\n        int result = activityLabelResId;\n        result = 31 * result + resolveInfo.hashCode();\n        return result;\n    }\n\n    /**\n     * Retrieve a unique id used to identify target activity.\n     *\n     * @return unique id used to identify target activity.\n     */\n    public String getId() {\n        return this.resolveInfo.activityInfo.packageName\n                + this.resolveInfo.activityInfo.name;\n    }\n\n    /**\n     * Retrieve the package name of the target activity.\n     *\n     * @return package name.\n     */\n    public String getPackageName() {\n        return resolveInfo.activityInfo.packageName;\n    }\n\n    /**\n     * Retrive the name of the target activity.\n     *\n     * @return activity name.\n     */\n    public String getActivityName() {\n        return resolveInfo.activityInfo.name;\n    }\n\n    /**\n     * Retrieve the textual label res id of the Activity.\n     *\n     * @return textual label res id of the Activity.\n     */\n    public int getActivityLabelResId() {\n        return activityLabelResId;\n    }\n\n    /**\n     * Retrieve the Uri used to access to the target application launcher icon.\n     *\n     * @return uri linking to the application launcher icon.\n     */\n    public Uri getIconUri() {\n        return iconUri;\n    }\n\n    /**\n     * Used to know if the target activity is a mail client.\n     * <p/>\n     * Basically, any activity which can handle type 'message/rfc_822'.\n     *\n     * @return true if the target activity is a mail client, false otherwise.\n     */\n    public boolean isMailClient() {\n        return this.isMail;\n    }\n\n    /**\n     * Return a timestamp of the last selection inside the sharing dialog from you application.\n     *\n     * @return timestamp of the last selection in milliseconds since January 1, 1970 00:00:00.0 UTC\n     * or 0 if the target activity has never been selected by the user.\n     */\n    public long getLastSelection() {\n        return lastSelection;\n    }\n\n    /**\n     * Retrieve the label of the target activity.\n     *\n     * @return return target activity label or null if not yet loaded.\n     */\n    CharSequence getLabel() {\n        return label;\n    }\n\n    /**\n     * Resolve info linked to the target activity.\n     *\n     * @return Resolve info linked to the target activity.\n     */\n    ResolveInfo getResolveInfo() {\n        return resolveInfo;\n    }\n\n    /**\n     * Label of the target activity.\n     *\n     * @param label label of the target activity.\n     */\n    void setLabel(CharSequence label) {\n        this.label = label;\n    }\n\n    /**\n     * Comparator used to sort {@link TargetActivity} based on the recency of their previous\n     * selection and their default order as fallback when they have never been selected.\n     * <p/>\n     * The ordering imposed by this comparator on a set of {@link TargetActivity}\n     * is not consistent with equals since c.compare(e1, e2)==0 has not the same boolean\n     * value as e1.equals(e2).\n     */\n    public static final class RecencyComparatorProvider implements TargetActivityComparatorProvider {\n\n        /**\n         * Parcelable.\n         */\n        public static final Creator<RecencyComparatorProvider> CREATOR = new Creator<RecencyComparatorProvider>() {\n            @Override\n            public RecencyComparatorProvider createFromParcel(Parcel source) {\n                return new RecencyComparatorProvider(source);\n            }\n\n            @Override\n            public RecencyComparatorProvider[] newArray(int size) {\n                return new RecencyComparatorProvider[size];\n            }\n        };\n\n        /**\n         * Comparator used to sort {@link TargetActivity} based on the recency of their previous\n         * selection and their default order as fallback when they have never been selected.\n         * <p/>\n         * The ordering imposed by this comparator on a set of {@link TargetActivity}\n         * is not consistent with equals since c.compare(e1, e2)==0 has not the same boolean\n         * value as e1.equals(e2).\n         */\n        public RecencyComparatorProvider() {\n\n        }\n\n        /**\n         * Comparator used to sort {@link TargetActivity} based on the recency of their previous\n         * selection and their default order as fallback when they have never been selected.\n         * <p/>\n         * The ordering imposed by this comparator on a set of {@link TargetActivity}\n         * is not consistent with equals since c.compare(e1, e2)==0 has not the same boolean\n         * value as e1.equals(e2).\n         *\n         * @param in parcel.\n         */\n        protected RecencyComparatorProvider(Parcel in) {\n\n        }\n\n\n        @Override\n        public Comparator<TargetActivity> provideComparator() {\n            return new Comparator<TargetActivity>() {\n                @Override\n                public int compare(TargetActivity lhs, TargetActivity rhs) {\n                    float lhsScore = lhs.lastSelection;\n                    float rhsScore = rhs.lastSelection;\n\n                    if (lhsScore > 0 && rhsScore > 0) {\n                        return (int) (rhsScore - lhsScore);\n                    } else if (lhsScore > 0) {\n                        return -1;\n                    } else if (rhsScore > 0) {\n                        return 1;\n                    } else {\n                        return 0;\n                    }\n                }\n            };\n        }\n\n        @Override\n        public int describeContents() {\n            return 0;\n        }\n\n        @Override\n        public void writeToParcel(Parcel dest, int flags) {\n\n        }\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/fr/tvbarthel/intentshare/TargetActivityAdapter.java",
    "content": "package fr.tvbarthel.intentshare;\n\nimport android.content.Context;\nimport android.support.v7.widget.RecyclerView;\nimport android.view.ViewGroup;\n\nimport java.util.List;\n\n/**\n * Used to adapt {@link TargetActivityView} inside a list.\n */\nclass TargetActivityAdapter extends RecyclerView.Adapter<TargetActivityAdapter.ViewHolder> {\n\n    /**\n     * View types.\n     */\n    private static final int VIEW_TYPE_HEADER = 0x00000001;\n    private static final int VIEW_TYPE_RAW = 0x00000002;\n\n    private final String label;\n    private final IconLoader iconLoader;\n\n    /**\n     * Target activity info adapted.\n     */\n    private List<TargetActivity> targetActivities;\n\n    /**\n     * Internal listener used to catch the events from the {@link TargetActivityView} adapted.\n     */\n    private TargetActivityView.Listener internalTargetActivityViewListener;\n\n    /**\n     * Listener used to catch adapted views events.\n     */\n    private Listener listener;\n\n    /**\n     * Used to adapt {@link TargetActivityView} inside a list.\n     *\n     * @param targetActivities list of target activities.\n     * @param label            label to display as an header of the list.\n     * @param iconLoader       loader used to load {@link TargetActivity} icon.\n     */\n    public TargetActivityAdapter(final List<TargetActivity> targetActivities,\n                                 String label,\n                                 IconLoader iconLoader) {\n        this.targetActivities = targetActivities;\n        this.label = label;\n        internalTargetActivityViewListener = new TargetActivityView.Listener() {\n            @Override\n            public void onTargetActivitySelected(TargetActivity targetActivity) {\n                if (listener != null) {\n                    listener.onTargetActivitySelected(targetActivity);\n                }\n            }\n        };\n        this.iconLoader = iconLoader;\n    }\n\n    @Override\n    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {\n        RecyclerView.LayoutParams layoutParams = new RecyclerView.LayoutParams(\n                ViewGroup.LayoutParams.MATCH_PARENT,\n                ViewGroup.LayoutParams.MATCH_PARENT\n        );\n        Context context = parent.getContext();\n        switch (viewType) {\n            case VIEW_TYPE_HEADER:\n                TargetActivityHeaderView headerView\n                        = new TargetActivityHeaderView(context);\n                headerView.setLayoutParams(layoutParams);\n                int extraPadding = context.getResources()\n                        .getDimensionPixelSize(R.dimen.isl_target_activity_header_extra_padding);\n                headerView.setPadding(\n                        headerView.getPaddingLeft() + extraPadding,\n                        headerView.getPaddingTop(),\n                        headerView.getRight() + extraPadding,\n                        headerView.getPaddingBottom()\n                );\n                return new ViewHolder(headerView);\n            case VIEW_TYPE_RAW:\n                TargetActivityView targetActivityView\n                        = new TargetActivityView(context, iconLoader);\n                targetActivityView.setLayoutParams(layoutParams);\n                targetActivityView.setListener(internalTargetActivityViewListener);\n                return new ViewHolder(targetActivityView);\n            default:\n                throw new IllegalStateException(\"Can't create view \"\n                        + \"holder for the given view type : \" + viewType);\n        }\n    }\n\n    @Override\n    public void onBindViewHolder(ViewHolder holder, int position) {\n        switch (holder.getItemViewType()) {\n            case VIEW_TYPE_HEADER:\n                ((TargetActivityHeaderView) holder.itemView).setModel(label);\n                break;\n            case VIEW_TYPE_RAW:\n                // -1 for the header.\n                TargetActivityView targetActivityView = (TargetActivityView) holder.itemView;\n                targetActivityView.setModel(targetActivities.get(position - 1));\n                targetActivityView.loadIcon();\n                break;\n            default:\n                throw new IllegalStateException(\"Can't bind view \"\n                        + \"holder for view type : \" + holder.getItemViewType());\n        }\n    }\n\n    @Override\n    public void onViewRecycled(ViewHolder holder) {\n        super.onViewRecycled(holder);\n        if (holder.itemView instanceof TargetActivityView) {\n            ((TargetActivityView) holder.itemView).cancelIconLoading();\n        }\n    }\n\n    @Override\n    public int getItemCount() {\n        // +1 for the header\n        return targetActivities.size() + 1;\n    }\n\n    @Override\n    public int getItemViewType(int position) {\n        if (position == 0) {\n            return VIEW_TYPE_HEADER;\n        } else {\n            return VIEW_TYPE_RAW;\n        }\n    }\n\n    /**\n     * Listener used to catch events from the adapted views.\n     *\n     * @param listener listener to register.\n     */\n    public void setListener(Listener listener) {\n        this.listener = listener;\n    }\n\n    /**\n     * Used to notify that a target activity changed.\n     *\n     * @param targetActivity target activity which have changed.\n     */\n    public void notifyTargetActivityChanged(TargetActivity targetActivity) {\n        int in = targetActivities.indexOf(targetActivity);\n        if (in != -1) {\n            notifyItemChanged(in + 1); // header\n        }\n    }\n\n    /**\n     * View holder pattern.\n     */\n    public class ViewHolder extends RecyclerView.ViewHolder {\n\n        /**\n         * View holder.\n         *\n         * @param itemView {@link TargetActivityView}\n         */\n        public ViewHolder(TargetActivityView itemView) {\n            super(itemView);\n        }\n\n        /**\n         * View holder.\n         *\n         * @param headerView {@link TargetActivityHeaderView}\n         */\n        public ViewHolder(TargetActivityHeaderView headerView) {\n            super(headerView);\n        }\n    }\n\n    /**\n     * Listener used to catch events from adapted views.\n     */\n    public interface Listener {\n        /**\n         * Called when the user has chosen a target activity for the initial share intent.\n         *\n         * @param targetActivity chosen target activity.\n         */\n        void onTargetActivitySelected(TargetActivity targetActivity);\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/fr/tvbarthel/intentshare/TargetActivityComparatorProvider.java",
    "content": "package fr.tvbarthel.intentshare;\n\nimport android.os.Parcelable;\n\nimport java.util.Comparator;\n\n/**\n * ˙Interface which allow to define which comparator will be provided for sorting the\n * target activity inside the {@link TargetChooserActivity}.\n */\npublic interface TargetActivityComparatorProvider extends Parcelable {\n\n    /**\n     * Provide the comparator used to sort {@link TargetActivity} displayed to the user.\n     *\n     * @return comparator used to sort {@link TargetActivity} displayed to the user.\n     */\n    Comparator<TargetActivity> provideComparator();\n}\n"
  },
  {
    "path": "library/src/main/java/fr/tvbarthel/intentshare/TargetActivityHeaderView.java",
    "content": "package fr.tvbarthel.intentshare;\n\nimport android.content.Context;\nimport android.content.res.Resources;\nimport android.support.v4.content.ContextCompat;\nimport android.text.TextUtils;\nimport android.util.AttributeSet;\nimport android.util.TypedValue;\nimport android.widget.TextView;\n\n/**\n * Simple view used to display the label above the target activity list.\n */\nclass TargetActivityHeaderView extends TextView {\n\n    /**\n     * view height\n     */\n    private int height;\n\n    /**\n     * Simple view used to display the label above the target activity list.\n     *\n     * @param context holding context.\n     */\n    public TargetActivityHeaderView(Context context) {\n        this(context, null);\n    }\n\n    /**\n     * Simple view used to display the label above the target activity list.\n     *\n     * @param context holding context.\n     * @param attrs   attr from xml.\n     */\n    public TargetActivityHeaderView(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    /**\n     * Simple view used to display the label above the target activity list.\n     *\n     * @param context      holding context.\n     * @param attrs        attr from xml.\n     * @param defStyleAttr style.\n     */\n    public TargetActivityHeaderView(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        if (!isInEditMode()) {\n            initialize(context);\n        }\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));\n    }\n\n    /**\n     * Set the label which going to be displayed inside the header.\n     *\n     * @param label label to display inside the header.\n     */\n    public void setModel(String label) {\n        setText(label);\n    }\n\n    /**\n     * Initialize internal component\n     *\n     * @param context holding context.\n     */\n    private void initialize(Context context) {\n        setBackgroundColor(\n                ContextCompat.getColor(\n                        context,\n                        R.color.isl_target_activity_header_view_background\n                )\n        );\n        Resources resources = context.getResources();\n        height = resources.getDimensionPixelSize(R.dimen.isl_target_activity_header_view_height);\n        setTextSize(\n                TypedValue.COMPLEX_UNIT_PX,\n                resources.getDimensionPixelSize(R.dimen.isl_target_activity_header_view_font_size)\n        );\n        setTextColor(\n                ContextCompat.getColor(\n                        context,\n                        R.color.isl_target_activity_header_view_text_color\n                )\n        );\n        setSingleLine(true);\n        setEllipsize(TextUtils.TruncateAt.END);\n        int padding = resources.getDimensionPixelSize(R.dimen.isl_default_padding);\n        setPadding(getPaddingLeft(), padding, getPaddingRight(), padding);\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/fr/tvbarthel/intentshare/TargetActivityManager.java",
    "content": "package fr.tvbarthel.intentshare;\n\nimport android.content.ComponentName;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.IntentFilter;\nimport android.content.SharedPreferences;\nimport android.content.pm.PackageManager;\nimport android.content.pm.ResolveInfo;\nimport android.net.Uri;\nimport android.os.AsyncTask;\nimport android.support.annotation.NonNull;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.List;\n\n/**\n * Manager used to handle all logic linked to {@link TargetActivity}\n */\nclass TargetActivityManager {\n\n    /**\n     * Shared preferences key used to store chosen activities.\n     */\n    private static final String SHARED_PREF_KEY = \"shared_pref_target_activities\";\n\n    /**\n     * Pattern for last selection key.\n     * string 1 : package name\n     * string 2 : activity name\n     */\n    private static final String KEY_LAST_SELECTION = \"shared_pref_last_selection_$1%s_$2%s\";\n\n    /**\n     * List of target activities.\n     */\n    private ArrayList<TargetActivity> targetActivities;\n\n    /**\n     * Shared preferences used to store target activities scores.\n     */\n    private SharedPreferences sharedPreferences;\n\n    /**\n     * Manager used to handle all logic linked to {@link TargetActivity}\n     */\n    public TargetActivityManager() {\n        targetActivities = new ArrayList<>();\n    }\n\n    /**\n     * Resolve the list of {@link android.app.Activity} which can be targeted for sharing content.\n     * <p/>\n     * Basically, resolve the list of {@link android.app.Activity} which can handled\n     * {@link Intent#ACTION_SEND}.\n     *\n     * @param context    context used to resolves target activities.\n     * @param listener   listener used to catch resolving events.\n     * @param comparator comparator used to sort the resolved target activities.\n     */\n    public void resolveTargetActivities(Context context, ResolveListener listener,\n                                        Comparator<TargetActivity> comparator) {\n        targetActivities.clear();\n\n        sharedPreferences = context.getSharedPreferences(SHARED_PREF_KEY, Context.MODE_PRIVATE);\n\n        PackageManager packageManager = context.getPackageManager();\n\n        Intent intentShare = new Intent(Intent.ACTION_SEND);\n        intentShare.putExtra(Intent.EXTRA_TEXT, \"queryText\");\n        intentShare.setType(\"text/plain\");\n        List<ResolveInfo> shareActivities = packageManager.queryIntentActivities(\n                intentShare,\n                PackageManager.GET_RESOLVED_FILTER\n        );\n\n        for (int i = 0; i < shareActivities.size(); i++) {\n            ResolveInfo targetActivityInfo = shareActivities.get(i);\n            IntentFilter filter = targetActivityInfo.filter;\n            if (filter.hasDataType(\"text/plain\")) {\n\n                String lastSelectionKey = getLastSelectionKey(\n                        targetActivityInfo.activityInfo.packageName,\n                        targetActivityInfo.activityInfo.name\n                );\n\n                long lastSelection = sharedPreferences.getLong(lastSelectionKey, 0);\n\n                TargetActivity targetActivity\n                        = new TargetActivity(context, targetActivityInfo, lastSelection);\n                targetActivities.add(targetActivity);\n            }\n        }\n\n        Collections.sort(targetActivities, comparator);\n\n        for (int i = 0; i < targetActivities.size(); i++) {\n            new AsyncLabelLoader(context, targetActivities.get(i), listener).execute();\n        }\n\n        listener.onTargetActivitiesResolved(targetActivities);\n    }\n\n    private String getLastSelectionKey(String packageName, String activityName) {\n        return String.format(KEY_LAST_SELECTION, packageName, activityName);\n    }\n\n    /**\n     * Start a target activity with well field params according to the given {@link IntentShare}\n     *\n     * @param context        context used to start the activity.\n     * @param targetActivity target activity to start.\n     * @param intentShare    data which should be send to the target activity.\n     */\n    public void startTargetActivity(Context context, TargetActivity targetActivity, IntentShare intentShare) {\n        context.startActivity(\n                buildTargetActivityIntent(\n                        targetActivity,\n                        intentShare\n                )\n        );\n\n        sharedPreferences\n                .edit()\n                .putLong(getLastSelectionKey(\n                                targetActivity.getPackageName(),\n                                targetActivity.getActivityName()\n                        ),\n                        System.currentTimeMillis()\n                )\n                .apply();\n\n    }\n\n    /**\n     * Build the intent with {@link Intent#ACTION_SEND} action used to start the target activity\n     * with well field params according to the given {@link IntentShare}.\n     *\n     * @param targetActivity target activity which should be start.\n     * @param intentShare    shared content used to field the intent params.\n     * @return {@link Intent#ACTION_SEND} field to start the target activity.\n     */\n    private Intent buildTargetActivityIntent(TargetActivity targetActivity, IntentShare intentShare) {\n        String packageName = targetActivity.getPackageName();\n        String activityName = targetActivity.getActivityName();\n        ComponentName componentName = new ComponentName(\n                packageName,\n                activityName\n        );\n        Intent intent = new Intent(Intent.ACTION_SEND);\n        intent.setType(\"text/plain\");\n        if (targetActivity.isMailClient()) { // mail target\n            intent.putExtra(Intent.EXTRA_TEXT, intentShare.mailBody);\n            intent.putExtra(Intent.EXTRA_SUBJECT, intentShare.mailSubject);\n            addImageExtras(intent, intentShare.imageUri);\n        } else { // other target\n            intent.putExtra(Intent.EXTRA_TEXT, intentShare.text);\n            addImageExtras(intent, intentShare.imageUri);\n        }\n        applyExtraProvider(intent, packageName, intentShare.extraProviders);\n        intent.setComponent(componentName);\n        return intent;\n    }\n\n    /**\n     * Apply the extra provider to the current intent if one is associated to the targeted package.\n     *\n     * @param intent            intent send.\n     * @param targetPackageName targeted package.\n     * @param extraProviders    list of extra providers.\n     */\n    private void applyExtraProvider(\n            Intent intent,\n            String targetPackageName,\n            ArrayList<IntentShare.ExtraProvider> extraProviders) {\n\n        IntentShare.ExtraProvider extraProvider = null;\n        for (int i = 0; i < extraProviders.size(); i++) {\n            IntentShare.ExtraProvider provider = extraProviders.get(i);\n            if (provider.packageName.equals(targetPackageName)) {\n                extraProvider = provider;\n                break;\n            }\n        }\n\n        if (extraProvider != null) {\n            if (extraProvider.textDisabled) {\n                intent.removeExtra(Intent.EXTRA_TEXT);\n            } else if (extraProvider.overriddenText != null) {\n                intent.putExtra(Intent.EXTRA_TEXT, extraProvider.overriddenText);\n            }\n            if (extraProvider.subjectDisabled) {\n                intent.removeExtra(Intent.EXTRA_SUBJECT);\n            } else if (extraProvider.overriddenSubject != null) {\n                intent.putExtra(Intent.EXTRA_SUBJECT, extraProvider.overriddenSubject);\n            }\n            if (extraProvider.imageDisabled) {\n                intent.removeExtra(Intent.EXTRA_STREAM);\n                intent.setType(\"text/plain\");\n            } else if (extraProvider.overriddenImage != null) {\n                intent.putExtra(Intent.EXTRA_STREAM, extraProvider.overriddenImage);\n            }\n        }\n    }\n\n    private void addImageExtras(Intent intent, Uri imageUri) {\n        if (imageUri != null) {\n            intent.putExtra(Intent.EXTRA_STREAM, imageUri);\n            intent.setType(\"image/jpeg\");\n            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);\n        }\n    }\n\n    /**\n     * Listener used to catch resolve events.\n     */\n    public interface ResolveListener {\n\n        /**\n         * Called when the target activities has been resolved.\n         * <p/>\n         * Note that, since resolving target activities name can take a little more time,\n         * {@link ResolveListener#onLabelResolved(TargetActivity)}\n         * will be called once a label has been successfully loaded.\n         *\n         * @param targetActivities list of resolved target activities.\n         */\n        void onTargetActivitiesResolved(@NonNull ArrayList<TargetActivity> targetActivities);\n\n        /**\n         * Called when the label of a target activity has been resolved.\n         *\n         * @param targetActivity target for which the label has been resolved.\n         */\n        void onLabelResolved(@NonNull TargetActivity targetActivity);\n\n    }\n\n    /**\n     * Async task used to avoid loading the target activity label on the ui thread.\n     */\n    private static final class AsyncLabelLoader extends AsyncTask<Void, Void, CharSequence> {\n\n        private final PackageManager packageManager;\n        private final TargetActivity targetActivity;\n        private final ResolveListener listener;\n\n        /**\n         * Async task used to avoid loading the target activity label on the ui thread.\n         *\n         * @param context        context used to access to the package manager.\n         * @param targetActivity target activity for which the label should be loaded.\n         * @param listener       to notify once the label has been loaded.\n         */\n        public AsyncLabelLoader(\n                @NonNull Context context,\n                @NonNull TargetActivity targetActivity,\n                @NonNull ResolveListener listener) {\n            packageManager = context.getPackageManager();\n            this.targetActivity = targetActivity;\n            this.listener = listener;\n        }\n\n        @Override\n        protected CharSequence doInBackground(Void... params) {\n            return targetActivity.getResolveInfo().loadLabel(packageManager);\n        }\n\n        @Override\n        protected void onPostExecute(CharSequence s) {\n            super.onPostExecute(s);\n            targetActivity.setLabel(s);\n            listener.onLabelResolved(targetActivity);\n        }\n    }\n\n}\n"
  },
  {
    "path": "library/src/main/java/fr/tvbarthel/intentshare/TargetActivityView.java",
    "content": "package fr.tvbarthel.intentshare;\n\nimport android.content.Context;\nimport android.content.res.Resources;\nimport android.support.v4.content.ContextCompat;\nimport android.util.AttributeSet;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.widget.FrameLayout;\nimport android.widget.ImageView;\nimport android.widget.TextView;\n\n/**\n * Simple view used to display a {@link TargetActivity}.\n */\nclass TargetActivityView extends FrameLayout {\n\n    private ImageView icon;\n    private TextView label;\n    private TargetActivity model;\n    private OnClickListener mInternalClickListener;\n    private Listener listener;\n    private int height;\n    private IconLoader asyncIconLoader;\n\n    /**\n     * Simple view used to display a {@link TargetActivity}.\n     *\n     * @param context         holding context.\n     * @param asyncIconLoader loader used to load {@link TargetActivity} icon.\n     */\n    public TargetActivityView(Context context, IconLoader asyncIconLoader) {\n        super(context);\n        if (!isInEditMode()) {\n            initialize(context);\n        }\n        this.asyncIconLoader = asyncIconLoader;\n    }\n\n    /**\n     * Simple view used to display a {@link TargetActivity}.\n     *\n     * @param context holding context.\n     * @param attrs   attr from xml.\n     */\n    public TargetActivityView(Context context, AttributeSet attrs) {\n        super(context, attrs);\n        if (!isInEditMode()) {\n            initialize(context);\n        }\n    }\n\n    /**\n     * Simple view used to display a {@link TargetActivity}.\n     *\n     * @param context      holding context.\n     * @param attrs        attr from xml.\n     * @param defStyleAttr style.\n     */\n    public TargetActivityView(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        if (!isInEditMode()) {\n            initialize(context);\n        }\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));\n    }\n\n    /**\n     * Set the view model.\n     *\n     * @param model view model.\n     */\n    public void setModel(TargetActivity model) {\n        this.model = model;\n        label.setText(model.getLabel());\n    }\n\n    /**\n     * Set a listener used to catch view events.\n     *\n     * @param listener listener to register.\n     */\n    public void setListener(Listener listener) {\n        this.listener = listener;\n    }\n\n    /**\n     * Load the target activity icon.\n     */\n    public void loadIcon() {\n        icon.setImageDrawable(null);\n        asyncIconLoader.load(model.getIconUri(), icon);\n    }\n\n    /**\n     * Cancel the loading of the target activity icon.\n     */\n    public void cancelIconLoading() {\n        asyncIconLoader.cancel(icon);\n    }\n\n    /**\n     * Initialize internal component.\n     *\n     * @param context holding context.\n     */\n    private void initialize(Context context) {\n        LayoutInflater.from(context).inflate(R.layout.isl_target_activity_view, this);\n\n        Resources resources = context.getResources();\n\n        height = resources.getDimensionPixelSize(R.dimen.isl_target_activity_view_height);\n\n        int paddingVertical = resources.getDimensionPixelSize(R.dimen.isl_target_activity_padding_vertical);\n        int paddingHorizontal = resources.getDimensionPixelSize(R.dimen.isl_target_activity_padding_horizontal);\n        setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical);\n\n        setForeground(\n                ContextCompat.getDrawable(\n                        context,\n                        StyledAttributesUtils.getSelectableItemBackground(context)\n                )\n        );\n\n        icon = ((ImageView) findViewById(R.id.target_activity_view_icon));\n        label = ((TextView) findViewById(R.id.target_activity_view_label));\n\n        mInternalClickListener = new OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                if (listener != null) {\n                    listener.onTargetActivitySelected(model);\n                }\n            }\n        };\n        setOnClickListener(mInternalClickListener);\n\n    }\n\n    /**\n     * Listener used to catch view events.\n     */\n    public interface Listener {\n\n        /**\n         * Called when the user has chosen a target activity for his share intent.\n         *\n         * @param targetActivity chosen target activity.\n         */\n        void onTargetActivitySelected(TargetActivity targetActivity);\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/fr/tvbarthel/intentshare/TargetChooserActivity.java",
    "content": "package fr.tvbarthel.intentshare;\n\nimport android.animation.Animator;\nimport android.animation.AnimatorListenerAdapter;\nimport android.app.Activity;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.res.Resources;\nimport android.os.Bundle;\nimport android.support.annotation.NonNull;\nimport android.support.v7.app.AppCompatActivity;\nimport android.support.v7.widget.RecyclerView;\nimport android.view.View;\nimport android.view.ViewTreeObserver;\nimport android.view.animation.AccelerateInterpolator;\nimport android.view.animation.DecelerateInterpolator;\nimport android.view.animation.Interpolator;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Simple activity used to allow the user to choose a target activity for the sharing intent.\n */\npublic class TargetChooserActivity extends AppCompatActivity\n        implements TargetActivityAdapter.Listener, View.OnClickListener, TargetActivityManager.ResolveListener {\n\n    /**\n     * Extra key used to pass param to the activity.\n     */\n    private static final String EXTRA_INTENT_SHARE = \"tca_extra_intent_share\";\n\n    /**\n     * Key used to save the current scroll during rotation.\n     */\n    private static final String SAVED_CURRENT_SCROLL_Y = \"tca_saved_instance_key_current_scroll\";\n\n    /**\n     * Recycler view used to display the list of target application.\n     */\n    private RecyclerView recyclerView;\n\n    /**\n     * Padding top applied to the recycler view.\n     */\n    private int recyclerPaddingTop;\n\n    /**\n     * Adapter used to display target activity inside a list.\n     */\n    private TargetActivityAdapter adapter;\n\n    /**\n     * Values to share retrieved from intent extras.\n     */\n    private TargetActivityManager targetActivityManager;\n\n    /**\n     * Date which must be shared.\n     */\n    private IntentShare intentShare;\n\n    /**\n     * Height in of a {@link TargetActivityView}\n     */\n    private int targetActivityViewHeight;\n\n    /**\n     * Target activity selected by the user.\n     */\n    private TargetActivity selectedTargetActivity;\n\n    /**\n     * Used to know if listener has been notified.\n     */\n    private boolean listenerNotified;\n\n    /**\n     * Sticky header view displayed to keep an eye on the contextual action when the\n     * header inside the list is hidden.\n     */\n    private TargetActivityHeaderView stickyTitle;\n\n    /**\n     * Sticky header shadow.\n     */\n    private View stickyShadow;\n\n    /**\n     * Boolean used to know if the sticky header is displayed.\n     */\n    private boolean isStickyTitleDisplayed;\n\n    /**\n     * Used to keep current recycler scroll y up to date.\n     */\n    private int currentRecyclerScrollY;\n\n    /**\n     * Root view of the activity\n     */\n    private View rootView;\n\n    /**\n     * List of sharing target activity.\n     */\n    private List<TargetActivity> targetActivities;\n\n    /**\n     * Duration in milli.\n     */\n    private long animationDuration;\n\n    /**\n     * Interpolator for element which enter the screen.\n     */\n    private Interpolator inInterpolator;\n\n    /**\n     * Interpolator for element which leave the screen.\n     */\n    private Interpolator outInterpolator;\n\n    /**\n     * View used as background since recycler view padding can't allow to used\n     * recycler background directly.\n     */\n    private View background;\n\n    /**\n     * Used to know if the activity state has been restored after a saved instance.\n     */\n    private boolean stateRestored;\n\n    /**\n     * Simple activity used to allow the user to choose a target activity for the sharing intent.\n     *\n     * @param context     context used to start the activity.\n     * @param intentShare data to share\n     */\n    public static void start(Context context, IntentShare intentShare) {\n        Intent intent = new Intent(context, TargetChooserActivity.class);\n        intent.putExtra(EXTRA_INTENT_SHARE, intentShare);\n        context.startActivity(intent);\n\n        if (context instanceof Activity) {\n            ((Activity) context).overridePendingTransition(-1, -1);\n        }\n    }\n\n    @Override\n    public void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n\n        Bundle extras = getIntent().getExtras();\n        if (extras == null || !extras.containsKey(EXTRA_INTENT_SHARE)) {\n            throw new IllegalArgumentException(\"Fail to start activity due to missing mandatory extras.\"\n                    + \"Use start activity pattern.\");\n        }\n        intentShare = extras.getParcelable(EXTRA_INTENT_SHARE);\n\n        setContentView(R.layout.isl_activity_target_chooser);\n        rootView = findViewById(R.id.activity_target_chooser_root_view);\n        recyclerView = ((RecyclerView) findViewById(R.id.activity_target_chooser_recycler_list));\n        stickyTitle = ((TargetActivityHeaderView) findViewById(R.id.activity_chooser_sticky_title));\n        stickyShadow = findViewById(R.id.activity_chooser_sticky_title_shadow);\n        background = findViewById(R.id.activity_target_chooser_background);\n\n        targetActivities = new ArrayList<>();\n        selectedTargetActivity = null;\n        listenerNotified = false;\n\n        Resources resources = getResources();\n        animationDuration = resources.getInteger(android.R.integer.config_mediumAnimTime);\n\n        rootView.setOnClickListener(this);\n        rootView.setAlpha(0f);\n\n        stateRestored = savedInstanceState != null;\n        setUpRecyclerView(savedInstanceState);\n        setUpStickyTitle();\n\n        targetActivityManager = new TargetActivityManager();\n        targetActivityManager.resolveTargetActivities(this, this, intentShare.comparatorProvider.provideComparator());\n\n        inInterpolator = new DecelerateInterpolator();\n        outInterpolator = new AccelerateInterpolator();\n    }\n\n    @Override\n    public void onBackPressed() {\n        finishAnimated();\n    }\n\n    @Override\n    protected void onSaveInstanceState(Bundle outState) {\n        super.onSaveInstanceState(outState);\n        outState.putInt(SAVED_CURRENT_SCROLL_Y, currentRecyclerScrollY);\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        if (!listenerNotified && !isChangingConfigurations()) {\n            IntentShareListener.notifySharingCanceled(this);\n        }\n    }\n\n    @Override\n    public void finish() {\n        super.finish();\n        if (selectedTargetActivity != null) {\n            IntentShareListener.notifySharingCompleted(this, selectedTargetActivity.getPackageName());\n        } else if (!isChangingConfigurations()) {\n            IntentShareListener.notifySharingCanceled(this);\n        }\n        listenerNotified = true;\n    }\n\n    @Override\n    public void onClick(View v) {\n        finishAnimated();\n    }\n\n    @Override\n    public void onTargetActivitiesResolved(@NonNull ArrayList<TargetActivity> targetActivities) {\n        this.targetActivities.addAll(targetActivities);\n        adapter.notifyDataSetChanged();\n    }\n\n    @Override\n    public void onTargetActivitySelected(@NonNull TargetActivity targetActivity) {\n        selectedTargetActivity = targetActivity;\n        targetActivityManager.startTargetActivity(this, targetActivity, intentShare);\n        finish();\n    }\n\n    @Override\n    public void onLabelResolved(TargetActivity targetActivity) {\n        adapter.notifyTargetActivityChanged(targetActivity);\n    }\n\n\n    private void setUpRecyclerView(Bundle savedInstance) {\n        recyclerView.setLayoutManager(LayoutManagerFactory.buildLayoutManager(this));\n        targetActivities = new ArrayList<>();\n        adapter = new TargetActivityAdapter(\n                targetActivities,\n                intentShare.chooserTitle,\n                intentShare.iconLoader\n        );\n        adapter.setListener(this);\n\n        targetActivityViewHeight = getResources().getDimensionPixelSize(R.dimen.isl_target_activity_view_height);\n\n        if (savedInstance != null) {\n            currentRecyclerScrollY = savedInstance.getInt(SAVED_CURRENT_SCROLL_Y, 0);\n        } else {\n            currentRecyclerScrollY = 0;\n        }\n\n        recyclerView.getViewTreeObserver().addOnPreDrawListener(\n                new ViewTreeObserver.OnPreDrawListener() {\n\n                    @Override\n                    public boolean onPreDraw() {\n                        recyclerView.getViewTreeObserver().removeOnPreDrawListener(this);\n                        int totalHeight = adapter.getItemCount() * targetActivityViewHeight;\n                        int maxStartingHeight = (int) (recyclerView.getHeight() / 2.5f);\n                        int startingHeight = Math.min(totalHeight, maxStartingHeight);\n                        recyclerPaddingTop = recyclerView.getHeight() - startingHeight;\n                        recyclerView.setPadding(recyclerView.getPaddingLeft(), recyclerPaddingTop,\n                                recyclerView.getPaddingRight(), 0);\n                        recyclerView.setTranslationY(recyclerView.getHeight());\n                        int backgroundTranslationY = Math.max(0, recyclerPaddingTop - currentRecyclerScrollY);\n                        background.setTranslationY(recyclerView.getHeight() + backgroundTranslationY);\n                        recyclerView.setAdapter(adapter);\n                        if (stateRestored) {\n                            rootView.setAlpha(1f);\n                            recyclerView.setTranslationY(0);\n                            background.setTranslationY(backgroundTranslationY);\n                        } else {\n                            rootView.animate()\n                                    .alpha(1f)\n                                    .setDuration(animationDuration)\n                                    .setInterpolator(inInterpolator)\n                                    .setListener(null);\n                            recyclerView.animate()\n                                    .translationY(0)\n                                    .setDuration(animationDuration)\n                                    .setInterpolator(inInterpolator)\n                                    .setListener(null);\n                            background.animate()\n                                    .translationY(backgroundTranslationY)\n                                    .setDuration(animationDuration)\n                                    .setInterpolator(inInterpolator)\n                                    .setListener(null);\n                        }\n                        return false;\n                    }\n                }\n        );\n        recyclerView.addOnScrollListener(\n                new RecyclerView.OnScrollListener() {\n                    @Override\n                    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {\n                        super.onScrolled(recyclerView, dx, dy);\n                        currentRecyclerScrollY += dy;\n                        if (!isStickyTitleDisplayed && currentRecyclerScrollY >= recyclerPaddingTop) {\n                            isStickyTitleDisplayed = true;\n                            stickyTitle.setVisibility(View.VISIBLE);\n                            stickyShadow.setVisibility(View.VISIBLE);\n                        } else if (currentRecyclerScrollY < recyclerPaddingTop) {\n                            if (isStickyTitleDisplayed) {\n                                isStickyTitleDisplayed = false;\n                                stickyTitle.setVisibility(View.INVISIBLE);\n                                stickyShadow.setVisibility(View.INVISIBLE);\n                            }\n                            background.setTranslationY(recyclerPaddingTop - currentRecyclerScrollY);\n\n                        }\n                    }\n                }\n        );\n    }\n\n    private void setUpStickyTitle() {\n        stickyTitle.setVisibility(View.INVISIBLE);\n        stickyShadow.setVisibility(View.INVISIBLE);\n        stickyTitle.setModel(intentShare.chooserTitle);\n        isStickyTitleDisplayed = false;\n    }\n\n    private void finishAnimated() {\n        rootView.animate()\n                .alpha(0)\n                .setDuration(animationDuration)\n                .setInterpolator(outInterpolator)\n                .setListener(new AnimatorListenerAdapter() {\n                                 @Override\n                                 public void onAnimationEnd(Animator animation) {\n                                     super.onAnimationEnd(animation);\n                                     TargetChooserActivity.this.finish();\n                                     TargetChooserActivity.this.overridePendingTransition(-1, -1);\n                                 }\n                             }\n                );\n        recyclerView.animate()\n                .translationY(rootView.getHeight())\n                .setDuration(animationDuration)\n                .setInterpolator(outInterpolator)\n                .setListener(null);\n        background.animate()\n                .translationY(background.getTranslationY() + rootView.getHeight())\n                .setDuration(animationDuration)\n                .setInterpolator(outInterpolator)\n                .setListener(null);\n        stickyShadow.animate()\n                .translationY(rootView.getHeight())\n                .setDuration(animationDuration)\n                .setInterpolator(outInterpolator)\n                .setListener(null);\n        stickyTitle.animate()\n                .translationY(rootView.getHeight())\n                .setDuration(animationDuration)\n                .setInterpolator(outInterpolator)\n                .setListener(null);\n    }\n}\n"
  },
  {
    "path": "library/src/main/res/layout/isl_activity_target_chooser.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/activity_target_chooser_root_view\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"@color/isl_activity_translucent_background\"\n    android:fitsSystemWindows=\"true\">\n\n    <View\n        android:id=\"@+id/activity_target_chooser_background\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:background=\"@color/isl_target_activity_view_background\" />\n\n    <fr.tvbarthel.intentshare.BottomRecyclerView\n        android:id=\"@+id/activity_target_chooser_recycler_list\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:clipToPadding=\"false\"\n        android:overScrollMode=\"never\"\n        android:paddingLeft=\"@dimen/isl_target_activity_recycler_padding\"\n        android:paddingRight=\"@dimen/isl_target_activity_recycler_padding\" />\n\n    <fr.tvbarthel.intentshare.TargetActivityHeaderView\n        android:id=\"@+id/activity_chooser_sticky_title\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:paddingLeft=\"@dimen/isl_default_padding\"\n        android:paddingRight=\"@dimen/isl_default_padding\" />\n\n    <View\n        android:id=\"@+id/activity_chooser_sticky_title_shadow\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"10dp\"\n        android:layout_marginTop=\"@dimen/isl_target_activity_header_view_height\"\n        android:background=\"@drawable/isl_shadow_bottom\" />\n\n</FrameLayout>\n"
  },
  {
    "path": "library/src/main/res/layout/isl_target_activity_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<merge xmlns:android=\"http://schemas.android.com/apk/res/android\"\n       android:layout_width=\"match_parent\"\n       android:layout_height=\"match_parent\">\n\n    <ImageView\n        android:id=\"@+id/target_activity_view_icon\"\n        android:layout_width=\"@dimen/isl_target_activity_view_icon_size\"\n        android:layout_height=\"@dimen/isl_target_activity_view_icon_size\"\n        android:layout_gravity=\"center_vertical\"\n        android:layout_marginLeft=\"@dimen/isl_target_activity_icon_margin_left\"/>\n\n    <TextView\n        android:id=\"@+id/target_activity_view_label\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_gravity=\"center_vertical\"\n        android:layout_marginLeft=\"@dimen/isl_target_activity_view_label_icon_margin\"\n        android:ellipsize=\"end\"\n        android:singleLine=\"true\"\n        android:textColor=\"@color/isl_target_activity_view_label\"\n        android:textSize=\"@dimen/isl_target_activity_view_text_size\"/>\n\n</merge>"
  },
  {
    "path": "library/src/main/res/layout-v23/isl_target_activity_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<merge xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <ImageView\n        android:id=\"@+id/target_activity_view_icon\"\n        android:layout_width=\"@dimen/isl_target_activity_view_icon_size\"\n        android:layout_height=\"@dimen/isl_target_activity_view_icon_size\"\n        android:layout_gravity=\"center_horizontal|top\"\n        android:layout_marginLeft=\"@dimen/isl_target_activity_icon_margin_left\" />\n\n    <TextView\n        android:id=\"@+id/target_activity_view_label\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"@dimen/isl_target_activity_view_label_icon_margin\"\n        android:ellipsize=\"end\"\n        android:fontFamily=\"sans-serif-condensed\"\n        android:gravity=\"center\"\n        android:maxLines=\"2\"\n        android:textColor=\"@color/isl_target_activity_view_label\"\n        android:textSize=\"@dimen/isl_target_activity_view_text_size\" />\n\n</merge>"
  },
  {
    "path": "library/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"isl_target_activity_view_label\">#212121</color>\n    <color name=\"isl_target_activity_view_background\">@android:color/white</color>\n    <color name=\"isl_target_activity_header_view_background\">@android:color/white</color>\n    <color name=\"isl_target_activity_header_view_text_color\">#767676</color>\n    <color name=\"isl_activity_translucent_background\">#88000000</color>\n</resources>"
  },
  {
    "path": "library/src/main/res/values/dimens.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <dimen name=\"isl_default_padding\">16dp</dimen>\n\n    <!-- Target Activity View !-->\n    <dimen name=\"isl_target_activity_padding_vertical\">16dp</dimen>\n    <dimen name=\"isl_target_activity_padding_horizontal\">16dp</dimen>\n    <dimen name=\"isl_target_activity_view_icon_size\">24dp</dimen>\n    <dimen name=\"isl_target_activity_icon_margin_left\">10dp</dimen>\n    <dimen name=\"isl_target_activity_view_label_icon_margin\">54dp</dimen>\n    <dimen name=\"isl_target_activity_header_view_font_size\">19sp</dimen>\n    <dimen name=\"isl_target_activity_header_view_height\">60dp</dimen>\n    <dimen name=\"isl_target_activity_view_height\">60dp</dimen>\n    <dimen name=\"isl_target_activity_view_text_size\">19sp</dimen>\n    <dimen name=\"isl_target_activity_recycler_padding\">0dp</dimen>\n    <dimen name=\"isl_target_activity_header_extra_padding\">@dimen/isl_default_padding</dimen>\n</resources>"
  },
  {
    "path": "library/src/main/res/values/public.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <public name=\"IntentShareTheme\" type=\"style\" tools:ignore=\"ResourceName\" />\n</resources>"
  },
  {
    "path": "library/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"isl_default_sharing_label\">Share with</string>\n</resources>\n"
  },
  {
    "path": "library/src/main/res/values/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <style name=\"IntentShareTheme\" parent=\"isl_ActivityThemeBase\" tools:ignore=\"ResourceName\">\n        <!-- Customize your theme here. -->\n    </style>\n\n    <style name=\"isl_ActivityThemeBase\" parent=\"Theme.AppCompat.Light.NoActionBar\">\n        <item name=\"android:windowIsTranslucent\">true</item>\n        <item name=\"android:windowBackground\">@android:color/transparent</item>\n    </style>\n</resources>"
  },
  {
    "path": "library/src/main/res/values-v19/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <style name=\"IntentShareTheme\" parent=\"isl_ActivityThemeBase\" tools:ignore=\"ResourceName\">\n        <!-- Customize your theme here. -->\n        <item name=\"android:windowTranslucentStatus\">true</item>\n    </style>\n</resources>"
  },
  {
    "path": "library/src/main/res/values-v23/dimens.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <dimen name=\"isl_default_padding\">16dp</dimen>\n\n    <!-- Target Activity View !-->\n    <dimen name=\"isl_target_activity_padding_vertical\">16dp</dimen>\n    <dimen name=\"isl_target_activity_padding_horizontal\">4dp</dimen>\n    <dimen name=\"isl_target_activity_view_icon_size\">48dp</dimen>\n    <dimen name=\"isl_target_activity_icon_margin_left\">0dp</dimen>\n    <dimen name=\"isl_target_activity_view_label_icon_margin\">56dp</dimen>\n    <dimen name=\"isl_target_activity_header_view_font_size\">19sp</dimen>\n    <dimen name=\"isl_target_activity_header_view_height\">60dp</dimen>\n    <dimen name=\"isl_target_activity_view_height\">120dp</dimen>\n    <dimen name=\"isl_target_activity_view_text_size\">12sp</dimen>\n    <dimen name=\"isl_target_activity_recycler_padding\">@dimen/isl_default_padding</dimen>\n    <dimen name=\"isl_target_activity_header_extra_padding\">0dp</dimen>\n</resources>"
  },
  {
    "path": "library/src/test/java/fr/tvbarthel/intentshare/IntentShareTest.java",
    "content": "package fr.tvbarthel.intentshare;\n\nimport android.content.Context;\nimport android.net.Uri;\n\nimport junit.framework.Assert;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport static org.mockito.Mockito.mock;\n\n/**\n * Test for {@link IntentShare}\n */\n@RunWith(RobolectricTestRunner.class)\n@Config(manifest = Config.NONE)\npublic class IntentShareTest {\n\n    @Test\n    public void testTweetLimitEquals() throws Exception {\n        Context context = mock(Context.class);\n        String tweetLimitExceeded = \"Tweet 140-character limit over exceeded with a \"\n            + \"very very very very very very very very very very very very very\"\n            + \"very ver\"\n            + \"long text of 140 char\";\n        Assert.assertEquals(140, tweetLimitExceeded.length());\n        IntentShare.with(context).twitterBody(tweetLimitExceeded);\n    }\n\n    @Test\n    public void testImageUriSupported() throws Exception {\n        Context context = mock(Context.class);\n        Uri image = Uri.parse(\"content://fr.tvbarthel.test.fileprovider/test.png\");\n        IntentShare.with(context).image(image);\n    }\n\n    @Test(expected = IllegalArgumentException.class)\n    public void testImageUriSchemeNotSupported() throws Exception {\n        Context context = mock(Context.class);\n        Uri image = Uri.parse(\"http://tvbarthel.com/test.png\");\n        IntentShare.with(context).image(image);\n    }\n\n    @Test(expected = IllegalArgumentException.class)\n    public void testImageUriExtensionNotSupported() throws Exception {\n        Context context = mock(Context.class);\n        Uri image = Uri.parse(\"content://fr.tvbarthel.test.fileprovider/test.html\");\n        IntentShare.with(context).image(image);\n    }\n\n    @Test(expected = IllegalArgumentException.class)\n    public void testFacebookUriSchemeNotSupported() {\n        Context context = mock(Context.class);\n        Uri uri = Uri.parse(\"mailto://thomas.barthelemy.utc@gmail.com\");\n        IntentShare.with(context).facebookBody(uri);\n    }\n\n    @Test\n    public void testFacebookURiSchemeSupported() {\n        Context context = mock(Context.class);\n        Uri uri = Uri.parse(\"http://www.tvbarthel.com\");\n        IntentShare.with(context).facebookBody(uri);\n    }\n\n\n}\n"
  },
  {
    "path": "picasso-loader/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "picasso-loader/build.gradle",
    "content": "apply plugin: 'com.android.library'\napply plugin: 'com.github.dcendents.android-maven'\napply plugin: 'com.jfrog.bintray'\napply from: '../config/quality.gradle'\n\ngroup = 'fr.tvbarthel.intentshare'\nversion = rootProject.ext.versionName\n\nandroid {\n    compileSdkVersion rootProject.ext.compileSdkVersion\n    buildToolsVersion rootProject.ext.buildToolsVersion\n\n    defaultConfig {\n        minSdkVersion rootProject.ext.minSdkVersion\n        targetSdkVersion rootProject.ext.targetSdkVersion\n        versionCode rootProject.ext.versionCode\n        versionName rootProject.ext.versionName\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\n    compile 'com.squareup.picasso:picasso:2.5.2'\n\n    compile project(':library')\n}\n\nProperties properties = new Properties()\nproperties.load(project.rootProject.file('local.properties').newDataInputStream())\ndef bintrayUser = properties.getProperty('bintray.user')\ndef bintrayKey = properties.getProperty('bintray.apikey')\n\nbintray {\n    user = bintrayUser\n    key = bintrayKey\n\n\n    configurations = ['archives'] //When uploading configuration files\n\n    dryRun = false //Whether to run this as dry-run, without deploying\n    publish = true //If version should be auto published after an upload\n    //Package configuration. The plugin will use the repo and name properties to check if the package already exists. In that case, there's no need to configure the other package properties (like userOrg, desc, etc).\n    pkg {\n        repo = 'maven'\n        name = 'PicassoLoader'\n        desc = 'Icon loader based on Picasso for IntentShare library.'\n        websiteUrl = 'https://github.com/tvbarthel/IntentShare'\n        issueTrackerUrl = 'https://github.com/tvbarthel/IntentShare/issues'\n        vcsUrl = 'https://github.com/tvbarthel/IntentShare.git'\n        licenses = ['Apache-2.0']\n        labels = ['android', 'intent', 'sharing', 'share', 'picasso']\n        publicDownloadNumbers = true\n        version {\n            gpg {\n                sign = true //Determines whether to GPG sign the files. The default is false\n            }\n        }\n\n    }\n}\n\ninstall {\n    repositories.mavenInstaller {\n        pom {\n            project {\n                packaging 'aar'\n                name 'PicassoLoader'\n                url 'https://github.com/tvbarthel/IntentShare'\n                description 'Icon loader based on Picasso for IntentShare library.'\n                licenses {\n                    license {\n                        name 'The Apache Software License, Version 2.0'\n                        url 'http://www.apache.org/licenses/LICENSE-2.0.txt'\n                    }\n                }\n                developers {\n                    developer {\n                        id 'tbarthel-fr'\n                        name 'Thomas Barthelemy'\n                        email 'thomas.barthelemy.utc@gmail.com'\n                    }\n                    developer {\n                        id 'vbarthel-fr'\n                        name 'Vincent Barthelemy'\n                        email 'vincent.barthelemy.perso@gmail.com'\n                    }\n                }\n                scm {\n                    connection 'https://github.com/tvbarthel/IntentShare.git'\n                    developerConnection 'https://github.com/tvbarthel/IntentShare.git'\n                    url 'https://github.com/tvbarthel/IntentShare'\n\n                }\n            }\n        }\n    }\n}\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    failOnError = false\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"
  },
  {
    "path": "picasso-loader/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/thomasbarthelemy/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": "picasso-loader/src/main/AndroidManifest.xml",
    "content": "<manifest package=\"fr.tvbarthel.intentshare.loader.picasso\">\n\n    <application />\n\n</manifest>\n"
  },
  {
    "path": "picasso-loader/src/main/java/fr/tvbarthel/intentshare/loader/picasso/PicassoIconLoader.java",
    "content": "package fr.tvbarthel.intentshare.loader.picasso;\n\nimport android.net.Uri;\nimport android.os.Parcel;\nimport android.widget.ImageView;\n\nimport com.squareup.picasso.Picasso;\n\nimport fr.tvbarthel.intentshare.IconLoader;\n\n/**\n * {@link IconLoader} based on {@link com.squareup.picasso.Picasso}.\n */\npublic class PicassoIconLoader implements IconLoader {\n\n    /**\n     * Parcelable.\n     */\n    public static final Creator<PicassoIconLoader> CREATOR = new Creator<PicassoIconLoader>() {\n        @Override\n        public PicassoIconLoader createFromParcel(Parcel source) {\n            return new PicassoIconLoader(source);\n        }\n\n        @Override\n        public PicassoIconLoader[] newArray(int size) {\n            return new PicassoIconLoader[size];\n        }\n    };\n\n    /**\n     * {@link IconLoader} based on {@link com.squareup.picasso.Picasso}.\n     */\n    public PicassoIconLoader() {\n    }\n\n    /**\n     * {@link IconLoader} based on {@link com.squareup.picasso.Picasso}.\n     *\n     * @param in parcel.\n     */\n    protected PicassoIconLoader(Parcel in) {\n    }\n\n    @Override\n    public void load(Uri iconUri, ImageView imageView) {\n        Picasso.with(imageView.getContext())\n                .load(iconUri)\n                .fit()\n                .centerInside()\n                .into(imageView);\n    }\n\n    @Override\n    public void cancel(ImageView imageView) {\n        Picasso.with(imageView.getContext()).cancelRequest(imageView);\n    }\n\n    @Override\n    public int describeContents() {\n        return 0;\n    }\n\n    @Override\n    public void writeToParcel(Parcel dest, int flags) {\n    }\n\n}\n"
  },
  {
    "path": "sample/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "sample/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 25\n    buildToolsVersion \"25.0.0\"\n\n    defaultConfig {\n        applicationId \"fr.tvbarthel.intentsharesample\"\n        minSdkVersion 14\n        targetSdkVersion 25\n        versionCode 3\n        versionName \"1.2\"\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:25.0.0'\n    compile 'com.android.support:design:25.0.0'\n    compile project(':library')\n    compile project(':picasso-loader')\n    compile project(':glide-loader')\n}\n"
  },
  {
    "path": "sample/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 /home/thomas/Documents/android-sdk-linux/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": "sample/src/androidTest/java/fr/tvbarthel/intentsharesample/ApplicationTest.java",
    "content": "package fr.tvbarthel.intentsharesample;\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": "sample/src/main/AndroidManifest.xml",
    "content": "<manifest package=\"fr.tvbarthel.intentsharesample\"\n          xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <application\n        android:allowBackup=\"false\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\">\n        <activity android:name=\".MainActivity\">\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        <!-- provider used to expose image through sharing intent!-->\n        <provider\n            android:name=\".SharingFileProvider\"\n            android:authorities=\"fr.tvbarthel.intentsharesample.fileprovider\"\n            android:exported=\"false\"\n            android:grantUriPermissions=\"true\">\n            <meta-data\n                android:name=\"android.support.FILE_PROVIDER_PATHS\"\n                android:resource=\"@xml/file_provider_paths\" />\n        </provider>\n\n\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "sample/src/main/java/fr/tvbarthel/intentsharesample/Adapter.java",
    "content": "package fr.tvbarthel.intentsharesample;\n\nimport android.support.v7.widget.RecyclerView;\nimport android.view.View;\nimport android.view.ViewGroup;\n\nimport java.util.ArrayList;\n\n/**\n * Simple adapter used to display the main content.\n */\nclass Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {\n\n\n    private static final int VIEW_TYPE_HEADER = 1;\n    private static final int VIEW_TYPE_FOOTER = 2;\n    private static final int VIEW_TYPE_EXTRA_PROVIDER = 3;\n    private static final int HEADER_COUNT = 1;\n    private static final int FOOTER_COUNT = 1;\n\n    private final ArrayList<ExtraProviderWrapper> extraProviders;\n\n    private HeaderView.Listener internalHeaderListener;\n    private FooterView.Listener internalFooterListener;\n    private ExtraProviderWrapperView.Listener internalExtraProviderViewListener;\n    private Listener listener;\n\n    /**\n     * Simple adapter used to display the main content.\n     *\n     * @param extraProviders extra providers which must be listed for the user.\n     */\n    public Adapter(ArrayList<ExtraProviderWrapper> extraProviders) {\n        this.extraProviders = extraProviders;\n        internalHeaderListener = new HeaderView.Listener() {\n            @Override\n            public void onLearMoreRequested() {\n                if (listener != null) {\n                    listener.onLearMoreRequested();\n                }\n            }\n\n            @Override\n            public void onDialogTitleChanged(String dialogTitle) {\n                if (listener != null) {\n                    listener.onDialogTitleChanged(dialogTitle);\n                }\n            }\n\n            @Override\n            public void onSharedTextChanged(String sharedText) {\n                if (listener != null) {\n                    listener.onSharedTextChanged(sharedText);\n                }\n            }\n\n            @Override\n            public void onFacebookLinkChanged(String currentFacebookLink) {\n                if (listener != null) {\n                    listener.onFacebookLinkChanged(currentFacebookLink);\n                }\n            }\n\n            @Override\n            public void onTweetChanged(String currentTweet) {\n                if (listener != null) {\n                    listener.onTweetChanged(currentTweet);\n                }\n            }\n\n            @Override\n            public void onMailSubjectChanged(String currentMailSubject) {\n                if (listener != null) {\n                    listener.onMailSubjectChanged(currentMailSubject);\n                }\n            }\n\n            @Override\n            public void onMailBodyChanged(String currentMailBody) {\n                if (listener != null) {\n                    listener.onMailBodyChanged(currentMailBody);\n                }\n            }\n        };\n        internalFooterListener = new FooterView.Listener() {\n            @Override\n            public void onAddExtraProviderRequested() {\n                if (listener != null) {\n                    listener.onAddExtraProviderRequested();\n                }\n            }\n        };\n        internalExtraProviderViewListener = new ExtraProviderWrapperView.Listener() {\n            @Override\n            public void onExtraProviderDetailRequested(ExtraProviderWrapper wrapper) {\n                if (listener != null) {\n                    int wrapperPosition = Adapter.this.extraProviders.indexOf(wrapper);\n                    listener.onExtraProviderDetailRequested(wrapperPosition, wrapper);\n                }\n            }\n        };\n    }\n\n    @Override\n    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {\n\n        switch (viewType) {\n            case VIEW_TYPE_HEADER:\n                HeaderView headerView = new HeaderView(parent.getContext());\n                headerView.setListener(internalHeaderListener);\n                headerView.setLayoutParams(\n                        new RecyclerView.LayoutParams(\n                                ViewGroup.LayoutParams.MATCH_PARENT,\n                                ViewGroup.LayoutParams.WRAP_CONTENT\n                        )\n                );\n                return new ViewHolder(headerView);\n            case VIEW_TYPE_FOOTER:\n                FooterView footerView = new FooterView(parent.getContext());\n                footerView.setListener(internalFooterListener);\n                footerView.setLayoutParams(\n                        new RecyclerView.LayoutParams(\n                                ViewGroup.LayoutParams.MATCH_PARENT,\n                                ViewGroup.LayoutParams.WRAP_CONTENT\n                        )\n                );\n                return new ViewHolder(footerView);\n            default:\n                ExtraProviderWrapperView extraProviderView\n                        = new ExtraProviderWrapperView(parent.getContext());\n                extraProviderView.setListener(internalExtraProviderViewListener);\n                extraProviderView.setLayoutParams(\n                        new RecyclerView.LayoutParams(\n                                ViewGroup.LayoutParams.MATCH_PARENT,\n                                ViewGroup.LayoutParams.WRAP_CONTENT\n                        )\n                );\n                return new ViewHolder(extraProviderView);\n        }\n    }\n\n    @Override\n    public void onBindViewHolder(ViewHolder holder, int position) {\n        if (holder.getItemViewType() == VIEW_TYPE_EXTRA_PROVIDER) {\n            ((ExtraProviderWrapperView) holder.itemView).presentData(extraProviders.get(position - HEADER_COUNT));\n        }\n    }\n\n    @Override\n    public int getItemCount() {\n        return extraProviders.size() + HEADER_COUNT + FOOTER_COUNT;\n    }\n\n    @Override\n    public int getItemViewType(int position) {\n        if (position == 0) {\n            return VIEW_TYPE_HEADER;\n        } else if (position == getItemCount() - 1) {\n            return VIEW_TYPE_FOOTER;\n        } else {\n            return VIEW_TYPE_EXTRA_PROVIDER;\n        }\n    }\n\n    /**\n     * Listener used to catch adapted views events.\n     *\n     * @param listener Listener used to catch adapted views events.\n     */\n    public void setListener(Listener listener) {\n        this.listener = listener;\n    }\n\n    /**\n     * Notify the adapter that an extra provider has been inserted at the end of the list.\n     */\n    public void notifyExtraProviderInserted() {\n        notifyItemInserted(extraProviders.size() - 1 + HEADER_COUNT);\n    }\n\n    /**\n     * Notify the adapter that an extra provider has changed.\n     *\n     * @param position position of the extra provider in the list.\n     */\n    public void notifyExtraProviderChanged(int position) {\n        notifyItemChanged(position + HEADER_COUNT);\n    }\n\n    /**\n     * View holder pattern.\n     */\n    public final class ViewHolder extends RecyclerView.ViewHolder {\n\n        /**\n         * View holder pattern.\n         *\n         * @param itemView view to hold.\n         */\n        public ViewHolder(View itemView) {\n            super(itemView);\n        }\n    }\n\n    /**\n     * Listener used to catch adapted views events.\n     */\n    public interface Listener {\n\n        /**\n         * Called when the user wants to access to more information about the library.\n         */\n        void onLearMoreRequested();\n\n        /**\n         * Called when the user wants to add an extra provider.\n         */\n        void onAddExtraProviderRequested();\n\n        /**\n         * Called when the user update the dialog title.\n         */\n        void onDialogTitleChanged(String dialogTitle);\n\n        /**\n         * Called when the user update the text to share.\n         *\n         * @param sharedText text to share.\n         */\n        void onSharedTextChanged(String sharedText);\n\n        /**\n         * Called when the user change the link he wants to share on facebook.\n         *\n         * @param currentFacebookLink facebook link.\n         */\n        void onFacebookLinkChanged(String currentFacebookLink);\n\n        /**\n         * Called when the user change the content of the tweet.\n         *\n         * @param currentTweet new tweet body.\n         */\n        void onTweetChanged(String currentTweet);\n\n        /**\n         * Called when the user change the mail subject.\n         *\n         * @param currentMailSubject new mail subject.\n         */\n        void onMailSubjectChanged(String currentMailSubject);\n\n        /**\n         * Called when the user change the mail body.\n         *\n         * @param currentMailBody new mail body.\n         */\n        void onMailBodyChanged(String currentMailBody);\n\n        /**\n         * Called when the user wants to access to more detail for a given extra provider.\n         */\n        void onExtraProviderDetailRequested(int wrapperPosition, ExtraProviderWrapper wrapper);\n    }\n}\n"
  },
  {
    "path": "sample/src/main/java/fr/tvbarthel/intentsharesample/ExtraProviderDialogFragment.java",
    "content": "package fr.tvbarthel.intentsharesample;\n\nimport android.app.Activity;\nimport android.app.Dialog;\nimport android.os.Bundle;\nimport android.support.annotation.NonNull;\nimport android.support.design.widget.TextInputLayout;\nimport android.support.v4.app.DialogFragment;\nimport android.support.v4.app.FragmentManager;\nimport android.support.v7.app.AlertDialog;\nimport android.text.TextUtils;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.animation.Animation;\nimport android.view.animation.AnimationUtils;\nimport android.widget.CheckBox;\nimport android.widget.EditText;\nimport android.widget.ScrollView;\n\nimport fr.tvbarthel.intentshare.IntentShare;\n\n/**\n * Simple dialog used to edit an extra provider.\n */\npublic class ExtraProviderDialogFragment extends DialogFragment {\n\n    private static final String TAG = ExtraProviderDialogFragment.class.getSimpleName();\n    private static final String EXTRA_PROVIDER = \"args_extra_provider\";\n    private static final String EXTRA_POSITION = \"args_extra_position\";\n\n    /**\n     * Dummy callback used when fragment isn't attached.\n     */\n    private static Callback dummyCallback = new Callback() {\n        @Override\n        public void onExtraProviderChanged(int position, ExtraProviderWrapper extraProviderWrapper) {\n\n        }\n\n        @Override\n        public void onExtraProviderCreated(ExtraProviderWrapper extraProviderWrapper) {\n\n        }\n    };\n\n    /**\n     * Current callback object.\n     */\n    private Callback callback = dummyCallback;\n\n    /**\n     * Extra provider.\n     */\n    private ExtraProviderWrapper extraProvider;\n\n    /**\n     * position of the extra provider.\n     */\n    private int extraProviderPosition;\n\n    /**\n     * View components.\n     */\n    private TextInputLayout appNameInputLayout;\n    private TextInputLayout packageNameInputLayout;\n    private EditText textEditText;\n    private EditText subjectEditText;\n    private CheckBox disableTextCheckBox;\n    private CheckBox disableSubjectCheckBox;\n    private CheckBox disableImageCheckBox;\n\n    /**\n     * Animation used to display emphasis on non valid field.\n     */\n    private Animation wiggle;\n    private ScrollView scrollView;\n\n    /**\n     * Retrieve a new instnace to create a new extra provider.\n     *\n     * @return well instantiated instance.\n     */\n    public static ExtraProviderDialogFragment newInstance() {\n        return newInstance(-1, null);\n    }\n\n    /**\n     * Retrieve a new instance for editing a given extra provider.\n     *\n     * @param position             position of the extra provider inside the list.\n     * @param extraProviderWrapper extra provider to edit.\n     * @return well instantiated instance.\n     */\n    public static ExtraProviderDialogFragment newInstance(\n            int position,\n            ExtraProviderWrapper extraProviderWrapper) {\n        ExtraProviderDialogFragment extraProviderDialogFragment = new ExtraProviderDialogFragment();\n        Bundle args = new Bundle();\n        args.putParcelable(EXTRA_PROVIDER, extraProviderWrapper);\n        args.putInt(EXTRA_POSITION, position);\n        extraProviderDialogFragment.setArguments(args);\n        return extraProviderDialogFragment;\n    }\n\n    @Override\n    public void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        wiggle = AnimationUtils.loadAnimation(getContext(), R.anim.wiggle);\n    }\n\n    @Override\n    public void onAttach(Activity activity) {\n        super.onAttach(activity);\n\n        if (!(activity instanceof Callback)) {\n            throw new IllegalStateException(\"Holding activity must implement the dialog callback.\");\n        }\n\n        callback = ((Callback) activity);\n\n        extraProviderPosition = -1;\n        extraProvider = null;\n\n        Bundle args = getArguments();\n        if (args == null || !args.containsKey(EXTRA_POSITION) || !args.containsKey(EXTRA_PROVIDER)) {\n            throw new IllegalStateException(\"Required args missing, used new instance pattern.\");\n        }\n        extraProviderPosition = args.getInt(EXTRA_POSITION);\n        extraProvider = args.getParcelable(EXTRA_PROVIDER);\n    }\n\n    @Override\n    public void onDetach() {\n        super.onDetach();\n        callback = dummyCallback;\n    }\n\n    /**\n     * Display the dialog to the user.\n     *\n     * @param fragmentManager fragment manager used to show the dialog.\n     */\n    public void show(FragmentManager fragmentManager) {\n        this.show(fragmentManager, TAG);\n    }\n\n    @NonNull\n    @Override\n    public Dialog onCreateDialog(Bundle savedInstanceState) {\n        final View dialogView = LayoutInflater.from(getContext()).inflate(R.layout.fragment_dialog_extra_provider, null);\n\n        scrollView = ((ScrollView) dialogView.findViewById(R.id.fragment_dialog_extra_provider_scroll));\n        appNameInputLayout = ((TextInputLayout) dialogView.findViewById(R.id.fragment_dialog_extra_provider_app_name_input));\n        packageNameInputLayout = ((TextInputLayout) dialogView.findViewById(R.id.fragment_dialog_extra_provider_package_name_input));\n        textEditText = ((EditText) dialogView.findViewById(R.id.fragment_dialog_extra_provider_text));\n        subjectEditText = ((EditText) dialogView.findViewById(R.id.fragment_dialog_extra_provider_subject));\n        disableTextCheckBox = ((CheckBox) dialogView.findViewById(R.id.fragment_dialog_extra_provider_default_text_check));\n        disableSubjectCheckBox = ((CheckBox) dialogView.findViewById(R.id.fragment_dialog_extra_provider_default_subject_check));\n        disableImageCheckBox = ((CheckBox) dialogView.findViewById(R.id.fragment_dialog_extra_provider_default_image_check));\n\n        dialogView.findViewById(R.id.fragment_dialog_extra_provider_ok).setOnClickListener(\n                new View.OnClickListener() {\n                    @Override\n                    public void onClick(View v) {\n                        processForm();\n                    }\n                }\n        );\n\n        initializeView();\n\n\n        return new AlertDialog.Builder(getContext())\n                .setView(dialogView)\n                .setCancelable(true)\n                .create();\n    }\n\n    /**\n     * Initialize the dialog based on the passed extra provider.\n     */\n    private void initializeView() {\n        if (extraProvider != null) {\n            IntentShare.ExtraProvider wrappedProvider = this.extraProvider.getExtraProvider();\n            appNameInputLayout.getEditText().setText(extraProvider.getAppName());\n            packageNameInputLayout.getEditText().setText(wrappedProvider.getPackageName());\n            textEditText.setText(wrappedProvider.getOverriddenText());\n            subjectEditText.setText(wrappedProvider.getOverriddenSubject());\n            disableTextCheckBox.setChecked(wrappedProvider.isTextDisabled());\n            disableSubjectCheckBox.setChecked(wrappedProvider.isSubjectDisabled());\n            disableImageCheckBox.setChecked(wrappedProvider.isImageDisabled());\n        }\n    }\n\n    /**\n     * Process the current form data.\n     */\n    private void processForm() {\n        if (isFormValid()) {\n            IntentShare.ExtraProvider extraProvider = new IntentShare.ExtraProvider(\n                    packageNameInputLayout.getEditText().getText().toString()\n            );\n\n            String text = textEditText.getText().toString();\n            if (!TextUtils.isEmpty(text)) {\n                extraProvider.overrideText(text);\n            }\n\n            String subject = subjectEditText.getText().toString();\n            if (!TextUtils.isEmpty(subject)) {\n                extraProvider.overrideSubject(subject);\n            }\n\n            if (disableTextCheckBox.isChecked()) {\n                extraProvider.disableText();\n            }\n\n            if (disableSubjectCheckBox.isChecked()) {\n                extraProvider.disableSubject();\n            }\n\n            if (disableImageCheckBox.isChecked()) {\n                extraProvider.disableImage();\n            }\n\n            if (extraProviderPosition != -1) {\n                callback.onExtraProviderChanged(\n                        extraProviderPosition,\n                        new ExtraProviderWrapper(\n                                appNameInputLayout.getEditText().getText().toString(),\n                                extraProvider\n                        )\n                );\n            } else {\n                callback.onExtraProviderCreated(new ExtraProviderWrapper(\n                                appNameInputLayout.getEditText().getText().toString(),\n                                extraProvider\n                        )\n                );\n            }\n            dismiss();\n        }\n    }\n\n    /**\n     * Used to check if the form is well field.\n     *\n     * @return true if the farm is valid, false otherwise.\n     */\n    private boolean isFormValid() {\n        return isEditTextValid(appNameInputLayout) && isEditTextValid(packageNameInputLayout);\n    }\n\n    /**\n     * Used to check if an {@link EditText} is not empty.\n     *\n     * @param inputLayout layout containing an edit text which musn't be empty.\n     * @return true if the edit text is not empty.\n     */\n    private boolean isEditTextValid(@NonNull TextInputLayout inputLayout) {\n        EditText editText = inputLayout.getEditText();\n        String text = editText.getText().toString();\n        boolean empty = TextUtils.isEmpty(text);\n        if (empty) {\n            inputLayout.startAnimation(wiggle);\n            scrollView.smoothScrollTo(0, inputLayout.getTop());\n\n        }\n        return !empty;\n    }\n\n    /**\n     * Callback used to catch fragment events.\n     */\n    public interface Callback {\n        /**\n         * Called when the extra provider at the given position index has changed.\n         *\n         * @param position             position passed.\n         * @param extraProviderWrapper extra provider wrapper.\n         */\n        void onExtraProviderChanged(int position, ExtraProviderWrapper extraProviderWrapper);\n\n        /**\n         * Called when the user create a new extra provider.\n         *\n         * @param extraProviderWrapper new extra provider created.\n         */\n        void onExtraProviderCreated(ExtraProviderWrapper extraProviderWrapper);\n    }\n}\n"
  },
  {
    "path": "sample/src/main/java/fr/tvbarthel/intentsharesample/ExtraProviderWrapper.java",
    "content": "package fr.tvbarthel.intentsharesample;\n\nimport android.os.Parcel;\nimport android.os.Parcelable;\n\nimport fr.tvbarthel.intentshare.IntentShare;\n\n/**\n * Encapsulate data around an {@link ExtraProviderWrapper}\n */\nclass ExtraProviderWrapper implements Parcelable {\n\n    /**\n     * Parcelable.\n     */\n    public static final Parcelable.Creator<ExtraProviderWrapper> CREATOR\n            = new Parcelable.Creator<ExtraProviderWrapper>() {\n        @Override\n        public ExtraProviderWrapper createFromParcel(Parcel source) {\n            return new ExtraProviderWrapper(source);\n        }\n\n        @Override\n        public ExtraProviderWrapper[] newArray(int size) {\n            return new ExtraProviderWrapper[size];\n        }\n    };\n\n    private String appName;\n    private IntentShare.ExtraProvider extraProvider;\n\n    /**\n     * Encapsulate data around an {@link ExtraProviderWrapper}\n     *\n     * @param appName name of the app for which the extra provider has been build.\n     */\n    public ExtraProviderWrapper(String appName, IntentShare.ExtraProvider extraProvider) {\n        this.appName = appName;\n        this.extraProvider = extraProvider;\n    }\n\n    /**\n     * Encapsulate data around an {@link ExtraProviderWrapper}\n     *\n     * @param in parcel.\n     */\n    protected ExtraProviderWrapper(Parcel in) {\n        this.appName = in.readString();\n        this.extraProvider = in.readParcelable(IntentShare.ExtraProvider.class.getClassLoader());\n    }\n\n    @Override\n    public int describeContents() {\n        return 0;\n    }\n\n    @Override\n    public void writeToParcel(Parcel dest, int flags) {\n        dest.writeString(this.appName);\n        dest.writeParcelable(this.extraProvider, flags);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        ExtraProviderWrapper that = (ExtraProviderWrapper) o;\n\n        if (appName != null ? !appName.equals(that.appName) : that.appName != null) {\n            return false;\n        }\n        return !(extraProvider != null ? !extraProvider.equals(that.extraProvider) : that.extraProvider != null);\n\n    }\n\n    @Override\n    public int hashCode() {\n        int result = appName != null ? appName.hashCode() : 0;\n        result = 31 * result + (extraProvider != null ? extraProvider.hashCode() : 0);\n        return result;\n    }\n\n    /**\n     * Name of the app for which the extra provider has been build.\n     *\n     * @return Name of the app for which the extra provider has been build.\n     */\n    public String getAppName() {\n        return appName;\n    }\n\n    /**\n     * Access to the wrapped extra provider.\n     *\n     * @return wrapped extra provider.\n     */\n    public IntentShare.ExtraProvider getExtraProvider() {\n        return extraProvider;\n    }\n\n}\n"
  },
  {
    "path": "sample/src/main/java/fr/tvbarthel/intentsharesample/ExtraProviderWrapperView.java",
    "content": "package fr.tvbarthel.intentsharesample;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.widget.FrameLayout;\nimport android.widget.TextView;\n\n/**\n * View used to display an {@link ExtraProviderWrapper} list entry.\n */\nclass ExtraProviderWrapperView extends FrameLayout {\n\n    private TextView labelView;\n    private Listener listener;\n    private ExtraProviderWrapper extraProviderWrapper;\n\n    /**\n     * View used to display an extra provider list entry.\n     *\n     * @param context holding context.\n     */\n    public ExtraProviderWrapperView(Context context) {\n        this(context, null);\n    }\n\n    /**\n     * View used to display an extra provider list entry.\n     *\n     * @param context holding context.\n     * @param attrs   attrs from xml.\n     */\n    public ExtraProviderWrapperView(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    /**\n     * View used to display an extra provider list entry.\n     *\n     * @param context      holding context.\n     * @param attrs        attrs from xml.\n     * @param defStyleAttr style.\n     */\n    public ExtraProviderWrapperView(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        initialize(context);\n    }\n\n    /**\n     * Set the extra provider which should be presented to the user.\n     *\n     * @param extraProviderWrapper wrapper to display to the user.\n     */\n    public void presentData(ExtraProviderWrapper extraProviderWrapper) {\n        this.extraProviderWrapper = extraProviderWrapper;\n        labelView.setText(extraProviderWrapper.getAppName());\n    }\n\n    /**\n     * Set a listener to catch view events.\n     *\n     * @param listener listener used to catch view events.\n     */\n    public void setListener(Listener listener) {\n        this.listener = listener;\n    }\n\n    /**\n     * Initialize internal component.\n     *\n     * @param context holding context.\n     */\n    private void initialize(Context context) {\n        LayoutInflater.from(context).inflate(R.layout.extra_provider_view, this);\n        labelView = ((TextView) findViewById(R.id.extra_provider_view_label));\n        labelView.setOnClickListener(new OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                if (listener != null) {\n                    listener.onExtraProviderDetailRequested(extraProviderWrapper);\n                }\n            }\n        });\n    }\n\n    /**\n     * Interface used to catch view events.\n     */\n    public interface Listener {\n\n        /**\n         * Called when the user wants to access to more detail for a given extra provider.\n         */\n        void onExtraProviderDetailRequested(ExtraProviderWrapper wrapper);\n    }\n}\n"
  },
  {
    "path": "sample/src/main/java/fr/tvbarthel/intentsharesample/FooterView.java",
    "content": "package fr.tvbarthel.intentsharesample;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.widget.FrameLayout;\n\n/**\n * Footer view of the list.\n */\nclass FooterView extends FrameLayout {\n\n    private Listener listener;\n\n    /**\n     * Footer view of the list.\n     *\n     * @param context holding context.\n     */\n    public FooterView(Context context) {\n        this(context, null);\n    }\n\n    /**\n     * Footer view of the list.\n     *\n     * @param context holding context.\n     * @param attrs   attrs from xml.\n     */\n    public FooterView(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    /**\n     * Footer view of the list.\n     *\n     * @param context      holding context.\n     * @param attrs        attrs from xml.\n     * @param defStyleAttr style.\n     */\n    public FooterView(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        initialize(context);\n    }\n\n    /**\n     * Listener used to catch view events.\n     *\n     * @param listener Listener used to catch view events.\n     */\n    public void setListener(Listener listener) {\n        this.listener = listener;\n    }\n\n    /**\n     * Initialize internal component.\n     *\n     * @param context holding context.\n     */\n    private void initialize(Context context) {\n        LayoutInflater.from(context).inflate(R.layout.footer_view, this);\n        findViewById(R.id.footer_view_add).setOnClickListener(new OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                if (listener != null) {\n                    listener.onAddExtraProviderRequested();\n                }\n            }\n        });\n    }\n\n    /**\n     * Listener used to catch view events.\n     */\n    public interface Listener {\n        /**\n         * Called when the user wants to add an extra provider.\n         */\n        void onAddExtraProviderRequested();\n    }\n\n}\n"
  },
  {
    "path": "sample/src/main/java/fr/tvbarthel/intentsharesample/HeaderView.java",
    "content": "package fr.tvbarthel.intentsharesample;\n\nimport android.content.Context;\nimport android.content.res.Resources;\nimport android.text.Editable;\nimport android.text.TextWatcher;\nimport android.util.AttributeSet;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.widget.EditText;\nimport android.widget.LinearLayout;\n\n/**\n * View used to display the header.\n */\nclass HeaderView extends LinearLayout {\n\n    private OnClickListener internalClickListener;\n    private Listener listener;\n    private String currentDialogTitle;\n    private String currentSharedText;\n    private String currentFacebookLink;\n    private String currentTweet;\n    private EditText tweetEditText;\n    private String currentMailSubject;\n    private String currentMailBody;\n\n    /**\n     * View used to display the header.\n     *\n     * @param context holding context.\n     */\n    public HeaderView(Context context) {\n        this(context, null);\n    }\n\n    /**\n     * View used to display the header.\n     *\n     * @param context holding context.\n     * @param attrs   attrs from xml.\n     */\n    public HeaderView(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    /**\n     * View used to display the header.\n     *\n     * @param context      holding context.\n     * @param attrs        attrs from xml.\n     * @param defStyleAttr style.\n     */\n    public HeaderView(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        initialize(context);\n    }\n\n    /**\n     * Listener used to catch view events.\n     *\n     * @param listener listener used to catch view events.\n     */\n    public void setListener(Listener listener) {\n        this.listener = listener;\n        listener.onDialogTitleChanged(currentDialogTitle);\n        listener.onSharedTextChanged(currentSharedText);\n        listener.onFacebookLinkChanged(currentFacebookLink);\n        listener.onTweetChanged(currentTweet);\n        listener.onMailBodyChanged(currentMailBody);\n        listener.onMailSubjectChanged(currentMailSubject);\n    }\n\n    /**\n     * Initialize internal component.\n     *\n     * @param context holding context.\n     */\n    private void initialize(Context context) {\n        LayoutInflater.from(context).inflate(R.layout.header_view, this);\n\n        setOrientation(VERTICAL);\n\n        Resources resources = context.getResources();\n        int horizontalPadding = resources.getDimensionPixelSize(R.dimen.activity_horizontal_margin);\n        int verticalPadding = resources.getDimensionPixelSize(R.dimen.activity_vertical_margin);\n        setPadding(horizontalPadding, verticalPadding, horizontalPadding, 0);\n\n        internalClickListener = new OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                switch (v.getId()) {\n                    case R.id.main_header_view_learn_more_button:\n                        if (listener != null) {\n                            listener.onLearMoreRequested();\n                        }\n                        break;\n\n                }\n            }\n        };\n\n        findViewById(R.id.main_header_view_learn_more_button).setOnClickListener(internalClickListener);\n\n        initializeDialogTitle(context);\n        initializeSharedText(context);\n        initializeFacebookLink(context);\n        initializeTweetLink(context);\n        initializeMail(context);\n\n\n    }\n\n    private void initializeMail(Context context) {\n        EditText editSubject = (EditText) findViewById(R.id.main_header_view_mail_subject);\n        currentMailSubject = context.getString(R.string.article_title);\n        editSubject.setText(currentMailSubject);\n        editSubject.addTextChangedListener(new TextWatcher() {\n            @Override\n            public void beforeTextChanged(CharSequence s, int start, int count, int after) {\n\n            }\n\n            @Override\n            public void onTextChanged(CharSequence s, int start, int before, int count) {\n\n            }\n\n            @Override\n            public void afterTextChanged(Editable s) {\n                if (listener != null) {\n                    currentMailSubject = s.toString();\n                    listener.onMailSubjectChanged(currentMailSubject);\n                }\n            }\n        });\n        EditText editBody = (EditText) findViewById(R.id.main_header_view_mail_body);\n        currentMailBody = context.getString(R.string.article);\n        editBody.setText(currentMailBody);\n        editBody.addTextChangedListener(new TextWatcher() {\n            @Override\n            public void beforeTextChanged(CharSequence s, int start, int count, int after) {\n\n            }\n\n            @Override\n            public void onTextChanged(CharSequence s, int start, int before, int count) {\n\n            }\n\n            @Override\n            public void afterTextChanged(Editable s) {\n                if (listener != null) {\n                    currentMailBody = s.toString();\n                    listener.onMailBodyChanged(currentMailBody);\n                }\n            }\n        });\n    }\n\n    private void initializeTweetLink(Context context) {\n        tweetEditText = (EditText) findViewById(R.id.main_header_view_twitter);\n        currentTweet = context.getString(R.string.article_tweet);\n        tweetEditText.setText(currentTweet);\n        tweetEditText.addTextChangedListener(new TextWatcher() {\n            @Override\n            public void beforeTextChanged(CharSequence s, int start, int count, int after) {\n\n            }\n\n            @Override\n            public void onTextChanged(CharSequence s, int start, int before, int count) {\n\n            }\n\n            @Override\n            public void afterTextChanged(Editable s) {\n                if (s.length() > 140) {\n                    tweetEditText.setText(s.subSequence(0, 139));\n                    tweetEditText.setSelection(139);\n                }\n                if (listener != null) {\n                    currentTweet = s.toString();\n                    listener.onTweetChanged(currentTweet);\n                }\n            }\n        });\n    }\n\n    private void initializeFacebookLink(Context context) {\n        EditText editText = (EditText) findViewById(R.id.main_header_view_facebook);\n        currentFacebookLink = context.getString(R.string.article_url);\n        editText.setText(currentFacebookLink);\n        editText.addTextChangedListener(new TextWatcher() {\n            @Override\n            public void beforeTextChanged(CharSequence s, int start, int count, int after) {\n\n            }\n\n            @Override\n            public void onTextChanged(CharSequence s, int start, int before, int count) {\n\n            }\n\n            @Override\n            public void afterTextChanged(Editable s) {\n                if (listener != null) {\n                    currentFacebookLink = s.toString();\n                    listener.onFacebookLinkChanged(currentFacebookLink);\n                }\n            }\n        });\n    }\n\n    private void initializeSharedText(Context context) {\n        EditText sharedText = (EditText) findViewById(R.id.main_header_view_input_text);\n        currentSharedText = context.getString(R.string.default_shared_text);\n        sharedText.setText(currentSharedText);\n        sharedText.addTextChangedListener(new TextWatcher() {\n            @Override\n            public void beforeTextChanged(CharSequence s, int start, int count, int after) {\n\n            }\n\n            @Override\n            public void onTextChanged(CharSequence s, int start, int before, int count) {\n\n            }\n\n            @Override\n            public void afterTextChanged(Editable s) {\n                if (listener != null) {\n                    currentSharedText = s.toString();\n                    listener.onSharedTextChanged(currentSharedText);\n                }\n            }\n        });\n    }\n\n    private void initializeDialogTitle(Context context) {\n        EditText dialogTitle = (EditText) findViewById(R.id.main_header_view_input_dialog_title);\n        currentDialogTitle = context.getString(R.string.default_dialog_title);\n        dialogTitle.setText(currentDialogTitle);\n        dialogTitle.addTextChangedListener(new TextWatcher() {\n            @Override\n            public void beforeTextChanged(CharSequence s, int start, int count, int after) {\n\n            }\n\n            @Override\n            public void onTextChanged(CharSequence s, int start, int before, int count) {\n\n            }\n\n            @Override\n            public void afterTextChanged(Editable s) {\n                if (listener != null) {\n                    currentDialogTitle = s.toString();\n                    listener.onDialogTitleChanged(currentDialogTitle);\n                }\n            }\n        });\n    }\n\n    /**\n     * Listener used to catch view events.\n     */\n    public interface Listener {\n\n        /**\n         * Called when the user wants to access to more information about the library.\n         */\n        void onLearMoreRequested();\n\n        /**\n         * Called when the user update the dialog title.\n         */\n        void onDialogTitleChanged(String dialogTitle);\n\n        /**\n         * Called when the user update the text to share.\n         *\n         * @param sharedText text to share.\n         */\n        void onSharedTextChanged(String sharedText);\n\n        /**\n         * Called when the user change the link he wants to share on facebook.\n         *\n         * @param currentFacebookLink facebook link.\n         */\n        void onFacebookLinkChanged(String currentFacebookLink);\n\n        /**\n         * Called when the user change the content of the tweet.\n         *\n         * @param currentTweet new tweet body.\n         */\n        void onTweetChanged(String currentTweet);\n\n        /**\n         * Called when the user change the mail subject.\n         *\n         * @param currentMailSubject new mail subject.\n         */\n        void onMailSubjectChanged(String currentMailSubject);\n\n        /**\n         * Called when the user change the mail body.\n         *\n         * @param currentMailBody new mail body.\n         */\n        void onMailBodyChanged(String currentMailBody);\n    }\n}\n"
  },
  {
    "path": "sample/src/main/java/fr/tvbarthel/intentsharesample/MainActivity.java",
    "content": "package fr.tvbarthel.intentsharesample;\n\nimport android.content.Context;\nimport android.content.Intent;\nimport android.graphics.Bitmap;\nimport android.graphics.BitmapFactory;\nimport android.net.Uri;\nimport android.os.Bundle;\nimport android.support.v4.content.FileProvider;\nimport android.support.v7.app.AppCompatActivity;\nimport android.support.v7.widget.LinearLayoutManager;\nimport android.support.v7.widget.RecyclerView;\nimport android.util.Log;\nimport android.view.Menu;\nimport android.view.MenuInflater;\nimport android.view.MenuItem;\nimport android.view.View;\nimport android.widget.Toast;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.File;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.util.ArrayList;\n\nimport fr.tvbarthel.intentshare.IconLoader;\nimport fr.tvbarthel.intentshare.IntentShare;\nimport fr.tvbarthel.intentshare.IntentShareListener;\nimport fr.tvbarthel.intentshare.TargetActivityComparatorProvider;\nimport fr.tvbarthel.intentshare.loader.glide.GlideIconLoader;\nimport fr.tvbarthel.intentshare.loader.picasso.PicassoIconLoader;\n\npublic class MainActivity extends AppCompatActivity implements\n        Adapter.Listener, View.OnClickListener, ExtraProviderDialogFragment.Callback {\n\n    /**\n     * Log cat.\n     */\n    private static final String TAG = MainActivity.class.getSimpleName();\n\n    /**\n     * Const used for saving temp image file for sharing purpose.\n     */\n    private static final int SHARED_IMAGE_QUALITY = 100;\n    private static final String SHARED_DIRECTORY = \"sharing\";\n    private static final String SHARED_IMAGE_FILE = \"shared_img.png\";\n    private static final String FILE_PROVIDER_AUTHORITY = \"fr.tvbarthel.intentsharesample.fileprovider\";\n\n    private IntentShareListener intentShareListener;\n\n    private PicassoIconLoader picassoIconLoader;\n    private IconLoader iconLoader;\n    private TargetActivityComparatorProvider customComparatorProvider;\n    private GlideIconLoader glideIconLoader;\n\n    private String targetPackage;\n    private String dialogTitle;\n    private String sharedText;\n    private ArrayList<ExtraProviderWrapper> extraProviders;\n    private Adapter adapter;\n    private Uri facebookLink;\n    private String tweet;\n    private String mailSubject;\n    private String mailBody;\n    private Uri imageUri;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n\n        targetPackage = null;\n        customComparatorProvider = null;\n\n        intentShareListener = new IntentShareListener() {\n            @Override\n            public void onCompleted(String packageName) {\n                targetPackage = packageName;\n            }\n\n            @Override\n            public void onCanceled() {\n                Toast.makeText(MainActivity.this, \"Sharing canceled\", Toast.LENGTH_SHORT).show();\n            }\n        };\n\n        setUpRecyclerView();\n        findViewById(R.id.activity_main_share_button).setOnClickListener(this);\n        imageUri = getShareableUri(this, BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n        if (targetPackage != null) {\n            Toast.makeText(MainActivity.this, \"Shared with : \" + targetPackage, Toast.LENGTH_SHORT).show();\n            targetPackage = null;\n        }\n    }\n\n    @Override\n    public boolean onCreateOptionsMenu(Menu menu) {\n        MenuInflater inflater = getMenuInflater();\n        inflater.inflate(R.menu.activity_sample_menu, menu);\n        return true;\n    }\n\n    @Override\n    public boolean onOptionsItemSelected(MenuItem item) {\n        switch (item.getItemId()) {\n            case R.id.sample_icon_loader_default:\n                iconLoader = null;\n                break;\n            case R.id.sample_icon_loader_picasso:\n                if (picassoIconLoader == null) {\n                    picassoIconLoader = new PicassoIconLoader();\n                }\n                iconLoader = picassoIconLoader;\n                break;\n            case R.id.sample_icon_loader_glide:\n                if (glideIconLoader == null) {\n                    glideIconLoader = new GlideIconLoader();\n                }\n                iconLoader = picassoIconLoader;\n                break;\n            case R.id.sorting_default:\n                customComparatorProvider = null;\n                break;\n            case R.id.sorting_custom:\n                customComparatorProvider = new SocialTargetActivityComparatorProvider();\n                break;\n            default:\n                return super.onOptionsItemSelected(item);\n\n        }\n        item.setChecked(true);\n        return true;\n    }\n\n    @Override\n    public void onLearMoreRequested() {\n        Intent intent = new Intent(Intent.ACTION_VIEW);\n        intent.setData(Uri.parse(getString(R.string.article_url)));\n        startActivity(intent);\n    }\n\n    @Override\n    public void onAddExtraProviderRequested() {\n        ExtraProviderDialogFragment.newInstance().show(getSupportFragmentManager());\n    }\n\n    @Override\n    public void onDialogTitleChanged(String dialogTitle) {\n        this.dialogTitle = dialogTitle;\n    }\n\n    @Override\n    public void onSharedTextChanged(String sharedText) {\n        this.sharedText = sharedText;\n    }\n\n    @Override\n    public void onFacebookLinkChanged(String currentFacebookLink) {\n        this.facebookLink = Uri.parse(currentFacebookLink);\n    }\n\n    @Override\n    public void onTweetChanged(String currentTweet) {\n        this.tweet = currentTweet;\n    }\n\n    @Override\n    public void onMailSubjectChanged(String currentMailSubject) {\n        this.mailSubject = currentMailSubject;\n    }\n\n    @Override\n    public void onMailBodyChanged(String currentMailBody) {\n        this.mailBody = currentMailBody;\n    }\n\n    @Override\n    public void onExtraProviderDetailRequested(int wrapperPosition, ExtraProviderWrapper wrapper) {\n        ExtraProviderDialogFragment.newInstance(wrapperPosition, wrapper).show(getSupportFragmentManager());\n    }\n\n    @Override\n    public void onExtraProviderChanged(int position, ExtraProviderWrapper extraProviderWrapper) {\n        extraProviders.remove(position);\n        extraProviders.add(position, extraProviderWrapper);\n        adapter.notifyExtraProviderChanged(position);\n    }\n\n    @Override\n    public void onExtraProviderCreated(ExtraProviderWrapper extraProviderWrapper) {\n        extraProviders.add(extraProviderWrapper);\n        adapter.notifyExtraProviderInserted();\n    }\n\n\n    @Override\n    public void onClick(View v) {\n        IntentShare intentShare = IntentShare.with(MainActivity.this)\n                .chooserTitle(dialogTitle)\n                .text(sharedText)\n                .mailBody(mailBody)\n                .mailSubject(mailSubject)\n                .image(imageUri)\n                .facebookBody(facebookLink)\n                .twitterBody(tweet)\n                .listener(intentShareListener);\n        if (customComparatorProvider != null) {\n            intentShare.comparatorProvider(customComparatorProvider);\n        }\n        if (iconLoader != null) {\n            intentShare.iconLoader(iconLoader);\n        }\n        for (int i = 0; i < extraProviders.size(); i++) {\n            intentShare.addExtraProvider(extraProviders.get(i).getExtraProvider());\n        }\n        intentShare.deliver();\n    }\n\n    private void setUpRecyclerView() {\n        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.activity_main_recycler);\n        recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));\n        extraProviders = new ArrayList<>();\n\n        extraProviders.add(buildPocketProvider());\n        extraProviders.add(buildKeepProvider());\n\n        adapter = new Adapter(extraProviders);\n        adapter.setListener(this);\n        recyclerView.setHasFixedSize(false);\n        recyclerView.setAdapter(adapter);\n    }\n\n    /**\n     * Pocket only handle links.\n     *\n     * @return well instantiate provider.\n     */\n    private ExtraProviderWrapper buildPocketProvider() {\n        // pocket only handle link.\n        IntentShare.ExtraProvider provider\n                = new IntentShare.ExtraProvider(\"com.ideashower.readitlater.pro\")\n                .disableImage()\n                .disableSubject()\n                .overrideText(getString(R.string.article_url));\n        return new ExtraProviderWrapper(\"Pocket\", provider);\n    }\n\n    /**\n     * Keep can have a subject used as not title.\n     *\n     * @return well instantiate provider.\n     */\n    private ExtraProviderWrapper buildKeepProvider() {\n        // pocket only handle link.\n        IntentShare.ExtraProvider provider\n                = new IntentShare.ExtraProvider(\"com.google.android.keep\")\n                .overrideSubject(getString(R.string.article_title));\n        return new ExtraProviderWrapper(\"Google Keep\", provider);\n    }\n\n    private Uri getShareableUri(Context context, Bitmap bitmap) {\n        // Compress the drawingCache before saving and sharing.\n        final ByteArrayOutputStream bytes = new ByteArrayOutputStream();\n        bitmap.compress(Bitmap.CompressFormat.PNG, SHARED_IMAGE_QUALITY, bytes);\n\n        // Write the compressed bytes to a files\n        final File outputDirectory = new File(context.getFilesDir(), SHARED_DIRECTORY);\n        if (outputDirectory.isDirectory() || outputDirectory.mkdirs()) {\n            final File shareColorFile = new File(outputDirectory, SHARED_IMAGE_FILE);\n            try {\n                final FileOutputStream fo = new FileOutputStream(shareColorFile);\n                fo.write(bytes.toByteArray());\n                fo.close();\n\n                // Get the content uri.\n                return FileProvider.getUriForFile(context,\n                        FILE_PROVIDER_AUTHORITY, shareColorFile);\n\n            } catch (IOException e) {\n                Log.e(TAG, \"Fail to write bitmap inside the temp file.\");\n            }\n        } else {\n            Log.e(TAG, \"Fail to create temp file for bitmap sharing.\");\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "sample/src/main/java/fr/tvbarthel/intentsharesample/SharingFileProvider.java",
    "content": "package fr.tvbarthel.intentsharesample;\n\nimport android.database.Cursor;\nimport android.database.MatrixCursor;\nimport android.net.Uri;\nimport android.provider.MediaStore;\nimport android.support.v4.content.FileProvider;\n\n/**\n * A simple {@link FileProvider} that solves a bug with the com.android.mms application.\n * <p/>\n * http://androidxref.com/5.1.1_r6/xref/packages/apps/Mms/src/com/android/mms/ui/UriImage.java#546\n * <p/>\n * <p/>\n * When sharing an images with a content Uri, the com.android.mms application\n * tries to get the orientation of the image from the provider.\n * <p/>\n * This {@link FileProvider} is a very simple example that handle the query of {@link android.provider.MediaStore.Images.ImageColumns#ORIENTATION}\n * projection.\n * <p/>\n * <b>Note:</b> this {@link FileProvider} always returns '0' for the value of the orientation.\n * If your images do not have the same orientation, you should build your own logic.\n */\npublic class SharingFileProvider extends FileProvider {\n\n    @Override\n    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {\n        if (isMediaStoreOrientationProjection(projection)) {\n            return queryMediaStoreOrientation();\n        }\n\n        return super.query(uri, projection, selection, selectionArgs, sortOrder);\n    }\n\n    /**\n     * Check if a projection corresponds to a {@link android.provider.MediaStore.Images.ImageColumns#ORIENTATION} projection.\n     *\n     * @param projection the projection to check.\n     * @return Returns true is the given projection corresponds to {@link android.provider.MediaStore.Images.ImageColumns#ORIENTATION}, false otherwise.\n     */\n    private boolean isMediaStoreOrientationProjection(String[] projection) {\n        return projection != null && projection.length == 1 && MediaStore.Images.ImageColumns.ORIENTATION.equals(projection[0]);\n    }\n\n    /**\n     * Query the {@link android.provider.MediaStore.Images.ImageColumns#ORIENTATION}\n     *\n     * @return Returns a {@link Cursor} with {@link android.provider.MediaStore.Images.ImageColumns#ORIENTATION} set to 0.\n     */\n    private Cursor queryMediaStoreOrientation() {\n        String[] cols = new String[]{MediaStore.Images.ImageColumns.ORIENTATION};\n        Object[] values = new Object[]{0};\n\n        final MatrixCursor cursor = new MatrixCursor(cols, 1);\n        cursor.addRow(values);\n        return cursor;\n    }\n}\n"
  },
  {
    "path": "sample/src/main/java/fr/tvbarthel/intentsharesample/SocialTargetActivityComparatorProvider.java",
    "content": "package fr.tvbarthel.intentsharesample;\n\nimport android.os.Parcel;\n\nimport java.util.ArrayList;\nimport java.util.Comparator;\n\nimport fr.tvbarthel.intentshare.TargetActivity;\nimport fr.tvbarthel.intentshare.TargetActivityComparatorProvider;\n\n/**\n * Simple custom {@link TargetActivityComparatorProvider} used to illustrate how to provide\n * a different sorting for the target activities displayed to the user.\n * <p/>\n * This example simply displayed some social media apps at first and then keep the original\n * order returned by the system.\n */\nclass SocialTargetActivityComparatorProvider implements TargetActivityComparatorProvider {\n\n    private ArrayList<String> prioritizedPackageNames;\n\n    /**\n     * Parcelable.\n     */\n    public static final Creator<SocialTargetActivityComparatorProvider> CREATOR\n            = new Creator<SocialTargetActivityComparatorProvider>() {\n        @Override\n        public SocialTargetActivityComparatorProvider createFromParcel(Parcel source) {\n            return new SocialTargetActivityComparatorProvider(source);\n        }\n\n        @Override\n        public SocialTargetActivityComparatorProvider[] newArray(int size) {\n            return new SocialTargetActivityComparatorProvider[size];\n        }\n    };\n\n    /**\n     * Simple custom {@link TargetActivityComparatorProvider} used to illustrate how to provide\n     * a different sorting for the target activities displayed to the user.\n     * <p/>\n     * This example simply displayed some social media apps at first and then keep the original\n     * order returned by the system.\n     */\n    public SocialTargetActivityComparatorProvider() {\n        prioritizedPackageNames = new ArrayList<>();\n        prioritizedPackageNames.add(\"com.instagram.android\");         // instagram\n        prioritizedPackageNames.add(\"com.snapchat.android\");          // snapchat\n        prioritizedPackageNames.add(\"com.pinterest\");                 // pinterest\n        prioritizedPackageNames.add(\"com.sgiggle.production\");        // tango\n        prioritizedPackageNames.add(\"jom.tencent.mm\");                // wechat\n        prioritizedPackageNames.add(\"jp.naver.line.android\");         // line\n        prioritizedPackageNames.add(\"com.whatsapp\");                  // what's app\n        prioritizedPackageNames.add(\"com.google.android.talk\");       // hangout\n        prioritizedPackageNames.add(\"com.google.android.apps.plus\");  // G+\n        prioritizedPackageNames.add(\"com.twitter.android\");           // twitter\n        prioritizedPackageNames.add(\"com.facebook.orca\");             // FB\n        prioritizedPackageNames.add(\"com.facebook.katana\");           // FB\n    }\n\n    /**\n     * Simple custom {@link TargetActivityComparatorProvider} used to illustrate how to provide\n     * a different sorting for the target activities displayed to the user.\n     * <p/>\n     * This example simply displayed some social media apps at first and then keep the original\n     * order returned by the system.\n     *\n     * @param in parcel.\n     */\n    protected SocialTargetActivityComparatorProvider(Parcel in) {\n        prioritizedPackageNames = new ArrayList<>();\n        in.readStringList(prioritizedPackageNames);\n    }\n\n\n    @Override\n    public Comparator<TargetActivity> provideComparator() {\n        return new Comparator<TargetActivity>() {\n            @Override\n            public int compare(TargetActivity lhs, TargetActivity rhs) {\n                int lhsPriority = prioritizedPackageNames.indexOf(lhs.getPackageName());\n                int rhsPriority = prioritizedPackageNames.indexOf(rhs.getPackageName());\n                if (lhsPriority != -1 && rhsPriority != -1) {\n                    return lhsPriority - rhsPriority;\n                } else if (lhsPriority != -1) {\n                    return -1;\n                } else if (rhsPriority != -1) {\n                    return 1;\n                } else {\n                    return 0; // keep the original order if not present in the prioritized list.\n                }\n            }\n        };\n    }\n\n    @Override\n    public int describeContents() {\n        return 0;\n    }\n\n    @Override\n    public void writeToParcel(Parcel dest, int flags) {\n        dest.writeStringList(prioritizedPackageNames);\n    }\n}\n"
  },
  {
    "path": "sample/src/main/res/anim/wiggle.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shareInterpolator=\"false\">\n    <translate\n        android:duration=\"60\"\n        android:fromXDelta=\"-10\"\n        android:interpolator=\"@android:anim/accelerate_interpolator\"\n        android:repeatCount=\"3\"\n        android:repeatMode=\"reverse\"\n        android:toXDelta=\"10\" />\n\n    <translate\n        android:duration=\"60\"\n        android:fromXDelta=\"-20\"\n        android:interpolator=\"@android:anim/decelerate_interpolator\"\n        android:toXDelta=\"15\" />\n</set>"
  },
  {
    "path": "sample/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:layout_gravity=\"center\"\n    tools:context=\".MainActivity\">\n\n    <android.support.v7.widget.RecyclerView\n        android:id=\"@+id/activity_main_recycler\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:clipToPadding=\"false\"\n        android:paddingBottom=\"@dimen/fab_padding_safeness\" />\n\n    <android.support.design.widget.FloatingActionButton\n        android:id=\"@+id/activity_main_share_button\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"bottom|end\"\n        android:layout_marginBottom=\"@dimen/activity_vertical_margin\"\n        android:layout_marginRight=\"@dimen/activity_horizontal_margin\"\n        android:src=\"@drawable/ic_share\" />\n\n</FrameLayout>\n"
  },
  {
    "path": "sample/src/main/res/layout/extra_provider_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<merge xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <TextView\n        android:id=\"@+id/extra_provider_view_label\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:background=\"?attr/selectableItemBackground\"\n        android:gravity=\"center_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:text=\"App Name\" />\n\n</merge>"
  },
  {
    "path": "sample/src/main/res/layout/footer_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<merge xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <TextView\n        android:id=\"@+id/footer_view_add\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\"\n        android:background=\"?attr/selectableItemBackground\"\n        android:padding=\"@dimen/default_padding\"\n        android:text=\"@string/add_provider\"\n        android:textColor=\"@color/colorAccent\"\n        android:textSize=\"18sp\" />\n\n</merge>"
  },
  {
    "path": "sample/src/main/res/layout/fragment_dialog_extra_provider.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\">\n\n    <ScrollView\n        android:id=\"@+id/fragment_dialog_extra_provider_scroll\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginBottom=\"70dp\">\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"@dimen/activity_vertical_margin\"\n            android:orientation=\"vertical\"\n            android:padding=\"@dimen/default_padding\">\n\n\n            <android.support.design.widget.TextInputLayout\n                android:id=\"@+id/fragment_dialog_extra_provider_app_name_input\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_gravity=\"center\">\n\n                <EditText\n                    android:id=\"@+id/fragment_dialog_extra_provider_app_name\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:hint=\"@string/fragment_dialog_extra_provider_app_name_hint\"\n                    android:inputType=\"textPersonName\"\n                    android:nextFocusDown=\"@+id/fragment_dialog_extra_provider_package_name\"\n                    android:singleLine=\"true\" />\n\n            </android.support.design.widget.TextInputLayout>\n\n            <android.support.design.widget.TextInputLayout\n                android:id=\"@+id/fragment_dialog_extra_provider_package_name_input\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_gravity=\"center\"\n                android:layout_marginBottom=\"@dimen/activity_vertical_margin\">\n\n                <EditText\n                    android:id=\"@+id/fragment_dialog_extra_provider_package_name\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:hint=\"@string/fragment_dialog_extra_provider_package_name_hint\"\n                    android:inputType=\"textUri\"\n                    android:nextFocusDown=\"@+id/fragment_dialog_extra_provider_text\"\n                    android:singleLine=\"true\" />\n\n            </android.support.design.widget.TextInputLayout>\n\n            <TextView\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginTop=\"@dimen/activity_vertical_margin\"\n                android:text=\"@string/override\"\n                android:textSize=\"18sp\" />\n\n            <android.support.design.widget.TextInputLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_gravity=\"center\">\n\n                <EditText\n                    android:id=\"@+id/fragment_dialog_extra_provider_text\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:hint=\"@string/fragment_dialog_extra_provider_text_hint\"\n                    android:inputType=\"textMultiLine\"\n                    android:nextFocusDown=\"@+id/fragment_dialog_extra_provider_subject\" />\n\n            </android.support.design.widget.TextInputLayout>\n\n            <android.support.design.widget.TextInputLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_gravity=\"center\">\n\n                <EditText\n                    android:id=\"@+id/fragment_dialog_extra_provider_subject\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:hint=\"@string/fragment_dialog_extra_provider_subject_hint\"\n                    android:inputType=\"textMultiLine\"\n                    android:nextFocusDown=\"@+id/fragment_dialog_extra_provider_default_text_check\" />\n\n            </android.support.design.widget.TextInputLayout>\n\n            <TextView\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginBottom=\"@dimen/activity_vertical_margin\"\n                android:paddingTop=\"@dimen/default_padding\"\n                android:text=\"@string/image_override_warning\"\n                android:textSize=\"16sp\" />\n\n            <TextView\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginTop=\"@dimen/activity_vertical_margin\"\n                android:text=\"@string/disable\"\n                android:textSize=\"18sp\" />\n\n            <CheckBox\n                android:id=\"@+id/fragment_dialog_extra_provider_default_text_check\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"@string/default_text\" />\n\n            <CheckBox\n                android:id=\"@+id/fragment_dialog_extra_provider_default_subject_check\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"@string/default_subject\" />\n\n            <CheckBox\n                android:id=\"@+id/fragment_dialog_extra_provider_default_image_check\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"@string/default_image\" />\n\n        </LinearLayout>\n\n    </ScrollView>\n\n    <TextView\n        android:id=\"@+id/fragment_dialog_extra_provider_ok\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"bottom|end\"\n        android:layout_marginBottom=\"@dimen/activity_vertical_margin\"\n        android:layout_marginRight=\"@dimen/activity_horizontal_margin\"\n        android:background=\"?attr/selectableItemBackground\"\n        android:padding=\"@dimen/default_padding\"\n        android:text=\"@android:string/ok\"\n        android:textColor=\"@color/colorAccent\" />\n\n</FrameLayout>"
  },
  {
    "path": "sample/src/main/res/layout/header_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n\n    <TextView\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\"\n        android:gravity=\"center\"\n        android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n        android:paddingRight=\"@dimen/activity_horizontal_margin\"\n        android:paddingTop=\"@dimen/activity_vertical_margin\"\n        android:text=\"@string/app_name\"\n        android:textSize=\"24sp\" />\n\n    <TextView\n        android:id=\"@+id/main_header_view_learn_more_button\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\"\n        android:layout_marginBottom=\"@dimen/activity_vertical_margin\"\n        android:background=\"?attr/selectableItemBackground\"\n        android:gravity=\"center\"\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        android:text=\"@string/learn_more\"\n        android:textColor=\"@color/colorAccent\"\n        android:textSize=\"18sp\" />\n\n    <android.support.design.widget.TextInputLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\"\n        android:layout_marginBottom=\"@dimen/activity_vertical_margin\"\n        android:layout_marginTop=\"@dimen/activity_vertical_margin\">\n\n        <EditText\n            android:id=\"@+id/main_header_view_input_dialog_title\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:hint=\"@string/dialog_title\"\n            android:nextFocusDown=\"@+id/main_header_view_input_text\" />\n\n    </android.support.design.widget.TextInputLayout>\n\n    <TextView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginBottom=\"8dp\"\n        android:layout_marginTop=\"@dimen/activity_vertical_margin\"\n        android:text=\"@string/default_providers\"\n        android:textColor=\"@color/colorAccent\"\n        android:textSize=\"18sp\" />\n\n    <android.support.design.widget.TextInputLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\"\n        android:layout_marginBottom=\"@dimen/activity_vertical_margin\">\n\n        <EditText\n            android:id=\"@+id/main_header_view_input_text\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:hint=\"@string/shared_text\"\n            android:inputType=\"textMultiLine\" />\n\n    </android.support.design.widget.TextInputLayout>\n\n    <TextView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginBottom=\"8dp\"\n        android:text=\"@string/build_in_extra_providers\"\n        android:textColor=\"@color/colorAccent\"\n        android:textSize=\"18sp\" />\n\n    <android.support.design.widget.TextInputLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\"\n        android:layout_marginBottom=\"@dimen/activity_vertical_margin\">\n\n        <EditText\n            android:id=\"@+id/main_header_view_facebook\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:hint=\"@string/facebook_hint\"\n            android:inputType=\"textUri\"\n            android:singleLine=\"true\" />\n\n    </android.support.design.widget.TextInputLayout>\n\n    <android.support.design.widget.TextInputLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\"\n        android:layout_marginBottom=\"@dimen/activity_vertical_margin\">\n\n        <EditText\n            android:id=\"@+id/main_header_view_twitter\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:hint=\"@string/twitter_hint\"\n            android:inputType=\"textMultiLine\" />\n\n    </android.support.design.widget.TextInputLayout>\n\n    <android.support.design.widget.TextInputLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\">\n\n        <EditText\n            android:id=\"@+id/main_header_view_mail_subject\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:hint=\"@string/mail_subject_hint\"\n            android:inputType=\"text\"\n            android:singleLine=\"true\" />\n\n    </android.support.design.widget.TextInputLayout>\n\n    <android.support.design.widget.TextInputLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\"\n        android:layout_marginBottom=\"@dimen/activity_vertical_margin\">\n\n        <EditText\n            android:id=\"@+id/main_header_view_mail_body\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:hint=\"@string/mail_body_hint\"\n            android:inputType=\"textMultiLine\" />\n\n    </android.support.design.widget.TextInputLayout>\n\n    <TextView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"@string/custom_extra_providers\"\n        android:textColor=\"@color/colorAccent\"\n        android:textSize=\"18sp\" />\n\n</LinearLayout>"
  },
  {
    "path": "sample/src/main/res/menu/activity_sample_menu.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:title=\"@string/loader_menu\">\n        <menu>\n            <group\n                android:id=\"@+id/loader_group\"\n                android:checkableBehavior=\"single\">\n                <item\n                    android:id=\"@+id/sample_icon_loader_default\"\n                    android:checked=\"true\"\n                    android:title=\"@string/icon_loader_default\" />\n                <item\n                    android:id=\"@+id/sample_icon_loader_picasso\"\n                    android:title=\"@string/icon_loader_picasso\" />\n                <item\n                    android:id=\"@+id/sample_icon_loader_glide\"\n                    android:title=\"@string/icon_loader_glide\" />\n            </group>\n        </menu>\n    </item>\n    <item android:title=\"@string/sorting_menu\">\n        <menu>\n            <group\n                android:id=\"@+id/sorting_group\"\n                android:checkableBehavior=\"single\">\n                <item\n                    android:id=\"@+id/sorting_default\"\n                    android:checked=\"true\"\n                    android:title=\"@string/sorting_default\" />\n                <item\n                    android:id=\"@+id/sorting_custom\"\n                    android:title=\"@string/sorting_custom\" />\n            </group>\n        </menu>\n    </item>\n</menu>"
  },
  {
    "path": "sample/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#5a69c6</color>\n    <color name=\"colorPrimaryDark\">#5a69c6</color>\n    <color name=\"colorAccent\">#5a69c6</color>\n</resources>\n"
  },
  {
    "path": "sample/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\n    <!-- padding used at bottom of container to ensure nothing will be display under FAB when scroll to the end !-->\n    <dimen name=\"fab_padding_safeness\">80dp</dimen>\n    <dimen name=\"default_padding\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "sample/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">IntentShare Sample</string>\n    <string name=\"icon_loader_default\">Default IconLoader</string>\n    <string name=\"icon_loader_picasso\">Picasso IconLoader</string>\n    <string name=\"icon_loader_glide\">Glide IconLoader</string>\n    <string name=\"sorting_default\">Default Sorting (recency)</string>\n    <string name=\"sorting_custom\">Custom Sorting (social first)</string>\n\n    <string name=\"article_title\">Improves the sharing experience on Android with IntentShare.</string>\n    <string name=\"article_url\">http://tvbarthel.github.io/IntentShare/</string>\n    <string name=\"article_headline\">\"IntentShare is a light open-source library that improves the sharing experience on Android applications.</string>\n    <string name=\"article\">\"IntentShare is a light open-source library that improves the sharing experience on Android applications.\\n\\nNowadays, sharing content is part of our daily life. Unfortunately, the Android framework tools do not provide a sharing experience which reaches all of our expectations. We decided to implement our own tool, IntentShare, that might improve the user experience of a sharing action by:\\n\\n\\t • providing different extras according to the chosen target activity in order to take advantages of each target\\'s specificities.\\n\\n\\t • providing an easy way to track the selected target activities in order to improve/adapt the extras for a specific target.\\n\\n\\t • providing a sorted target activity list based on the context of your app in order to take advantages of how people use it.</string>\n    <string name=\"article_tweet\">Improves the sharing experience on Android with IntentShare. http://tvbarthel.github.io/IntentShare/ #android #sharing</string>\n    <string name=\"learn_more\">Learn more</string>\n    <string name=\"dialog_title\">Dialog Title</string>\n    <string name=\"shared_text\">Shared Text</string>\n    <string name=\"default_dialog_title\">Choose a target activity:</string>\n    <string name=\"default_shared_text\">@string/article_headline</string>\n    <string name=\"fragment_dialog_extra_provider_app_name_hint\">App name</string>\n    <string name=\"fragment_dialog_extra_provider_package_name_hint\">com.package.name</string>\n    <string name=\"fragment_dialog_extra_provider_text_hint\">overridden text</string>\n    <string name=\"fragment_dialog_extra_provider_subject_hint\">overridden subject</string>\n    <string name=\"disable\">Disable</string>\n    <string name=\"override\">Override</string>\n    <string name=\"default_text\">Disable text</string>\n    <string name=\"default_subject\">Disable subject</string>\n    <string name=\"default_image\">Disable image</string>\n    <string name=\"image_override_warning\">Overriding shared image not implemented yet in the sample.</string>\n    <string name=\"add_provider\">Add ExtraProvider</string>\n    <string name=\"build_in_extra_providers\">Build-in extra providers</string>\n    <string name=\"custom_extra_providers\">Custom extra providers</string>\n    <string name=\"facebook_hint\">Facebook link</string>\n    <string name=\"twitter_hint\">Tweet</string>\n    <string name=\"mail_subject_hint\">Mail subject</string>\n    <string name=\"mail_body_hint\">Mail body</string>\n    <string name=\"default_providers\">Default provider</string>\n    <string name=\"sorting_menu\">Target sorting</string>\n    <string name=\"loader_menu\">Icon loading</string>\n</resources>\n"
  },
  {
    "path": "sample/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</resources>\n"
  },
  {
    "path": "sample/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": "sample/src/main/res/xml/file_provider_paths.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<paths>\n    <files-path\n        name=\"sharing\"\n        path=\"sharing/\" />\n</paths>"
  },
  {
    "path": "sample/src/test/java/fr/tvbarthel/intentsharesample/ExampleUnitTest.java",
    "content": "package fr.tvbarthel.intentsharesample;\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 ':library', ':sample', ':picasso-loader', ':glide-loader'"
  }
]