2016年10月12日 星期三

Building a Music App - Part 1

Ref : http://www.kilobolt.com/day-4-building-a-music-app---part-1-building-blocks.html





For each activity, we will add:
android:screenOrientation="landscape"

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.awesomemusicselectorapp"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.awesomemusicselectorapp.MainActivity"
            android:label="@string/app_name"
            android:screenOrientation="landscape" >
             >


            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.example.awesomemusicselectorapp.SecondActivity"
            android:label="@string/title_activity_second"
            android:screenOrientation="landscape" >
             >

        </activity>
    </application>

</manifest>
This should make the two activities landscape. Now when we run our app, it should be in landscape mode!

three ways to modify UI

There are three ways you can modify the UI of your app. The first (and possibly the easiest) is to use a Graphical Layout, which will show us our XML files in a realistic preview. The second is to use XML to insert objects and to modify them. The third is to do it dynamically in Java. We will be sticking with the first two for this lesson.

If we open up our MainActivity.java, which is our first screen, the onCreate method (the method that is called when the Activity is starting) calls the method:

@Override
   protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);}

We previously discussed that setContentView will take in the ID of a layout resource and sets the content of our Activity as specified in the layout resource. In this case, we can find the layout in:

res > layout > activity_main.xml.

If we open this up, we can access the Graphical Layout and the XML versions of this file like so:
Note 2: Learn about different types of units of measurement: px, dp, dip, and sp, and when to use them here:
http://developer.android.com/guide/topics/resources/more-resources.html#Dimension
dp
Density-independent Pixels - An abstract unit that is based on the physical density of the screen. These units are relative to a 160 dpi (dots per inch) screen, on which 1dp is roughly equal to 1px. When running on a higher density screen, the number of pixels used to draw 1dp is scaled up by a factor appropriate for the screen's dpi. Likewise, when on a lower density screen, the number of pixels used for 1dp is scaled down. The ratio of dp-to-pixel will change with the screen density, but not necessarily in direct proportion. Using dp units (instead of px units) is a simple solution to making the view dimensions in your layout resize properly for different screen densities. In other words, it provides consistency for the real-world sizes of your UI elements across different devices.
sp
Scale-independent Pixels - This is like the dp unit, but it is also scaled by the user's font size preference. It is recommend you use this unit when specifying font sizes, so they will be adjusted for both the screen density and the user's preference.
pt
Points - 1/72 of an inch based on the physical size of the screen.
px
Pixels - Corresponds to actual pixels on the screen. This unit of measure is not recommended because the actual representation can vary across devices; each devices may have a different number of pixels per inch and may have more or fewer total pixels available on the screen.
mm
Millimeters - Based on the physical size of the screen.
in
Inches - Based on the physical size of the screen.
private void startSecondActivity(int buttonNum) {
   Intent intent = new Intent(this, SecondActivity.class);
   intent.putExtra("BUTTON NUMBER", buttonNum);
   startActivity(intent);
}
Recall how we created an Intent (a message that holds data about a desired action) in Day 5 (MainActivity) (check that yours is identical, or it will not work. Eclipse, for some reason, changed the key "BUTTON NUMBER" during packaging, so if you are running downloaded code, you may have to fix this):

  Intent intent = new Intent(this, SecondActivity.class);
  intent.putExtra("BUTTON NUMBER", buttonNum);
  startActivity(intent);


Now, in the bottom of the onCreate() method of the SecondActivity class, we add the following:

Intent intent = getIntent();int number = intent.getIntExtra("BUTTON NUMBER", 1);
Now, open up SecondActivity again. In the onCreate() method, we want to start playing the music.

We will begin by adding the following.

1. Below the class declaration:
public class SecondActivity extends Activity {

Add:
private MediaPlayer mPlayer;
private int currentSong = 0;

SecondActivity onCreate()

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        Intent intent = getIntent();
        int number = intent.getIntExtra("BUTTON NUMBER", 1);

        TextView tv = (TextView) findViewById(R.id.textView);
        tv.setText(String.valueOf(number));

        if (number == 1) {
            mPlayer = MediaPlayer.create(SecondActivity.this, R.raw.song1);
            currentSong = R.raw.song1;
        } else if (number == 2) {
            mPlayer = MediaPlayer.create(SecondActivity.this, R.raw.song2);
            currentSong = R.raw.song2;

        } else if (number == 3) {
            mPlayer = MediaPlayer.create(SecondActivity.this, R.raw.song3);
            currentSong = R.raw.song3;

        } else if (number == 4) {
            mPlayer = MediaPlayer.create(SecondActivity.this, R.raw.song4);
            currentSong = R.raw.song4;

            // Defaults are always a good idea:
        } else {
            mPlayer = MediaPlayer.create(SecondActivity.this, R.raw.song1);
            currentSong = R.raw.song1;

        }

        mPlayer.start();
    }

We use a series of if statements to determine which song to play. We even add a default value just in case something goes wrong. After loading up the MediaPlayer with the desired song, we call:

mPlayer.start();

Pretty straight forward.

Now here's the tricky part. What if the user pauses the app? Right now, if the user gets a call or if the user presses the home button, the music will continue to play. That is because we are not Overriding an onPause() method. So let's add one.

SecondActivity onPause()

    @Override
    protected void onPause() {
        super.onPause();
        if (mPlayer.isPlaying()) {
            mPlayer.pause();
        }
    }

The onPause() method is called whenever the application is hidden from the user. Typically this is when the user opens another Activity (or presses Back to return to MainActivity). We will first call super.onPause() (this is required, because there are certain calls in the Activity.class's onPause method - the method we are overriding - that must be called for proper system function).

Then we simply check if mPlayer is playing before we pause it.

Now the music will pause when the user leaves the app, but what if he or she returns to it? Then onCreate method will NOT be called, as the Activity is not being created for the first time. Then we need to add the following method: onResume().

SecondActivity onResume()

    @Override
    protected void onResume() {
        super.onResume();
        if (mPlayer == null) {
            mPlayer = MediaPlayer.create(SecondActivity.this, currentSong);
        }

        mPlayer.start();
    }
First, we make sure that our mPlayer is not null. As we are juggling resources around in our mobile device, sometimes large memory objects may get lost. If it is null, we simply create a new one with the currentSong - the song that was playing when the app was paused.
Finally, we must help the system clean up a little bit in case the application closes. It will be good practice for us to do our own clean up and make sure system resources are available for other apps, so let's do that:

SecondActivity onStop()

    @Override
    protected void onStop() {
        super.onStop();

        if (mPlayer.isPlaying()) {
            mPlayer.stop();
        }
    }
Same thing here. We call the super.onStop(), as the superclass's onStop method must be called to call critical methods upon Stopping an application. We will check if the mPlayer is playing, and then stop it, and everything will be ready to be disposed by Android.






沒有留言:

張貼留言