<!-- 主Activity -->
<!-- android:exported="true" 表示可以由其他程序访问 -->
<activity
android:name="com.android.music.MusicBrowserActivity"
android:theme="@android:style/Theme.NoTitleBar"
android:exported="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.MUSIC_PLAYER" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
/MusicBrowserActivity/AndroidManifest.xml
在清单文件中,定义了该项目的入口Activity,顺着这个Activity,我们进入到项目源码的分析
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
/*
MusicUtils中使程序可以按照选择显示不同的Activity,显示出对应的Tab选项卡内容,那么它是怎么做的呢?
*/ int activeTab = MusicUtils.getIntPref(this, "activetab", R.id.artisttab);
if (activeTab != R.id.artisttab
&& activeTab != R.id.albumtab
&& activeTab != R.id.songtab
&& activeTab != R.id.playlisttab)
{ activeTab = R.id.artisttab; }
//打开哪个Tab选项卡 MusicUtils.activateTab(this, activeTab);
为了搞清楚,Tab四个选项卡的显示是如何做到的,我们跳转到
MusicUtils.getIntPref(Context context, String name, int def)
{
/*原来是要得到音乐程序没关闭时,所处的Tab选项卡,比方说我正在听音乐,这时候要发个短信,我按了Home键
之后再回来的时候,我当然更希望还在我原来的界面下*/
SharedPreferences prefs = context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
return prefs.getInt(name, def);
}
继续往下
activeTab中已经存放了上一次没退出的情况下所在的选项卡信息(若为第一次打开,则默认选项卡为 "艺术家" R.id.artisttab)
网上有看到人问过,不知道选项卡下的内容在哪里得到显示,其实就是通过
MusicUtils.activateTab(this, activeTab);
static void activateTab(Activity a, int id) {
Intent intent = new Intent(Intent.ACTION_PICK); //设置action为"android.intent.action.PICK"
switch (id) {
case R.id.artisttab:
/*设置数据Uri和数据的MIME类型,这两个东东是显示对应Activity的关键*/
intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/artistalbum");
break;
case R.id.albumtab:
intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/album");
break;
case R.id.songtab:
intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
break;
case R.id.playlisttab:
intent.setDataAndType(Uri.EMPTY, MediaStore.Audio.Playlists.CONTENT_TYPE);
break;
case R.id.nowplayingtab:
intent = new Intent(a, MediaPlaybackActivity.class);
a.startActivity(intent);
// fall through and return
default:
return;
}
intent.putExtra("withtabs", true);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
a.startActivity(intent);
a.finish();
a.overridePendingTransition(0, 0);
}
为何设置DataAndType就可以打开对应的Activity,相信有过开发经验的人现在都已经知道了,但为了方便其他还不清楚的人,我还是卖弄下
这种启动Activity的方式,我们称之为 隐式启动Activity ,通过action 和 data 的 MIME类型来对应Activity
我们跳转到AndroidManifest.xml中,找到如下Activity,
<activity android:name="com.android.music.ArtistAlbumBrowserActivity" android:exported="false" >
<intent-filter>
<action android:name="android.intent.action.PICK" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.dir/artistalbum"/>
对照/*intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/artistalbum");*/想必你已经明白了吧?
</intent-filter>
</activity>
这个类的真正的重点在于后面的代码,这里涉及到
AIDL,Service和Activity的绑定,Binder
因此,后面这部分等到讲主要类 MediaPlaybackService时,再具体讲
String shuf = getIntent().getStringExtra("autoshuffle");
if ("true".equals(shuf)) {
mToken = MusicUtils.bindToService(this, autoshuffle);
}
private ServiceConnection autoshuffle = new ServiceConnection() {
public void onServiceConnected(ComponentName classname, IBinder obj) {
// we need to be able to bind again, so unbind
try {
unbindService(this);
} catch (IllegalArgumentException e) {
}
IMediaPlaybackService serv = IMediaPlaybackService.Stub.asInterface(obj);
if (serv != null) {
try {
serv.setShuffleMode(MediaPlaybackService.SHUFFLE_AUTO);
} catch (RemoteException ex) {
}
}
}
public void onServiceDisconnected(ComponentName classname) {
}
};