【我的问题】android:service里的一个内部线程类可以公用service的数据吗
2014-08-27 16:52
453 查看
代码如下:
package com.alien.smartmusicplayer;
import android.R.anim;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.IBinder;
import android.provider.MediaStore;
import android.util.Log;
public class PlayerService extends Service
{
private MediaPlayer mPlayer;
PlayerService_Receiver playerService_Receiver;
private static Uri nowPlayingUri;//存放当前播放音乐的Uri
private static boolean isPlaying=false;//是否正在播放音乐
private static int currentProgress;//存放当前音乐进度
private static int duration;//存放音乐文件长度
UpdateTrack mUpdateTrack;
private static Intent mIntent=new Intent("com.alien.smartmusicplayer.action.PLAYER_STATUS");
@Override
public IBinder onBind(Intent intent)
{
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate()
{
//切勿忘记这句
super.onCreate();
Log.d("mLog", "service启动");//dddddddddddddddd
//创建MediaPlayer
mPlayer=new MediaPlayer();
//startUpdateTrack(100);
/**
* 设置广播接收器:接收来自mainactivity的控制信息广播
*创建BroadcastReceiver *创建IntentFilter过滤器
*/
playerService_Receiver=new PlayerService_Receiver();
IntentFilter intentFilter=new IntentFilter();
intentFilter.addAction("com.alien.smartmusicplayer.action.CONTROL_ACTION");
registerReceiver(playerService_Receiver, intentFilter);
}
/**
* 反注册广播接收器
*/
@Override
public void onDestroy()
{
super.onDestroy();
unregisterReceiver(playerService_Receiver);
Log.d("mLog","service被销毁:onDestroy()被调用");
}
/**
* PlayerService广播接收器
* 用来接收来自View控件的控制消息,以响应控制信息
*/
public class PlayerService_Receiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
//获取intent的来源,下面将根据intent的来源进行消息响应
String intentFrom=intent.getStringExtra("intentFrom");
Log.d("mLog","PlayerService收到的intent来自:"+intentFrom);
/**
* 根据intentFrom的值进行相应处理
*/
//①来自所有歌曲列表的音乐列表项点击
if (intentFrom.equals("allSongsListView_OnItemClickListener"))
{
long ID=intent.getLongExtra("ID", -1);
nowPlayingUri=Uri.withAppendedPath(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,"/"+String.valueOf(ID));
if (nowPlayingUri != null)
{
if (isPlaying)
{//如果正在播放就先停止和销毁当前播放的音频文件
mPlayer.stop();
mPlayer.release();
//isPlaying=mPlayer.isPlaying(); 这句有了会报错
}
Log.d("mLog","点击被接收"+nowPlayingUri);
//用来接收点击音乐列表项目时,intent传送过来的音乐id
mPlayer=MediaPlayer.create(PlayerService.this, nowPlayingUri);
mPlayer.start();
duration=mPlayer.getDuration();//获取音乐文件长度
isPlaying=mPlayer.isPlaying();
startUpdateTrack(100);
}
}//②来自contentfragment的控制台按钮的点击
else if (intentFrom.equals("ContentFragmentOnClickListener"))
{
/**
* ContentFragmentOnClickListener在ContentFragment.java里
* 该intent含有“controlButton”,主要是播放控制按钮:播放、上一曲、下一曲,还有进度条
*/
//获取被按下的是哪个按钮
int controlButton=intent.getIntExtra("controlButton", -1);
//播放、上一曲、下一曲 按钮事件处理
switch (controlButton)
{
case R.id.content_fragment_playerCtrl_PLAY:
mPlayer.pause();//mPlayer暂停
isPlaying=mPlayer.isPlaying();
Log.d("mLog","PLAY被按下,isplaying="+isPlaying);
break;
default:
break;
}
}//③来自contentfragment的进度条seek_bar事件处理
else if (intentFrom.equals("SeekBarChangeListener"))
{
int seek_bar=intent.getIntExtra("seek_bar", -1);
if (seek_bar==R.id.seek_bar)
{
int progress=intent.getIntExtra("progress", -1);//获取音乐进度
mPlayer.seekTo(progress);
currentProgress=mPlayer.getCurrentPosition();//获取音乐当前播放进度位置
}
}
}
}
/**
* 响应了收来自View控件的控制消息后,PlayerService的状态会改变
* 定时将PlayerService的新状态通过广播发送出去,让View接收并更新显示内容
* ***************************************************************************
*/
public class UpdateTrack extends Thread
{
int milliseconds;//更新音轨的间隔时间
public UpdateTrack(int ms)
{
this.milliseconds=ms;
}
@Override
public void run()
{
//如果mPlayer处于播放状态则更新音轨信息
while (isPlaying)
{
Log.d("UpdateTrack","UpdateTrack广播线程启动: "+isPlaying);
/**
* 注意线程安全:下面这句话留在这里会出现线程异常退出,说明log语句留在程序里有可能出问题
* //Log.d("UpdateTrack","mPlayer正在播放音乐吗: "+mPlayer.isPlaying());
*/
try
{
sleep(milliseconds);
currentProgress=mPlayer.getCurrentPosition();
} catch (Exception e)
{
e.printStackTrace();
Log.d("UpdateTrack","UpdateTrack广播线程异常");
}
/**
* 注意线程安全:下面这句话在这里会出现线程异常退出
* currentProgress=mPlayer.getCurrentPosition();
*/
mIntent.setData(nowPlayingUri);//存放当前播放音乐的Uri
mIntent.putExtra("isPlaying", isPlaying);//是否正在播放音乐
mIntent.putExtra("currentProgress", currentProgress);//存放当前音乐进度
mIntent.putExtra("duration", duration);//存放音乐文件长度
sendUpdateTrack_Broadcast();
Log.d("UpdateTrack","更新广播已经发送##############");
}
}
}
public void sendUpdateTrack_Broadcast()
{
sendBroadcast(mIntent);
}
public void startUpdateTrack(int milliseconds)
{
mUpdateTrack=new UpdateTrack(milliseconds);
mUpdateTrack.start();
}
//***************************************************************************
}
package com.alien.smartmusicplayer;
import android.R.anim;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.IBinder;
import android.provider.MediaStore;
import android.util.Log;
public class PlayerService extends Service
{
private MediaPlayer mPlayer;
PlayerService_Receiver playerService_Receiver;
private static Uri nowPlayingUri;//存放当前播放音乐的Uri
private static boolean isPlaying=false;//是否正在播放音乐
private static int currentProgress;//存放当前音乐进度
private static int duration;//存放音乐文件长度
UpdateTrack mUpdateTrack;
private static Intent mIntent=new Intent("com.alien.smartmusicplayer.action.PLAYER_STATUS");
@Override
public IBinder onBind(Intent intent)
{
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate()
{
//切勿忘记这句
super.onCreate();
Log.d("mLog", "service启动");//dddddddddddddddd
//创建MediaPlayer
mPlayer=new MediaPlayer();
//startUpdateTrack(100);
/**
* 设置广播接收器:接收来自mainactivity的控制信息广播
*创建BroadcastReceiver *创建IntentFilter过滤器
*/
playerService_Receiver=new PlayerService_Receiver();
IntentFilter intentFilter=new IntentFilter();
intentFilter.addAction("com.alien.smartmusicplayer.action.CONTROL_ACTION");
registerReceiver(playerService_Receiver, intentFilter);
}
/**
* 反注册广播接收器
*/
@Override
public void onDestroy()
{
super.onDestroy();
unregisterReceiver(playerService_Receiver);
Log.d("mLog","service被销毁:onDestroy()被调用");
}
/**
* PlayerService广播接收器
* 用来接收来自View控件的控制消息,以响应控制信息
*/
public class PlayerService_Receiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
//获取intent的来源,下面将根据intent的来源进行消息响应
String intentFrom=intent.getStringExtra("intentFrom");
Log.d("mLog","PlayerService收到的intent来自:"+intentFrom);
/**
* 根据intentFrom的值进行相应处理
*/
//①来自所有歌曲列表的音乐列表项点击
if (intentFrom.equals("allSongsListView_OnItemClickListener"))
{
long ID=intent.getLongExtra("ID", -1);
nowPlayingUri=Uri.withAppendedPath(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,"/"+String.valueOf(ID));
if (nowPlayingUri != null)
{
if (isPlaying)
{//如果正在播放就先停止和销毁当前播放的音频文件
mPlayer.stop();
mPlayer.release();
//isPlaying=mPlayer.isPlaying(); 这句有了会报错
}
Log.d("mLog","点击被接收"+nowPlayingUri);
//用来接收点击音乐列表项目时,intent传送过来的音乐id
mPlayer=MediaPlayer.create(PlayerService.this, nowPlayingUri);
mPlayer.start();
duration=mPlayer.getDuration();//获取音乐文件长度
isPlaying=mPlayer.isPlaying();
startUpdateTrack(100);
}
}//②来自contentfragment的控制台按钮的点击
else if (intentFrom.equals("ContentFragmentOnClickListener"))
{
/**
* ContentFragmentOnClickListener在ContentFragment.java里
* 该intent含有“controlButton”,主要是播放控制按钮:播放、上一曲、下一曲,还有进度条
*/
//获取被按下的是哪个按钮
int controlButton=intent.getIntExtra("controlButton", -1);
//播放、上一曲、下一曲 按钮事件处理
switch (controlButton)
{
case R.id.content_fragment_playerCtrl_PLAY:
mPlayer.pause();//mPlayer暂停
isPlaying=mPlayer.isPlaying();
Log.d("mLog","PLAY被按下,isplaying="+isPlaying);
break;
default:
break;
}
}//③来自contentfragment的进度条seek_bar事件处理
else if (intentFrom.equals("SeekBarChangeListener"))
{
int seek_bar=intent.getIntExtra("seek_bar", -1);
if (seek_bar==R.id.seek_bar)
{
int progress=intent.getIntExtra("progress", -1);//获取音乐进度
mPlayer.seekTo(progress);
currentProgress=mPlayer.getCurrentPosition();//获取音乐当前播放进度位置
}
}
}
}
/**
* 响应了收来自View控件的控制消息后,PlayerService的状态会改变
* 定时将PlayerService的新状态通过广播发送出去,让View接收并更新显示内容
* ***************************************************************************
*/
public class UpdateTrack extends Thread
{
int milliseconds;//更新音轨的间隔时间
public UpdateTrack(int ms)
{
this.milliseconds=ms;
}
@Override
public void run()
{
//如果mPlayer处于播放状态则更新音轨信息
while (isPlaying)
{
Log.d("UpdateTrack","UpdateTrack广播线程启动: "+isPlaying);
/**
* 注意线程安全:下面这句话留在这里会出现线程异常退出,说明log语句留在程序里有可能出问题
* //Log.d("UpdateTrack","mPlayer正在播放音乐吗: "+mPlayer.isPlaying());
*/
try
{
sleep(milliseconds);
currentProgress=mPlayer.getCurrentPosition();
} catch (Exception e)
{
e.printStackTrace();
Log.d("UpdateTrack","UpdateTrack广播线程异常");
}
/**
* 注意线程安全:下面这句话在这里会出现线程异常退出
* currentProgress=mPlayer.getCurrentPosition();
*/
mIntent.setData(nowPlayingUri);//存放当前播放音乐的Uri
mIntent.putExtra("isPlaying", isPlaying);//是否正在播放音乐
mIntent.putExtra("currentProgress", currentProgress);//存放当前音乐进度
mIntent.putExtra("duration", duration);//存放音乐文件长度
sendUpdateTrack_Broadcast();
Log.d("UpdateTrack","更新广播已经发送##############");
}
}
}
public void sendUpdateTrack_Broadcast()
{
sendBroadcast(mIntent);
}
public void startUpdateTrack(int milliseconds)
{
mUpdateTrack=new UpdateTrack(milliseconds);
mUpdateTrack.start();
}
//***************************************************************************
}
相关文章推荐
- 下拉数据过长被滚动条拦住的问题可以通过一个下拉展开事件去掉横向滚动条
- Android应用是否可以只有一个Service或Broadcast Reciver,而没有Activity?
- Android Handler机制 (一个Thead中可以建立多个Hander,通过msg.target保证MessageQueue中的每个msg交由发送message的handler进行处理 ,但是 每个线程中最多只有一个Looper,肯定也就一个MessageQuque)
- 线程间无需特别的手段进行通信,因为线程间可以共享数据结构,也就是一个全局变量可以被两个线程同时使用,不过要注意的是线程间需要做好同步。
- 关于android service生命周期里面值得注意的一个问题
- android--Service1(service不是一个单独的进程,也不是一个线程)
- 一个android列表的适配器数据异步加载的问题
- activity主窗口与软键盘的交互模式,可以用来避免输入法面板遮挡问题,Android1.5后的一个新特性。
- EventBus,一个可以在Activity、Fragment、Service之间传递任意类型数据的事件总线框架
- Android应用是否可以只有一个Service或Broadcast Reciver,而没有Activity?
- 一个socket连接、发送、接收数据失败后是否可以重新进行连接的问题
- 可以将线程内核对象视为由关于线程的统计信 息组成的一个小型数据结构
- 讨论一个并发线程导致的数据保存失败的问题
- Android的Activity启动长时间的操作开启一个Service比开启一个线程好
- Android应用是否可以只有一个Service或Broadcast Reciver,而没有Activity?
- 一个 android和js 数据交互的问题
- Android BindService中遇到的一个小问题
- 黑马程序员——java中两个线程对同一个数据做不同操作的安全问题
- 一个可以不传参数就可以在函数中改变调用者内部的变量数据的函数
- Android应用是否可以只有一个Service或Broadcast Reciver,而没有Activity?