|
给大家发个最写的一个例子 帖子有点长,但内容并不是很多
包含一着歌,所以文件比较大,5M多;
源码下载: 心灵僻处,如果您要查看本帖隐藏内容请回复
作个解释:
aidl = Android 接口,定义语言,用于远程通讯,我们只需要编写,.aidl文件,eclipse插件就会为我们生成相应的代码。
在要远程控制的service中创建一个该接口的对象,()实现具体方法。
在service的onBind中将其返回。
@Override
public IBinder onBind(Intent intent) {
return stub;
}
复制代码
activy必需要和这个service绑定并在onServiceConnected 方法中获得接口对象实例
具体执行过程 是,activity通过,bindService(new Intent(Main.this,
LocalService.class), mConnection, Context.BIND_AUTO_CREATE); 和service绑定,会触发上面的代码,创建一个mConnection 对象。在onServiceConnected 中通过.Stub.asInterface(service);获得远程接口对象。之后就可以像使用本地对象一个使用远程对象mPlayer了。
IPlayer.aidl 源码
复制代码
service代码
package com.chonwhite.mplayer;
import java.io.IOException;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;
public class LocalService extends Service {
private NotificationManager mNM;
private MediaPlayer mPlayer;
IPlayer.Stub stub = new IPlayer.Stub() {
@Override
public void play() throws RemoteException {
// TODO AutmPlayer.
mPlayer.start();
}
@Override
public void pause() throws RemoteException {
// TODO Auto-generated method stub
mPlayer.pause();
}
@Override
public void stop() throws RemoteException {
// TODO Auto-generated method stub
mPlayer.stop();
}
@Override
public int getDuration() throws RemoteException {
// TODO Auto-generated method stub
return mPlayer.getDuration();
}
@Override
public int getCurrentTime() throws RemoteException {
// TODO Auto-generated method stub
return mPlayer.getCurrentPosition();
}
@Override
public void setCurrent(int cur) throws RemoteException {
// TODO Auto-generated method stub
mPlayer.seekTo(cur);
}
@Override
public boolean isPlaying() throws RemoteException {
// TODO Auto-generated method stub
return mPlayer.isPlaying();
}
};
@Override
public void onCreate() {
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
mPlayer = MediaPlayer.create(this, R.raw.mom);
mPlayer.start();
// Display a notification about us starting. We put an icon in the status bar.
showNotification();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
@Override
public void onDestroy() {
// Cancel the persistent notification.
mNM.cancel("ServiceStarted", 0);
// Tell the user we stopped.
Toast.makeText(this, "ServiceStoped", Toast.LENGTH_SHORT).show();
}
//当activity和service绑定时调用
@Override
public IBinder onBind(Intent intent) {
return stub;
}
/**
* Show a notification while this service is running.
*/
private void showNotification() {
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = "LocalServiceStarted";
// Set the icon, scrolling text and timestamp
Notification notification = new Notification(R.drawable.icon, text,
System.currentTimeMillis());
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, Main.class), 0);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this, "ServiceLable",
text, contentIntent);
// Send the notification.
// We use a layout id because it is a unique number. We use it later to cancel.
mNM.notify("LocalServiceStarted", 0, notification);
}
}
复制代码
Main Activy代码
package com.chonwhite.mplayer;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;
public class Main extends Activity{
private IPlayer mPlayer;//代理播放器句柄
private SeekBar seekbar;
private TextView cur;//当前播放时间
private TextView dur;//歌曲总长度
private LrcSurfaceView mLrc ;
//handler负责管理线程
Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
//cur.setText("当前播放时间" + msg.arg1);
};
};
//一个线程负责更新信息
private Runnable updateThread = new Runnable(){
@Override
public void run(){
Log.i("Thread","In RUN_____________>>>>>");
if (mPlayer!= null){//不执行null Check 会出现NullPointException
try {
int seconds = mPlayer.getCurrentTime() / 1000;
int minutes = seconds / 60;
seconds = seconds % 60;
cur.setText("当前播放时间" +minutes +":"+ seconds+ "播放状态"+ mPlayer.isPlaying());
dur.setText("歌曲总长度:" + mPlayer.getDuration());
//更新歌词时间
mLrc.timeUpdate(mPlayer.getCurrentTime(), mPlayer.getDuration());
//更新进度条
seekbar.setMax(mPlayer.getDuration());
seekbar.setProgress(mPlayer.getCurrentTime());
} catch (RemoteException e) {
// TODO Auto-generated catch block
Log.e("Error","Unable to get Time------------->>");
}
}
//cur.setText("In RUN");
mHandler.postDelayed(updateThread, 100);//将线程延迟加入handler处理
}
};
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mPlayer = IPlayer.Stub.asInterface(service);//后台播放器控制句柄
// Tell the user about this for our demo.
Toast.makeText(Main.this, "ServiceConnected",
Toast.LENGTH_SHORT).show();
}
public void onServiceDisconnected(ComponentName className) {
//mBoundService = null;
Toast.makeText(Main.this, "Serviedisconnected",
Toast.LENGTH_SHORT).show();
};
};
void doBindService() {
// Establish a connection with the service. We use an explicit
// class name because we want a specific service implementation that
// we know will be running in our own process (and thus won't be
// supporting component replacement by other applications).
bindService(new Intent(Main.this,
LocalService.class), mConnection, Context.BIND_AUTO_CREATE);
}
void doUnbindService() {
unbindService(mConnection);
}
@Override
protected void onDestroy() {
super.onDestroy();
doUnbindService();
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
//大家都懂的
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button play = (Button)findViewById(R.id.play);
Button pause = (Button)findViewById(R.id.pause);
Button stop = (Button)findViewById(R.id.stop);
mLrc = (LrcSurfaceView)findViewById(R.id.lrc);
seekbar = (SeekBar)findViewById(R.id.seekbar);
cur = (TextView)findViewById(R.id.current);
dur = (TextView)findViewById(R.id.duration);
//为进度条设置,监听器
seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
if(mPlayer!=null){
try {
mPlayer.setCurrent(seekbar.getProgress());
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
//播放按钮监听器
play.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
try {
mPlayer.play();
//dur.setText("歌曲总长度" + mPlayer.getDuration());
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
//暂停按钮
pause.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
try {
mPlayer.pause();
//cur.setText(mPlayer.getCurrentTime()+"");
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
//停止按钮监听器
stop.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
try {
mPlayer.stop();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
bindService(new Intent(Main.this,
LocalService.class), mConnection, Context.BIND_AUTO_CREATE);
startService(new Intent(Main.this,
LocalService.class));
mHandler.post(updateThread);
}
//菜单,大家都懂的
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, 1, 1, "以后再写");
menu.add(0, 2, 2, "退出");
return super.onCreateOptionsMenu(menu);
}
//处理菜单事件
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 1:
//startActivity(new Intent(Main.this,FileListActivity.class){
//});
break;
case 2:
//退出操作提示
AlertDialog.Builder builder2=new AlertDialog.Builder(this);
builder2.setIcon(R.drawable.alert_dialog_icon).setTitle("提示").setMessage("你确定要退出播放吗?").setPositiveButton("确定", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
doUnbindService();
stopService(new Intent(Main.this, LocalService.class));
finish();
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which) {
}
}).create().show();
break;
}
return super.onOptionsItemSelected(item);
}
}
复制代码main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
androidrientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<RelativeLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<Button
android:id="@+id/play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/pause"
android:text="lay"
/>
<Button
android:id="@+id/pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="Pause"
/>
<Button
android:id="@+id/stop"
android:layout_toRightOf="@+id/pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Stop"
/>
</RelativeLayout>
<TextView
android:id="@+id/current"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="current"
/>
<TextView
android:id="@+id/duration"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Duration"
/>
<SeekBar android:layout_marginTop="10px"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/seekbar"
/>
<com.chonwhite.mplayer.LrcSurfaceView
android:id="@+id/lrc"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
/>
</LinearLayout>
复制代码
manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.chonwhite.mplayer"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".Main"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".FileListActivity"></activity>
<service android:name=".LocalService" ></service>
</application>
</manifest>
复制代码 |
|