[LIBRARY][GUIDE] DynamicShareActionProvider

Search This thread

nikwen

Senior Member
Feb 1, 2013
3,142
1,597
Berlin, Germany
www.nikwen.de
[LIBRARY][GUIDE] DynamicShareActionProvider

Some time ago I had a conversation with @SimplicityApks about Google's ShareActionProvider. We found out that it's not flexible enough as it doesn't allow dynamic generation of the data which should be shared.

So here I release my open-source DynamicShareActionProvider library. Its code can be found on Github.

The differences:

  • Sharing is done dynamically now!
    This means that your app specifies the type of the shared data first and generates the data when an app is chosen for sharing. No more need to define what to share when the Activity is created. The content can now be set dynamically. :)
    There are two types of listeners so that you can also generate the data in an AsyncTask.

  • There is no app icon of the most often used app appearing next to the share icon.
    Other icons often do not match the app theme.

  • The shown app list is not limited to three apps and a "See all" entry first.
    Why should the user not see all apps for that action?

  • You can adjust/must set the icon manually.
    Don't worry. ;)

Screenshots:

screenshot_1_resized.png
screenshot_2_resized.png


(The second screenshot is from the app FunctionCapture by @SimplicityApks)


Big thanks to:

This was featured on the XDA portal on December 20, 2013. :D
 
Last edited:

nikwen

Senior Member
Feb 1, 2013
3,142
1,597
Berlin, Germany
www.nikwen.de
[GUIDE] Adding this to your app

As indicated in the first post, the implementation is a little bit different than with Google's ShareActionProvider.
I assume that you are using Google's ActionBarCompat library.

Add the ActionBarCompat and the DynamicShareActionProvider library to your project first.

Afterwards, there are two ways of sharing your data using the DynamicShareActionProvider:

  • You can pass the data to the library when an app is selected and it will do the sharing part.
  • Or the library gives you an Intent which you just need to add the data to. This allows using an AsyncTask for data generation.

Adding the provider to the menu file

The first steps are the same for both ways. Add this to your menu resource file:

Code:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:library="http://schemas.android.com/apk/res-auto">

    <item android:id="@+id/menu_item_share"
          library:showAsAction="always"
          android:title="Share"
          android:icon="@drawable/abc_ic_menu_share_holo_dark"
          library:actionProviderClass="de.nikwen.dynamicshareactionprovider.library.DynamicShareActionProvider" />

    <!-- Your other entries here -->

</menu>

I saved the menu file as "res/menu/main.xml".

What's different from Google's Provider here, is that you need to set the icon for the menu entry. That shouldn't be a problem though because we can use the one from the ActionBarCompat library.

Then inflate the menu resource in the onCreateOptionsMenu() method of your Activity and get the provider from the menu:

Code:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);

    DynamicShareActionProvider provider = (DynamicShareActionProvider) MenuItemCompat.getActionProvider(menu.findItem(R.id.menu_item_share));

    return true;
}

Set the data type

To be able to filter your installed apps for those that can handle the data which should be shared, the provider needs to know which type of data you want to share. Set it like this:

Code:
provider.setShareDataType("text/plain");
(Add this to your onCreateOptionsMenu() method.)

Two different types of listeners

Now you need to choose the way you want to do the sharing:

  • If the generation of the data which should be shared takes much time so that you want to use an AsyncTask or a Service for that, use the DynamicShareActionProvider.OnShareLaterListener.
  • Otherwise use the DynamicShareActionProvider.OnShareIntentUpdateListener.


Using the OnShareIntentUpdateListener - Let the library do the sharing for you

Set the listener using the setOnShareIntentUpdateListener() method:

Code:
provider.setOnShareIntentUpdateListener(new DynamicShareActionProvider.OnShareIntentUpdateListener() {

    @Override
    public Bundle onShareIntentExtrasUpdate() {
        Bundle extras = new Bundle();
        
        //Generate your data here and add it to the Bundle
        
        return extras;
    }

});
(Add this to your onCreateOptionsMenu() method as well.)

We override the onShareIntentExtrasUpdate() method here and pass a Bundle as the return value. The data you add to the bundle should have the same format that you would use, if you added it to the Intent directly using the Intent#putExtras(Bundle extras) method (that's what is used internally).

This is an example for passing the data from an EditText:

Code:
@Override
public Bundle onShareIntentExtrasUpdate() {
    Bundle extras = new Bundle();
    EditText shareEdit = (EditText) findViewById(R.id.share_edit);
    extras.putString(android.content.Intent.EXTRA_TEXT, shareEdit.getText().toString());
    return extras;
}

You're done. :)

Using the OnShareLaterListener - Do the sharing yourself

This time we override the onShareClick() method of the OnShareLaterListener:

Code:
provider.setOnShareLaterListener(new DynamicShareActionProvider.OnShareLaterListener() {

    @Override
    public void onShareClick(Intent shareIntent) {
        MyShareAsyncTask task = new MyShareAsyncTask();
        task.execute(shareIntent);
    }

});

We get the share Intent as an argument and don't have to pass a return value. Instead, we have to do the sharing part manually.

The example code uses an AsyncTask for that:

Code:
private class MyShareAsyncTask extends AsyncTask<Intent, Void, Intent> {

    @Override
    protected void onPreExecute() {
        Toast.makeText(MainActivity.this, R.string.asynctask, Toast.LENGTH_LONG).show();
    }

    @Override
    protected Intent doInBackground(Intent... intents) {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        EditText shareEdit = (EditText) findViewById(R.id.share_edit);
        intents[0].putExtra(android.content.Intent.EXTRA_TEXT, "Shared from an AsyncTask: " + shareEdit.getText().toString());

        return intents[0];
    }

    @Override
    protected void onPostExecute(Intent intent) {
        startActivity(intent);
    }

}

However, you're free to do it the way you like. ;)

You're done. :)
 
Last edited:

Masrepus

Senior Member
Feb 12, 2013
767
99
Hey congrats for the portal post about ur lib :)
:good:

---------------------------------
Phone : Samsung Galaxy Mini S5570
OS:
•AOSP ICS Touchwiz V5 by A_U
•Android 4.0.4
•Baseband XWKS2
•Kernel: 2.6.37.6 Badass v1.9 by alin.p
•Recovery CWM v4.0.0.5
Mods:
PureAudio, Mounts2SD, ODEX through Universal ODEX script, AdBlock by AdAway
---------------------------------

Gesendet von Tapatalk
 
  • Like
Reactions: nikwen

nikwen

Senior Member
Feb 1, 2013
3,142
1,597
Berlin, Germany
www.nikwen.de
Hey congrats for the portal post about ur lib :)
:good:

---------------------------------
Phone : Samsung Galaxy Mini S5570
OS:
•AOSP ICS Touchwiz V5 by A_U
•Android 4.0.4
•Baseband XWKS2
•Kernel: 2.6.37.6 Badass v1.9 by alin.p
•Recovery CWM v4.0.0.5
Mods:
PureAudio, Mounts2SD, ODEX through Universal ODEX script, AdBlock by AdAway
---------------------------------

Gesendet von Tapatalk

Very nice for us devs! Thanks, I will look where to implement this :)

Big thanks to both of you. :)
 

nikwen

Senior Member
Feb 1, 2013
3,142
1,597
Berlin, Germany
www.nikwen.de
Just pushed an update to the library which adds support for ActionBarSherlock and the native ActionBar. I haven't changed the readme-file yet as I'm currently looking for someone to test those versions in his app. Would be great if someone (maybe you?) did it. :)

If you're interested in the update, have a look at the issue on Github: Issue #2
 
  • Like
Reactions: SimplicityApks

Top Liked Posts

  • There are no posts matching your filters.
  • 9
    [LIBRARY][GUIDE] DynamicShareActionProvider

    Some time ago I had a conversation with @SimplicityApks about Google's ShareActionProvider. We found out that it's not flexible enough as it doesn't allow dynamic generation of the data which should be shared.

    So here I release my open-source DynamicShareActionProvider library. Its code can be found on Github.

    The differences:

    • Sharing is done dynamically now!
      This means that your app specifies the type of the shared data first and generates the data when an app is chosen for sharing. No more need to define what to share when the Activity is created. The content can now be set dynamically. :)
      There are two types of listeners so that you can also generate the data in an AsyncTask.

    • There is no app icon of the most often used app appearing next to the share icon.
      Other icons often do not match the app theme.

    • The shown app list is not limited to three apps and a "See all" entry first.
      Why should the user not see all apps for that action?

    • You can adjust/must set the icon manually.
      Don't worry. ;)

    Screenshots:

    screenshot_1_resized.png
    screenshot_2_resized.png


    (The second screenshot is from the app FunctionCapture by @SimplicityApks)


    Big thanks to:

    This was featured on the XDA portal on December 20, 2013. :D
    2
    [GUIDE] Adding this to your app

    As indicated in the first post, the implementation is a little bit different than with Google's ShareActionProvider.
    I assume that you are using Google's ActionBarCompat library.

    Add the ActionBarCompat and the DynamicShareActionProvider library to your project first.

    Afterwards, there are two ways of sharing your data using the DynamicShareActionProvider:

    • You can pass the data to the library when an app is selected and it will do the sharing part.
    • Or the library gives you an Intent which you just need to add the data to. This allows using an AsyncTask for data generation.

    Adding the provider to the menu file

    The first steps are the same for both ways. Add this to your menu resource file:

    Code:
    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:library="http://schemas.android.com/apk/res-auto">
    
        <item android:id="@+id/menu_item_share"
              library:showAsAction="always"
              android:title="Share"
              android:icon="@drawable/abc_ic_menu_share_holo_dark"
              library:actionProviderClass="de.nikwen.dynamicshareactionprovider.library.DynamicShareActionProvider" />
    
        <!-- Your other entries here -->
    
    </menu>

    I saved the menu file as "res/menu/main.xml".

    What's different from Google's Provider here, is that you need to set the icon for the menu entry. That shouldn't be a problem though because we can use the one from the ActionBarCompat library.

    Then inflate the menu resource in the onCreateOptionsMenu() method of your Activity and get the provider from the menu:

    Code:
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
    
        DynamicShareActionProvider provider = (DynamicShareActionProvider) MenuItemCompat.getActionProvider(menu.findItem(R.id.menu_item_share));
    
        return true;
    }

    Set the data type

    To be able to filter your installed apps for those that can handle the data which should be shared, the provider needs to know which type of data you want to share. Set it like this:

    Code:
    provider.setShareDataType("text/plain");
    (Add this to your onCreateOptionsMenu() method.)

    Two different types of listeners

    Now you need to choose the way you want to do the sharing:

    • If the generation of the data which should be shared takes much time so that you want to use an AsyncTask or a Service for that, use the DynamicShareActionProvider.OnShareLaterListener.
    • Otherwise use the DynamicShareActionProvider.OnShareIntentUpdateListener.


    Using the OnShareIntentUpdateListener - Let the library do the sharing for you

    Set the listener using the setOnShareIntentUpdateListener() method:

    Code:
    provider.setOnShareIntentUpdateListener(new DynamicShareActionProvider.OnShareIntentUpdateListener() {
    
        @Override
        public Bundle onShareIntentExtrasUpdate() {
            Bundle extras = new Bundle();
            
            //Generate your data here and add it to the Bundle
            
            return extras;
        }
    
    });
    (Add this to your onCreateOptionsMenu() method as well.)

    We override the onShareIntentExtrasUpdate() method here and pass a Bundle as the return value. The data you add to the bundle should have the same format that you would use, if you added it to the Intent directly using the Intent#putExtras(Bundle extras) method (that's what is used internally).

    This is an example for passing the data from an EditText:

    Code:
    @Override
    public Bundle onShareIntentExtrasUpdate() {
        Bundle extras = new Bundle();
        EditText shareEdit = (EditText) findViewById(R.id.share_edit);
        extras.putString(android.content.Intent.EXTRA_TEXT, shareEdit.getText().toString());
        return extras;
    }

    You're done. :)

    Using the OnShareLaterListener - Do the sharing yourself

    This time we override the onShareClick() method of the OnShareLaterListener:

    Code:
    provider.setOnShareLaterListener(new DynamicShareActionProvider.OnShareLaterListener() {
    
        @Override
        public void onShareClick(Intent shareIntent) {
            MyShareAsyncTask task = new MyShareAsyncTask();
            task.execute(shareIntent);
        }
    
    });

    We get the share Intent as an argument and don't have to pass a return value. Instead, we have to do the sharing part manually.

    The example code uses an AsyncTask for that:

    Code:
    private class MyShareAsyncTask extends AsyncTask<Intent, Void, Intent> {
    
        @Override
        protected void onPreExecute() {
            Toast.makeText(MainActivity.this, R.string.asynctask, Toast.LENGTH_LONG).show();
        }
    
        @Override
        protected Intent doInBackground(Intent... intents) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            EditText shareEdit = (EditText) findViewById(R.id.share_edit);
            intents[0].putExtra(android.content.Intent.EXTRA_TEXT, "Shared from an AsyncTask: " + shareEdit.getText().toString());
    
            return intents[0];
        }
    
        @Override
        protected void onPostExecute(Intent intent) {
            startActivity(intent);
        }
    
    }

    However, you're free to do it the way you like. ;)

    You're done. :)
    1
    Get the sample code

    It's on Github: Link to the sample code :)

    Other stuff

    See (and maybe share) my Google Plus post on the library.

    Let me know if you add this to your app. I will really appreciate it. :)
    1
    Well, it's time to say thank you again^^, without your lib sharing in my app wouldn't be nearly as useful... Thanks soo much! :good:
    1
    Well, it's time to say thank you again^^, without your lib sharing in my app wouldn't be nearly as useful... Thanks soo much! :good:

    Thank you very much for the compliments. :)
    And welcome. ;)