{"id":17472359,"url":"https://github.com/pranavpandey/small-app-support","last_synced_at":"2026-02-21T17:03:45.670Z","repository":{"id":88144632,"uuid":"50910800","full_name":"pranavpandey/small-app-support","owner":"pranavpandey","description":"A library to build apps for Sony Small Apps extension.","archived":false,"fork":false,"pushed_at":"2025-03-05T19:55:40.000Z","size":11230,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-12T20:27:49.882Z","etag":null,"topics":["android","library","material-design","small-apps-extension","sony"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pranavpandey.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2016-02-02T09:52:37.000Z","updated_at":"2025-03-05T19:55:44.000Z","dependencies_parsed_at":null,"dependency_job_id":"dc7539e9-6005-48e1-be45-eea59389701c","html_url":"https://github.com/pranavpandey/small-app-support","commit_stats":{"total_commits":42,"total_committers":1,"mean_commits":42.0,"dds":0.0,"last_synced_commit":"93d0660176db8486b932af2431303c63115edc67"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pranavpandey%2Fsmall-app-support","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pranavpandey%2Fsmall-app-support/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pranavpandey%2Fsmall-app-support/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pranavpandey%2Fsmall-app-support/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pranavpandey","download_url":"https://codeload.github.com/pranavpandey/small-app-support/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249182755,"owners_count":21226118,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","library","material-design","small-apps-extension","sony"],"created_at":"2024-10-18T17:08:44.098Z","updated_at":"2026-02-21T17:03:40.649Z","avatar_url":"https://github.com/pranavpandey.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"./graphics/icon.png\" height=\"160\"\u003e\r\n\r\n# Small App Support\r\n\r\n[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?)](https://www.apache.org/licenses/LICENSE-2.0.html)\r\n\r\n\u003e [!WARNING]\r\n\u003e This is marked as `deprecated` as Sony no longer supports them.\r\n\r\n**A library to build apps for Sony Small Apps extension with native apps like functionality. I have divided it into different parts for easy understanding. As small app is a service, there were issues while displaying dialog from the small app. So, I have wrote a method to easily display dialog from a small app.**\r\n\r\n\u003e [!IMPORTANT]\r\n\u003e This library is a collection of such type of methods and classes to provide a better interface and development experience.\r\n\r\n\u003cp align=\"left\"\u003e\r\n  \u003cimg src=\"./graphics/screenshots/1.png\" width=\"280\" height=\"486\" hspace=\"2\"\u003e\r\n  \u003cimg src=\"./graphics/screenshots/2.png\" width=\"280\" height=\"486\" hspace=\"2\"\u003e\r\n\u003c/p\u003e\r\n\r\n\u003cp align=\"left\"\u003e\r\n  \u003cimg src=\"./graphics/screenshots/3.png\" width=\"280\" height=\"486\" hspace=\"2\"\u003e\r\n  \u003cimg src=\"./graphics/screenshots/4.png\" width=\"280\" height=\"486\" hspace=\"2\"\u003e\r\n\u003c/p\u003e\r\n\r\n\u003cp align=\"left\"\u003e\r\n  \u003cimg src=\"./graphics/screenshots/5.png\" width=\"280\" height=\"486\" hspace=\"2\"\u003e\r\n  \u003cimg src=\"./graphics/screenshots/6.png\" width=\"280\" height=\"486\" hspace=\"2\"\u003e\r\n\u003c/p\u003e\r\n\r\n---\r\n\r\n## Contents\r\n\r\n- [Setup](https://github.com/pranavpandey/small-app-support#setup)\r\n- [Usage](https://github.com/pranavpandey/small-app-support#usage)\r\n    - [Theme](https://github.com/pranavpandey/small-app-support#theme)\r\n        - [SmallTheme](https://github.com/pranavpandey/small-app-support#smalltheme)\r\n        - [DynamicTheme](https://github.com/pranavpandey/small-app-support#dynamictheme)\r\n    - [View](https://github.com/pranavpandey/small-app-support#view)\r\n        - [ColorAttributes](https://github.com/pranavpandey/small-app-support#colorattributes)\r\n        - [ColoredImageView](https://github.com/pranavpandey/small-app-support#coloredimageview)\r\n        - [PressedStateImageView](https://github.com/pranavpandey/small-app-support#pressedstateimageview)\r\n        - [ColoredTextView](https://github.com/pranavpandey/small-app-support#coloredtextview)\r\n        - [ColoredLinearLayout](https://github.com/pranavpandey/small-app-support#coloredlinearlayout)\r\n    - [Launcher](https://github.com/pranavpandey/small-app-support#launcher)\r\n        - [ShortcutLauncher](https://github.com/pranavpandey/small-app-support#shortcutlauncher)\r\n    - [SmallUtils](https://github.com/pranavpandey/small-app-support#smallutils)\r\n    - [Dialog](https://github.com/pranavpandey/small-app-support#dialog)\r\n        - [ActionDialog](https://github.com/pranavpandey/small-app-support#actiondialog)\r\n        - [OpenIntentDialog](https://github.com/pranavpandey/small-app-support#openintentdialog)\r\n    - [Runtime Permissions](https://github.com/pranavpandey/small-app-support#runtime-permissions)\r\n- [Apps using Small App Support](https://github.com/pranavpandey/small-app-support#apps-using-small-app-support)\r\n- [License](https://github.com/pranavpandey/small-app-support#license)\r\n\r\n---\r\n\r\n## Setup\r\n\r\n### Eclipse with ADT\r\n\r\nIt is an ADT project, import both `library` and `sample` in Eclipse. After that, follow the steps below.\r\n\r\n1. Project \u003e Clean \u003e Clean all projects.\r\n2. Right-click on `sample` \u003e Run As \u003e Android Application.\r\n3. Select emulator or connect the device with usb debugging on.\r\n\r\nRun the sample to see it in action.\r\n\r\n---\r\n\r\n## Usage\r\n\r\nRead the documentation below to know how you can make attractive small apps by using this library. It will also simplify the development process and please don't rely only on this guide, keep exploring the different classes to find some hidden functions. If there is any mistake or some important features are missing then, feel free to update it and send me the pull request so that I can update it.\r\n\r\n\u003e I have divided it into different parts for easy understanding. First we have to initialize the `SmallTheme` to make things working properly.\r\n\r\n### Theme\r\n\r\nThere is a base `SmallApp` class which you can extend to initialize the `SmallTheme` and it also has some useful functions and can handle configuration changes. After that you can use it to extract different colors from the theme by getting its instance.\r\n\r\n#### SmallTheme\r\n\r\n`SmallTheme` is a class to detect Primary and Accent colors from the theme. In ICS, it will return the theme accent color. It also has some other methods like `showHint(view, string)`, `showHeaderHint(view, string)` to show hints for footer and header menu items respectively.\r\n\r\n```java\r\npublic class SmallAppSample extends SmallApp {\r\n\r\n  @Override\r\n  protected int getLayoutId() {\r\n    return R.layout.main;\r\n  }\r\n\r\n  @Override\r\n  protected void onCreate() {\r\n    super.onCreate();\r\n    // Set title for the small app\r\n    setTitle(R.string.title);\r\n\r\n    // Set windows attributes\r\n    SmallAppWindow.Attributes attr = getWindow().getAttributes();\r\n    attr.minWidth = getResources().getDimensionPixelSize(R.dimen.min_width);\r\n    attr.minHeight = getResources().getDimensionPixelSize(R.dimen.min_height);\r\n    attr.width = getResources().getDimensionPixelSize(R.dimen.width);\r\n    attr.height = getResources().getDimensionPixelSize(R.dimen.height);\r\n\r\n    attr.flags |= SmallAppWindow.Attributes.FLAG_RESIZABLE;\r\n    getWindow().setAttributes(attr);\r\n\r\n    // Get base colors\r\n    @ColorInt int primaryColor = SmallTheme.getInstance().getPrimaryColor();\r\n    @ColorInt int accentColor = SmallTheme.getInstance().getAccentColor();\r\n\r\n    // Get tint colors so that it will always be visible on the base color\r\n    @ColorInt int tintPrimaryColor = SmallTheme.getInstance().getTintPrimaryColor();\r\n    @ColorInt int tintAccentColor = SmallTheme.getInstance().getTintAccentColor();\r\n\r\n    // Use other SmallApp methods\r\n\r\n    // Minimize the small app window\r\n    windowMinimize();\r\n\r\n    // Set small app window fitted to the screen\r\n    windowFitted();\r\n\r\n    // Set small app window to its general state\r\n    windowNormal();\r\n\r\n    // Setup header with option menu\r\n    View header = LayoutInflater.from(this).inflate(R.layout.header, new LinearLayout(this), false);\r\n\r\n    final View optionMenu = header.findViewById(R.id.option_menu);\r\n\r\n    // Show header hint\r\n    optionMenu.setOnLongClickListener(new View.OnLongClickListener() {\r\n      @Override\r\n      public boolean onLongClick(View v) {\r\n        SmallTheme.getInstance().showHeaderHint(v, R.string.sas_options);\r\n        return false;\r\n      }\r\n    });\r\n  }\r\n}\r\n```\r\n\r\nIf you don't want to extend `SmallApp` class then, you have to do the following modifications in your `SmallApplication` class.\r\n\r\n```java\r\npublic class SmallAppSample extends SmallApplication {\r\n\r\n  @Override\r\n  protected void onCreate() {\r\n    super.onCreate();\r\n\r\n    // Initialize SmallTheme instance.\r\n    SmallTheme.initializeInstance(getApplicationContext());\r\n\r\n    ...\r\n  }\r\n\r\n  @Override\r\n  protected void onDestroy() {\r\n    super.onDestroy();\r\n\r\n    // To avoid memory leaks and to initialize it properly next time.\r\n    SmallTheme.getInstance().onDestroy();\r\n\r\n    ...\r\n  }\r\n}\r\n```\r\n\r\n#### DynamicTheme\r\n\r\nIn theme, there is another useful class `DynamicTheme`. It is mostly used internally but you can also use its `static` methods to generate colors dynamically.\r\n\r\n```java\r\n// Calculate tint based on a given color for better readability\r\nDynamicTheme.getTintColor(color);\r\n\r\n/**\r\n * Calculate accent based on a given color for dynamic theme generation.\r\n * Still in beta so, sometimes may be inaccurate color.\r\n */\r\nDynamicTheme.getAccentColor(color);\r\n\r\n/**\r\n * Calculate contrast of a color based on the give base color so\r\n * that it will be visible always on top of the base color.\r\n */\r\nDynamicTheme.getContrastColor(color, contrastWith);\r\n\r\n/**\r\n * Colorize and return the mutated drawable so that, all other references\r\n * do not change.\r\n */\r\nDynamicTheme.colorizeDrawable(drawable, color);\r\n// OR\r\nDynamicTheme.colorizeDrawableRes(context, drawable, color);\r\n\r\n/**\r\n * Highlight the query text within a TextView. Suitable for notifying user about the\r\n * searched query found in the adapter. TextView should not be empty. Please set your\r\n * default text first then, highlight the query text by using this function.\r\n */\r\nDynamicTheme.highlightQueryTextColor(query, textView, color);\r\n// OR\r\nDynamicTheme.highlightQueryTextColorRes(query, textView, colorId);\r\n```\r\n\r\n---\r\n\r\n### View\r\n\r\nIt consists of different views by which you can easily change `TextView` color or can apply filter on a `ImageView` according to the colors extracted from the theme. Make sure to initialize `SmallTheme` first if you are not extending `SmallApp` class. You can make these views background aware so that their color will always be visible on the supplied background. If no background is supplied then, it will use the default background color i.e; `#FF1A1A1A`\r\n\r\nFollowing color attributes are available which you can use in the layout to colorize these views.\r\n\r\n#### ColorAttributes\r\n\r\n1. `colorType` - applies filter on image view or changes text color according to the following values.\r\n\r\n    0. `none` - no color will be applied to the view.\r\n    1. `primary` - extracted `colorPrimary` from the current theme.\r\n    2. `primary_dark` - extracted `colorPrimaryDark` from the current theme.\r\n    3. `accent` - extracted `colorAccent` from the current theme.\r\n    4. `accent_dark` - extracted `colorAccentDark` from the current theme.\r\n    5. `tint_primary` - calculated tint color based on the `colorPrimary`.\r\n    6. `tint_primary_dark` - calculated tint color based on the `colorPrimaryDark`.\r\n    7. `tint_accent` - calculated tint color based on the `colorAccent`.\r\n    8. `tint_accent_dark` - calculated tint color based on the `colorAccentDark`.\r\n\r\n2. `backgroundAware` - `true` if this view will change its color according to the background. It was introduced to provide better legibility for colored images and to avoid dark image on dark background like situations. If this boolean is set then, it will check for the contrast color and do color calculations according to that color so that this image view will always be visible on that background. If no contrast color is found then, it will take default background color.\r\n\r\n3. `contrastWith` - background color for this view so that it will remain in contrast with this color.\r\n\r\n4. `colorAlpha` - background alpha for this view ranging from 0 - 255.\r\n\r\n#### ColoredImageView\r\n\r\nAn `ImageView` to apply color filter according to the supplied color `colorType`.\r\n\r\n```xml\r\n\u003ccom.pranavpandey.smallapp.view.ColoredImageView\r\n    android:layout_width=\"wrap_content\"\r\n    android:layout_height=\"wrap_content\"\r\n    app:colorType=\"primary\"\r\n    app:backgroundAware=\"true\"\r\n    app:contrastWith=\"#FF2A2A2A\" /\u003e\r\n```\r\n\r\nIn the above example, it will automatically apply `colorPrimary` filter on the `ImageView`. As `backgroundAware` set to `true` and a `contrastWith` color is also supplied so, it will check that the applied filter will be visible on `#FF2A2A2A` background or not. If not or both the colors are dark then, it will calculate the tint or light version of the `colorPrimary` which will always be visible on that background and changes the color filter.\r\n\r\n#### PressedStateImageView\r\n\r\nAn ImageView which changes alpha on touch to show pressed state. It is extended from `ColoredImageView` to provide colorizing abilities whenever is required.\r\n\r\n```xml\r\n\u003ccom.pranavpandey.smallapp.view.PressedStateImageView\r\n    android:layout_width=\"wrap_content\"\r\n    android:layout_height=\"wrap_content\"\r\n    android:src=\"@drawable/icon\" /\u003e\r\n```\r\n\r\n#### ColoredTextView\r\n\r\nA TextView to change its color according to the supplied `colorType`.\r\n\r\n```xml\r\n\u003ccom.pranavpandey.smallapp.view.ColoredTextView\r\n    android:layout_width=\"wrap_content\"\r\n    android:layout_height=\"wrap_content\"\r\n    app:colorType=\"primary\"\r\n    app:backgroundAware=\"true\"\r\n    app:contrastWith=\"#FF2A2A2A\" /\u003e\r\n```\r\n\r\nIn the above example, it will automatically set the text color to `colorPrimary`. As `backgroundAware` set to `true` and a `contrastWith` color is also supplied so, it will check that the applied color will be visible on `#FF2A2A2A` background or not. If not or both the colors are dark then, it will calculate the tint or light version of the `colorPrimary` which will always be visible on that background and changes the text color.\r\n\r\n#### ColoredLinearLayout\r\n\r\nA LinearLayout to change background according to the supplied `colorType`.\r\n\r\n```xml\r\n\u003ccom.pranavpandey.smallapp.view.ColoredLinearLayout\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"wrap_content\"\r\n    android:orientation=\"vertical\"\r\n    app:colorType=\"primary\"\r\n    app:colorAlpha=\"200\" /\u003e\r\n```\r\n\r\nIn the above example, it will automatically set the background color to `colorPrimary`. As `colorAlpha` is set to 200 so, it will also change the `argb` color alpha component to 200.\r\n\r\n\u003e All the views has getters and setters for these attributes to change them at runtime.\r\n\r\n```java\r\n// Setters\r\n\r\n// ColoredImageView\r\nColoredImageView.setColorType(colorType);\r\nColoredImageView.setBackgroundAware(boolean);\r\nColoredImageView.setContrastWith(color);\r\n\r\n// ColoredTextView\r\nColoredTextView.setColorType(colorType);\r\nColoredTextView.setBackgroundAware(boolean);\r\nColoredTextView.setContrastWith(color);\r\n\r\n// ColoredLinearLayout\r\nColoredLinearLayout.setColorType(colorType);\r\nColoredLinearLayout.setColorAlpha(int);\r\n\r\n\r\n// Getters\r\n\r\n// ColoredImageView\r\nColoredImageView.getColorType();\r\nColoredImageView.isBackgroundAware();\r\nColoredImageView.getContrastWith();\r\n\r\n// ColoredTextView\r\nColoredTextView.getColorType();\r\nColoredTextView.isBackgroundAware();\r\nColoredTextView.getContrastWith();\r\n\r\n// ColoredLinearLayout\r\nColoredLinearLayout.getColorType();\r\nColoredLinearLayout.getColorAlpha();\r\n```\r\n\r\n---\r\n\r\n### Launcher\r\n\r\nA set of class with collection of helper functions and constants to make launching of small app easier and from anywhere.\r\n\r\n#### ShortcutLauncher\r\n\r\nAn abstract activity to launch small app shortcuts form anywhere. Extend it in your project and override `getShortcutPackage()` method to pass a package name. You can also start the activity with an intent extra containing the package name and can extract that package name in this method. Rest of the things will be handle by the `SmallLauncher`.\r\n\r\n```java\r\n// Start activity with an intent extra.\r\nIntent intent = new Intent(context, ShortcutActivity.class);\r\nintent.putExtra(ShortcutLauncher.PACKAGE_NAME, \"com.pranavpandey.smallapp.sample\");\r\nstartActivity(intent);\r\n\r\n...\r\n\r\n// Extend ShortcutLauncher to launch small app.\r\npublic class ShortcutActivity extends ShortcutLauncher {\r\n\r\n  /**\r\n   * Override this function and pass a package name or\r\n   * start this activity with the intent.\r\n   */\r\n  @Override\r\n  protected String getShortcutPackage() {\r\n    return \"com.pranavpandey.smallapp.sample\";\r\n\r\n    // OR\r\n    return getIntent().getStringExtra(ShortcutLauncher.PACKAGE_NAME);\r\n  }\r\n}\r\n```\r\n\r\n---\r\n\r\n### SmallUtils\r\n\r\nThere were always be a problem while displaying dialog from a small app as it is derived from the `Service`. But by doing some modifications we can do it easily. `SmallUtils` is a collection of such useful functions. It also has other methods to save settings in `SharedPreferences`.\r\n\r\n```java\r\n// Create simple alert dialog .\r\nAlertDialog.Builder builder = new AlertDialog.Builder(context);\r\nbuilder.setTitle(R.string.sas_about);\r\nbuilder.setPositiveButton(android.R.string.ok, null);\r\n\r\n/**\r\n * Use SmallUtils to display it from a small app.\r\n * Pass the window token of your root view. A parent view of which you\r\n * want to attach the dialog.\r\n */\r\nSmallUtils.createDialog(builder.create(), getRootView().getWindowToken());\r\n\r\n// Save values in SharedPreferences.\r\n\r\n// Save integer value\r\nSmallUtils.savePrefs(context, \"Key\", int);\r\n// Save boolean value\r\nSmallUtils.savePrefs(context, \"Key\", boolean);\r\n// Save String value\r\nSmallUtils.savePrefs(context, \"Key\", string);\r\n\r\n\r\n// Load values from SharedPreferences.\r\n\r\n// Load integer preference. If not found then, return defaultInt.\r\nSmallUtils.loadPrefs(context, \"Key\", defaultInt);\r\n// Load boolean preference. If not found then, return defaultBoolean.\r\nSmallUtils.loadPrefs(context, \"Key\", defaultBooelan);\r\n// Load String preference. If not found then, return defaultString.\r\nSmallUtils.loadPrefs(context, \"Key\", defaultString);\r\n```\r\n\r\n---\r\n\r\n### Dialog\r\n\r\nThere are some in-built `Dialogs` so you don't have to write your own. You can use them to show options on long press or if you want to open some links, files, etc. It has an intent app picker which can also remember the user choices so they don't need to choose the app next time. Read below to know about their usage.\r\n\r\n#### ActionDialog\r\n\r\nA class which creates a dialog to show different actions to perform various operations by using an adapter containing all the actions which will be displayed either in a `List`or `Grid`. You can use `BaseActionItemAdapter` or any other custom adapter according to your need. Set a click listener to dispatch click events so that you can perform actions.\r\n\r\n\u003e You can set extra info to display as header of `List` or `Grid` which is also clickable.\r\n\r\n```java\r\n// Initialize list\r\nArrayList\u003cBaseActionItem\u003e actionList  = new ArrayList\u003cBaseActionItem\u003e();\r\n\r\n// Add actions into the list.\r\nactionList.add(new BaseActionItem(actionId, nameId, drawableId, isColorizable));\r\nactionList.add(new BaseActionItem(actionId, nameId, drawableId, isColorizable));\r\n\r\n// Configure dialog builder.\r\nAlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);\r\nalertDialogBuilder.setTitle(string);\r\nalertDialogBuilder.setNegativeButton(android.R.string.cancel, null);\r\n\r\n// Initialize ActionDialog and pass the builder.\r\nActionDialog actionDialog = new ActionDialog(context, alertDialogBuilder, Type.GRID);\r\n\r\n// Set actions adapter.\r\nactionDialog.setAdapter(new BaseActionItemAdapter(context, actionList, R.layout.sas_item_grid_action),\r\n  new OnActionItemClickListener() {\r\n    public void onActionItemClick(DialogInterface dialog, Adapter adapter,\r\n      AdapterView\u003c?\u003e parent, View view, int position, long id) {\r\n        int actionId =  ((BaseActionItem) adapter.getItem(position)).getActionId();\r\n\r\n        switch (actionId) {\r\n          // handle action item click events.\r\n        }\r\n      }\r\n    }\r\n  }\r\n)\r\n// Set extra info to be displayed in the header of list or grid.\r\n.setExtraInfo(drawableId, textString, new OnExtraInfoClickListener() {\r\n  public void onExtraInfoClick(View v) {\r\n    // handle click event.\r\n  }\r\n})\r\n// Show the action dialog.\r\n.show(getRootView());\r\n```\r\n\r\n#### OpenIntentDialog\r\n\r\nA class which creates a dialog to show all the activities available to handle the supplied intent. It is a solution to handle no activity found exception and you can do some other work if this exception occurs. It extends the `ActionDialog` class so that you can use its functions also.\r\n\r\n```java\r\n// Create intent.\r\nIntent intent = new Intent(Intent.ACTION_SEND);\r\nintent.setType(\"application/*\");\r\nintent.putExtra(Intent.EXTRA_SUBJECT, appName);\r\nintent.putExtra(Intent.EXTRA_BCC, \"\");\r\nintent.putExtra(Intent.EXTRA_TEXT, appName + \"\\n\"\r\n        + \"http://play.google.com/store/apps/details?id=\" + packageName);\r\n\r\n// Configure dialog builder.\r\nAlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context)\r\n.setTitle(R.string.share)\r\n.setNegativeButton(android.R.string.cancel, null);\r\n\r\n// Show open intent dialog.\r\nnew OpenIntentDialog(context, intent, alertDialogBuilder, Type.GRID)\r\n.setActivityOpenListener(new OnActivityOpenListener() {\r\n  @Override\r\n  public void onActivityOpen(ComponentName componentName) {\r\n    // handle activity open event.\r\n  }\r\n})\r\n/**\r\n * true if remember user selection to open same intent\r\n * with the same app next time.\r\n */\r\n.setRememberSelection(boolean)\r\n/**\r\n * Set extra info to be displayed in the header of list or grid.\r\n * Pass null to make header not clickable.\r\n */\r\n.setExtraInfo(drawableId, shareString, null)\r\n.show(getRootView());\r\n```\r\n\r\nIt will show a list of all the apps that can handle this intent. Select one of them, to open the intent. If `setRememberSelection(true)` then, it will show a checkbox to the users so that they can remember their selection for this intent.\r\n\r\n\u003e You can clear the user selection and all the associated apps by using the `Associations` class.\r\n\r\n```java\r\n/**\r\n * Clear all the associated apps.\r\n * Pass true to show a toast message and notify user.\r\n */\r\n(new Associations(context)).getHelper().clearAll(true);\r\n```\r\n\r\n---\r\n\r\n### Runtime Permissions\r\n\r\nYou can ask to grant permissions at runtime which was introduced in [Android M](https://developer.android.com/training/permissions/requesting.html). This feature is still in `beta` but it works well with most of the [dangerous permissions](https://developer.android.com/guide/topics/security/permissions.html#normal-dangerous).\r\n\r\nTo ask permissions at runtime, just override `getPermissions()` function of `SmallApp` class and pass all the permissions in an array. It will automatically asks user to grant all the permissions otherwise, app will not open. This is not a limitation as it is very difficult to make it more dynamic due to `SmallApplication` behavior. Still, you can do experiments to improve it according to your need.\r\n\r\n```java\r\npublic class SmallAppSample extends SmallApp {\r\n\r\n  ...\r\n\r\n  /**\r\n   * Ask for all dangerous permissions here.\r\n   */\r\n  @Override\r\n  protected String[] getPermissions() {\r\n    return new String[] { Manifest.permission.CAMERA,\r\n      Manifest.permission.READ_EXTERNAL_STORAGE,\r\n      Manifest.permission.WRITE_EXTERNAL_STORAGE };\r\n  }\r\n\r\n  /**\r\n   * Separate function for special kind of permissions.\r\n   */\r\n  @Override\r\n  protected boolean writeSystemSettings() {\r\n    return true;\r\n  }\r\n\r\n  ...\r\n}\r\n```\r\n\r\nAfter that add these activities in your project `AndroidManifest.xml` so that they can request permissions.\r\n\r\n```xml\r\n\u003cmanifest\r\n  ...\u003e\r\n\r\n  ...\r\n\r\n  \u003capplication\r\n    ...\u003e\r\n\r\n    \u003cactivity\r\n      android:name=\"com.pranavpandey.smallapp.permission.PermissionDangerous\"\r\n      android:exported=\"true\"\r\n      android:theme=\"@style/AppTheme.Transparent\"\r\n      android:configChanges=\"orientation|keyboardHidden|screenSize\"\r\n      android:stateNotNeeded=\"true\"\r\n      android:excludeFromRecents=\"true\"\r\n      android:screenOrientation=\"behind\" /\u003e\r\n\r\n    \u003cactivity\r\n      android:name=\"com.pranavpandey.smallapp.permission.PermissionWriteSystemSettings\"\r\n      android:exported=\"true\"\r\n      android:theme=\"@style/AppTheme.Transparent\"\r\n      android:configChanges=\"orientation|keyboardHidden|screenSize\"\r\n      android:stateNotNeeded=\"true\"\r\n      android:excludeFromRecents=\"true\"\r\n      android:screenOrientation=\"behind\" /\u003e\r\n\r\n  \u003c/application\u003e\r\n\r\n  ...\r\n\r\n\u003c/manifest\u003e\r\n```\r\n\r\n---\r\n\r\n## Apps using Small App Support\r\n\r\nAll of my small apps are built with this library. You can download them via Google Play. Please email me if you are using this library and want to feature your small app here.\r\n\r\n\u003cp align=\"left\"\u003e\r\n  \u003cimg src=\"./graphics/apps/pranavpandey-stopwatch.png\" width=\"140\" hspace=\"2\"\u003e\r\n  \u003cimg src=\"./graphics/apps/pranavpandey-torch.png\" width=\"140\" hspace=\"2\"\u003e\r\n  \u003cimg src=\"./graphics/apps/pranavpandey-launcher.png\" width=\"140\" hspace=\"2\"\u003e\r\n  \u003cimg src=\"./graphics/apps/pranavpandey-phone.png\" width=\"140\" hspace=\"2\"\u003e\r\n  \u003cimg src=\"./graphics/apps/pranavpandey-rotation.png\" width=\"140\" hspace=\"2\"\u003e\r\n  \u003cimg src=\"./graphics/apps/pranavpandey-files.png\" width=\"140\" hspace=\"2\"\u003e\r\n  \u003cimg src=\"./graphics/apps/pranavpandey-lock.png\" width=\"140\" hspace=\"2\"\u003e\r\n\u003c/p\u003e\r\n\r\n- [Stopwatch](https://play.google.com/store/apps/details?id=com.pranavpandey.smallapp.stopwatch)\r\n- [Torch](https://play.google.com/store/apps/details?id=com.pranavpandey.smallapp.torch.lite)\r\n- [Launcher](https://play.google.com/store/apps/details?id=com.pranavpandey.smallapp.launcher)\r\n- [Phone](https://play.google.com/store/apps/details?id=com.pranavpandey.smallapp.phone)\r\n- [Rotation](https://play.google.com/store/apps/details?id=pranavpandey.smallapp.rotation)\r\n- [Files](https://play.google.com/store/apps/details?id=com.pranavpandey.smallapp.files.lite)\r\n- [Lock](https://play.google.com/store/apps/details?id=com.pranavpandey.smallapp.lock)\r\n\r\n---\r\n\r\n## License\r\n\r\n    Copyright 2016 Pranav Pandey\r\n\r\n    Licensed under the Apache License, Version 2.0 (the \"License\");\r\n    you may not use this file except in compliance with the License.\r\n    You may obtain a copy of the License at\r\n\r\n       http://www.apache.org/licenses/LICENSE-2.0\r\n\r\n    Unless required by applicable law or agreed to in writing, software\r\n    distributed under the License is distributed on an \"AS IS\" BASIS,\r\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n    See the License for the specific language governing permissions and\r\n    limitations under the License.\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpranavpandey%2Fsmall-app-support","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpranavpandey%2Fsmall-app-support","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpranavpandey%2Fsmall-app-support/lists"}