• No results found

Adding the MP3 using the media scanner

In document 50 Android Hacks (Page 151-155)

media ContentProvider Android v1.6+

37.2 Adding the MP3 using the media scanner

The code included in the last section works fine, but it has a big problem. Some values were set by hand and perhaps it would be better to read them from the file. For exam- ple, the real author of loop1.mp3 is “calpomatt” and not “Android.” We’d know that by reading the MP3’s metadata.

Fortunately, there’s a way to avoid having to add those values by hand. The code is the following:

MediaUtils.saveRaw(this, R.raw.loop2, LOOP2_PATH);

File is first saved in external storage

Uri uri = Uri.parse("file://" + LOOP2_PATH);

Intent i = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri); sendBroadcast(i);

Send a broadcast asking for a particular file to be scanned and added

37.3

The bottom line

If you’re creating an application that handles media, you should pay attention to the media ContentProvider. Try understanding and using it correctly. It might be essen- tial to your users.

37.4

External links

http://developer.android.com/guide/topics/providers/content-providers.html http://stackoverflow.com/questions/3735771/adding-mp3-to-the-contentresolver www.flashkit.com/loops/Pop-Rock/Rock/Get_P-calpomat-4517/index.php www.flashkit.com/loops/Pop-Rock/Rock/_Hard-XtremeWe-6500/index.php

Hack 38

Adding a refresh action to the action bar

Android v2.1+

The ActionBar API was added to Android version 3.0 (Honeycomb). The idea behind the ActionBar pattern is to have a place where you locate the user inside your applica- tion and offer contextual actions.

123

Adding a refresh action to the action bar

You might have noticed that some applications have a refresh action in their ActionBars. You see a Refresh icon and when you press it, a refresh process runs while a ProgressBar spins. Unfortunately, the platform doesn’t contain a widget—it needs to be cre- ated by hand. In this hack, I’ll show you how to do it. For the sake of compatibility we’ll use Jake Whar- ton’s ActionBarSherlock library. ActionBarSherlock offers the ActionBar API, but it can be used in older Android versions.

ABOUT ACTIONBARSHERLOCK You’ll need to know how to configure your application to use ActionBarSherlock to move on. You can learn how by visiting the library’s web page: http://actionbarsherlock.com/.

To add an ActionBar to an Activity, the first step is to make our application use the ActionBarSherlock theme. We can do this by using the following lines in the AndroidManifest.xml file:

<application

android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/Theme.Sherlock">

The second step is to create an activity, but instead of extending Activity, we need to extend SherlockActivity. The code to show a progress icon in the action bar is the following:

public class MainActivity extends SherlockActivity { private static final int MENU_REFRESH = 10;

private MenuItem mRefreshMenu; ...

@Override

public boolean onCreateOptionsMenu(Menu menu) { mRefreshMenu = menu.add(MENU_REFRESH, MENU_REFRESH,

Create refresh menu MENU_REFRESH, "Refresh"); mRefreshMenu.setIcon(R.drawable.menu_reload); mRefreshMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); return true; }

The result can be seen in figure 38.1.

The next step is to handle what to do when a user presses the Refresh button in the action bar or the button in the middle of the screen. Both items should launch a back- ground task. To simulate the background task, we’ll create an AsyncTask with the fol- lowing code:

private class LoadingAsyncTask extends AsyncTask<Void, Void, Void> { @Override

protected void onPreExecute() { super.onPreExecute();

startLoading();

Handle UI changes when the task is about to start

}

@Override

protected Void doInBackground(Void... params) { SystemClock.sleep(5000L); Sleep for 5 seconds return null; } @Override

protected void onPostExecute(Void result) { super.onPostExecute(result);

stopLoading();

Handle UI changes when the task is about to finish

} }

The execution of the AsyncTask is accomplished by a single method: public void handleRefresh(View v) {

new LoadingAsyncTask().execute(); }

This method is called from the centered button from the Activity’s layout using the android:onClick property and from the action bar in the onOptionsItemSelected() method.

We have almost everything in place. The only missing part is how to handle UI

changes when the background process starts and finishes. For the centered button, the logic is simple. We want to disable the button while the background task is work- ing and enable it when finished. We can do this by using the setEnabled(boolean enabled) method. The big question here is how to replace the progress menu item with something spinning. To do that, we’ll use an ActionView.

The ActionView is explained in the documentation (see section 38.2): An action view is a widget that appears in

the action bar as a substitute for an action item’s button. For example, if you have an item in the options menu for “Search,” you can add an action view that replaces the button with a SearchView widget, as shown in figure [38.2].

Because we’ll add the spinning widget through an ActionView, let’s create the view with XML:

Figure 38.2 An action bar with a collapsed ActionView for Search (top) and an expanded ActionView with the SearchView widget (bottom)

125

Adding a refresh action to the action bar

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" style="?attr/actionButtonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:addStatesFromChildren="true" android:focusable="true" android:gravity="center" android:paddingLeft="4dp" android:paddingRight="4dp" > <ProgressBar android:layout_width="30dp" android:layout_height="30dp" android:focusable="true" /> </LinearLayout>

Now that we have the XML, the rest is quite simple. This is how the startLoading() and stopLoading() methods handle the refresh menu item’s action view:

private void startLoading() {

mRefreshMenu.setActionView(R.layout.menu_item_refresh); mButton.setEnabled(false);

}

private void stopLoading() {

mRefreshMenu.setActionView(null); mButton.setEnabled(true);

}

38.1

The bottom line

This hack is an example of how to customize the action bar’s items. Nowadays, using an action bar is almost a must for every Android application, and thanks to Jake Whar- ton we have an Android library that backports the action bar to older platforms. It’s important to learn what’s possible and understand how it can fulfill your application use cases.

38.2

External links

http://developer.android.com/guide/topics/ui/actionbar.html http://actionbarsherlock.com/

Hack 39

Getting dependencies from the market

In document 50 Android Hacks (Page 151-155)