Adding an Easy Share Action in Android

Implementing an effective and user friendly share action in yourActionBar is made even easier with the introduction ofActionProvider in Android 4.0 (API Level 14). AnActionProvider, once attached to a menu item in the action bar, handles both the appearance and behavior of that item. In the case of ShareActionProvider, you provide a share intent and it does the rest.

Note:  ShareActionProvider is available starting with API Level 14 and higher.

Figure 1. TheShareActionProvider in the Gallery app.

Update Menu Declarations


To get started with ShareActionProviders, define theandroid:actionProviderClass attribute for the corresponding <item> in your menu resource file:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
            android:id="@+id/menu_item_share"
            android:showAsAction="ifRoom"
            android:title="Share"
            android:actionProviderClass=
                "android.widget.ShareActionProvider" />
    ...
</menu>

This delegates responsibility for the item’s appearance and function toShareActionProvider. However, you will need to tell the provider what you would like to share.

Set the Share Intent


In order for ShareActionProvider to function, you must provide it a share intent. This share intent should be the same as described in the Sending Simple Data to Other Apps lesson, with action ACTION_SEND and additional data set via extras like EXTRA_TEXT and EXTRA_STREAM. To assign a share intent, first find the corresponding MenuItem while inflating your menu resource in your Activity or Fragment. Next, callMenuItem.getActionProvider() to retrieve an instance of ShareActionProvider. Use setShareIntent()to update the share intent associated with that action item. Here’s an example:

private ShareActionProvider mShareActionProvider;
...

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate menu resource file.
    getMenuInflater().inflate(R.menu.share_menu, menu);

    // Locate MenuItem with ShareActionProvider
    MenuItem item = menu.findItem(R.id.menu_item_share);

    // Fetch and store ShareActionProvider
    mShareActionProvider = (ShareActionProvider) item.getActionProvider();

    // Return true to display menu
    return true;
}

// Call to update the share intent
private void setShareIntent(Intent shareIntent) {
    if (mShareActionProvider != null) {
        mShareActionProvider.setShareIntent(shareIntent);
    }
}

You may only need to set the share intent once during the creation of your menus, or you may want to set it and then update it as the UI changes. For example, when you view photos full screen in the Gallery app, the sharing intent changes as you flip between photos.

Receiving Simple Data from Other Apps in Android

Just as your application can send data to other applications, so too can it easily receive data from applications. Think about how users interact with your application, and what data types you want to receive from other applications. For example, a social networking application would likely be interested in receiving text content, like an interesting web URL, from another app. The Google+ Android application accepts both text andsingle or multiple images. With this app, a user can easily start a new Google+ post with photos from the Android Gallery app.

Update Your Manifest


Intent filters inform the system what intents an application component is willing to accept. Similar to how you constructed an intent with action ACTION_SEND in the Sending Simple Data to Other Apps lesson, you create intent filters in order to be able to receive intents with this action. You define an intent filter in your manifest, using the <intent-filter> element. For example, if your application handles receiving text content, a single image of any type, or multiple images of any type, your manifest would look like:

<activity android:name=".ui.MyActivity" >
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND_MULTIPLE" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
    </intent-filter>
</activity>

When another application tries to share any of these things by constructing an intent and passing it tostartActivity(), your application will be listed as an option in the intent chooser. If the user selects your application, the corresponding activity (.ui.MyActivity in the example above) will be started. It is then up to you to handle the content appropriately within your code and UI.

Handle the Incoming Content


To handle the content delivered by an Intent, start by calling getIntent() to get Intent object. Once you have the object, you can examine its contents to determine what to do next. Keep in mind that if this activity can be started from other parts of the system, such as the launcher, then you will need to take this into consideration when examining the intent.

void onCreate (Bundle savedInstanceState) {
    ...
    // Get intent, action and MIME type
    Intent intent = getIntent();
    String action = intent.getAction();
    String type = intent.getType();

    if (Intent.ACTION_SEND.equals(action) && type != null) {
        if ("text/plain".equals(type)) {
            handleSendText(intent); // Handle text being sent
        } else if (type.startsWith("image/")) {
            handleSendImage(intent); // Handle single image being sent
        }
    } else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
        if (type.startsWith("image/")) {
            handleSendMultipleImages(intent); // Handle multiple images being sent
        }
    } else {
        // Handle other intents, such as being started from the home screen
    }
    ...
}

void handleSendText(Intent intent) {
    String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
    if (sharedText != null) {
        // Update UI to reflect text being shared
    }
}

void handleSendImage(Intent intent) {
    Uri imageUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
    if (imageUri != null) {
        // Update UI to reflect image being shared
    }
}

void handleSendMultipleImages(Intent intent) {
    ArrayList<Uri> imageUris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
    if (imageUris != null) {
        // Update UI to reflect multiple images being shared
    }
}

 

Caution: Take extra care to check the incoming data, you never know what some other application may send you. For example, the wrong MIME type might be set, or the image being sent might be extremely large. Also, remember to process binary data in a separate thread rather than the main (“UI”) thread.

Updating the UI can be

 

Sending Simple Data to Other Apps in Android

When you construct an intent, you must specify the action you want the intent to “trigger.” Android defines several actions, including ACTION_SEND which, as you can probably guess, indicates that the intent is sending data from one activity to another, even across process boundaries. To send data to another activity, all you need to do is specify the data and its type, the system will identify compatible receiving activities and display them to the user (if there are multiple options) or immediately start the activity (if there is only one option). Similarly, you can advertise the data types that your activities support receiving from other applications by specifying them in your manifest.

Sending and receiving data between applications with intents is most commonly used for social sharing of content. Intents allow users to share information quickly and easily, using their favorite applications.

 

Send Text Content


Figure 1. Screenshot ofACTION_SEND intent chooser on a handset.
The most straightforward and common use of the ACTION_SEND action is sending text content from one activity to another. For example, the built-in Browser app can share the URL of the currently-displayed page as text with any application. This is useful for sharing an article or website with friends via email or social networking. Here is the code to implement this type of sharing:

Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");
startActivity(sendIntent);

If there’s an installed application with a filter that matches ACTION_SENDand MIME type text/plain, the Android system will run it; if more than one application matches, the system displays a disambiguation dialog (a “chooser”) that allows the user to choose an app.

However, if you call Intent.createChooser(), passing it your Intentobject, it returns a version of your intent that will always display the chooser. This has some advantages:

  • Even if the user has previously selected a default action for this intent, the chooser will still be displayed.
  • If no applications match, Android displays a system message.
  • You can specify a title for the chooser dialog.

Here’s the updated code:

Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");
startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to)));

The resulting dialog is shown in figure 1.

Optionally, you can set some standard extras for the intent: EXTRA_EMAILEXTRA_CCEXTRA_BCC,EXTRA_SUBJECT. If the receiving application is not designed to use them, it simply ignores them.

Note: Some e-mail applications, such as Gmail, expect a String[] for extras like EXTRA_EMAIL andEXTRA_CC, use putExtra(String, String[]) to add these to your intent.

Send Binary Content


Binary data is shared using the ACTION_SEND action combined with setting the appropriate MIME type and placing the URI to the data in an extra named EXTRA_STREAM. This is commonly used to share an image but can be used to share any type of binary content:

Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, uriToImage);
shareIntent.setType("image/jpeg");
startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.send_to)));

Note the following:

  • You can use a MIME type of "*/*", but this will only match activities that are able to handle generic data streams.
  • The receiving application needs permission to access the data the Uri points to. The recommended ways to do this are:
    • Store the data in your own ContentProvider, making sure that other apps have the correct permission to access your provider. The preferred mechanism for providing access is to use per-URI permissions which are temporary and only grant access to the receiving application. An easy way to create aContentProvider like this is to use the FileProvider helper class.
    • Use the system MediaStore. The MediaStore is primarily aimed at video, audio and image MIME types, however beginning with Android 3.0 (API level 11) it can also store non-media types (seeMediaStore.Files for more info). Files can be inserted into the MediaStore using scanFile() after which a content:// style Uri suitable for sharing is passed to the provided onScanCompleted()callback. Note that once added to the system MediaStore the content is accessible to any app on the device.

Send Multiple Pieces of Content


To share multiple pieces of content, use the ACTION_SEND_MULTIPLE action together with a list of URIs pointing to the content. The MIME type varies according to the mix of content you’re sharing. For example, if you share 3 JPEG images, the type is still "image/jpeg". For a mixture of image types, it should be "image/*" to match an activity that handles any type of image. You should only use "*/*" if you’re sharing out a wide variety of types. As previously stated, it’s up to the receiving application to parse and process your data. Here’s an example:

ArrayList<Uri> imageUris = new ArrayList<Uri>();
imageUris.add(imageUri1); // Add your image URIs here
imageUris.add(imageUri2);

Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris);
shareIntent.setType("image/*");
startActivity(Intent.createChooser(shareIntent, "Share images to.."));

 

Kill background processes to free up memory

ActivityManager activityManager = (ActivityManager)  getActivity().getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runAppList = activityManager.getRunningAppProcesses();
int listsize = runAppList.size();

if (runAppList != null) {
                for (int i = 0; i < listsize; ++i) {
                        if (runAppList.get(i).pid != android.os.Process.myPid()) {
                                android.os.Process.killProcess(runAppList.get(i).pid);
                                activityManager.killBackgroundProcesses(runAppList.get(i).processName);
                        }
                }
}

CSS3 User Interface : outline-offset

The outline-offset is such property of the CSS3 User Interface, which can be used to define the space between the element’s border and its outline.

<!DOCTYPE html>
<html>
<head>
<title>Title Name will go here</title>
<style>
#offsite_outline
{
margin:10px;
width:180px;
padding:15px;
height:80px;
border:1px solid red;
outline:1px solid green;
outline-offset:20px;
}
</style>
</head>
<body>
<div id="offsite_outline">
This div is containing the outline offset of 20 px.
</div>
</body>
</html>

CSS3 User Interface : box-sizing

The box-sizing is such a property which allows user to fit a box within the size of an element, the element size may vary but the box-sizing properties always fit the box within the given element width.

The default box-sizing is fit into the content-box. But we can change the specification of box-sizing with changing in box-width and box-height, as we can also modify our box-padding value. And finally It renders to the element to fix the box within given criteria.

<!DOCTYPE html>

<html>
    
    <head>
        <title>Title Name will go here</title>
        <style>
            #box_size
            {
                width:450px;
                border: 8px solid red;
                height: 45px;
            }
            
            #box_inner
            {
                box-sizing: border-box;
                -o-box-sizing: border-box;
                -icab-box-sizing: border-box;
                -khtml-box-sizing: border-box;
                -moz-box-sizing: border-box;
                -webkit-box-sizing: border-box;
                width:50%;
                height: 45px;
                text-align: center;
                border: 5px solid #6AAFCF;
                padding: 3px;
                float:left;
            }
            
        </style>
    
    </head>
    <body>
        <div id="box_size">
            <div id="box_inner">This div contains the left half.</div>
            <div id="box_inner">This div contains the right half.</div>            
        </div>
        
    </body>
    
</html>

CSS3 User Interface : resize

The resize is a such property of User Interface, by which you can resize your div layout on your browser. Three features of resize you can use a)resize:both b) resize:vertical c) resize:horizontal.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<!DOCTYPE html>
<html>
    
    <head>
        <title>Title Name will go here</title>
        <style>
            #div_both
            {
            border:1px solid green;
            margin-top:20px;
            padding:15px 30px;
            width:250px;
            resize:both;
            overflow:auto;
            }
            
            #div_horizontal
            {
            border:1px solid green;
            margin-top:20px;
            padding:15px 30px;
            width:250px;
            resize:horizontal;
            overflow:auto;
            }
            
            #div_vertical
            {
            border:1px solid green;
            margin-top:20px;
            padding:15px 30px;
            width:250px;
            resize:vertical;
            overflow:auto;
            }
            
        </style>
    
    </head>
    <body>
        <div id="div_both">This div is stretchable from both corner (Horizontal & Vertical).</div>
        <div id="div_horizontal">This div is stretchable from horizontal corner.</div>
        <div id="div_vertical">This div is stretchable from vertical corner.</div>             
        
    </body>
    
</html>

CSS3 Transition Effects

A CSS3 Transition Effect is a such an effect that lets an element gradually change from one style to another style. CSS3 Transition Effect is best suited for animation uses. But still a lot can be done without using the animation. A user interface is necessary to see the effects of transition. The all major browser support the CSS3 Transition Effects. Although CSS3 Transition Effect is sufficient for the transition of an element, but a text-transform property can enhance the style of CSS3 Transition Effects.

<!DOCTYPE html>

<html>
    
    <head>
        <title>Title Name will go here</title>
        <style>
            
            div.swapnil
            {
                width: 20px;
                height: 20px;
                margin: 20px auto;
            }
            
            div.swapnil div.raja img
            {
                width: 20px;
                height: 20px;
                color: #fff;
                padding: 10px;
                border-radius: 5px;
                margin-left: 0;
                -webkit-transition: 3s linear;
                -moz-transition: 3s linear;
                -o-transition: 3s linear;
                -ms-transition: 3s linear;
                transition: 3s linear;
            }
            
            div.swapnil:hover div.raja img
            {
                width: 240px;
                height: 220px;
                -webkit-transform:rotate(360deg);
                -moz-transform:rotate(360deg);
                -o-transform:rotate(360deg);
                -ms-transform:rotate(360deg);
                transform:rotate(360deg);
            }
            
        </style>
    
    </head>
    <body>
        <p>Hover on object to see it in action</p>
        <div class="swapnil">
            <div class="raja">
            <img src="media/star.png" width="20" height="20"/>
            </div>
        </div>
    </body>
    
</html>

CSS3 Text Effects

A CSS3 Text Effect is a such term which is used to implement some extra features on normal text. CSS3 Text Effect is used to extend the text features for viewing and layout purpose.

Their are mainly two properties of CSS3 Text Effects, which have been described as follows:

✔ text-shadow

✔ word-wrap

Where text-shadow is used to create the shadow around the text, We can change the shadow color also. And word-wrap is used to break the continued text in another line. It means whenever we get difficulty to break the line of sentence we can generally use this css3 text-wrap property.

Scan for Wireless Networks

Scan for wireless networks in the current area.

public class WifiTester extends Activity {
TextView mainText;
    WifiManager mainWifi;
    WifiReceiver receiverWifi;
    List<ScanResult> wifiList;
    StringBuilder sb = new StringBuilder();
    
    public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.main);
       mainText = (TextView) findViewById(R.id.mainText);
       mainWifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
       receiverWifi = new WifiReceiver();
       registerReceiver(receiverWifi, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
       mainWifi.startScan();
       mainText.setText("\\nStarting Scan...\\n");
    }

    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add(0, 0, 0, "Refresh");
        return super.onCreateOptionsMenu(menu);
    }

    public boolean onMenuItemSelected(int featureId, MenuItem item) {
        mainWifi.startScan();
        mainText.setText("Starting Scan");
        return super.onMenuItemSelected(featureId, item);
    }

    protected void onPause() {
        unregisterReceiver(receiverWifi);
        super.onPause();
    }

    protected void onResume() {
        registerReceiver(receiverWifi, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
        super.onResume();
    }
    
    class WifiReceiver extends BroadcastReceiver {
        public void onReceive(Context c, Intent intent) {
            sb = new StringBuilder();
            wifiList = mainWifi.getScanResults();
            for(int i = 0; i < wifiList.size(); i++){
                sb.append(new Integer(i+1).toString() + ".");
                sb.append((wifiList.get(i)).toString());
                sb.append("\\n");
            }
            mainText.setText(sb);
        }
    }
}