当前位置: 代码迷 >> Android >> 一个没停止的android闹钟,一旦开始就要把歌唱完
  详细解决方案

一个没停止的android闹钟,一旦开始就要把歌唱完

热度:37   发布时间:2016-04-28 05:58:21.0
一个没有停止的android闹钟,一旦开始就要把歌唱完 .

现在工作的原因,又要重新学习android。就打算写个应用。恰好最近不想起床,创意就来了,写个闹钟,一旦开始唱歌,不唱完休想停下来。

我学这个东西的时候还是2.2,现在都4.3了,变了很多。还真有点不适应。所以花了一个晚上才搞定。

首先新建工程。不多说了。

然后写一个页面。很简单,就一个Button,一个TimePicker。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:gravity="center_vertical"    >    <TimePicker        android:id="@+id/timePicker"        android:layout_width="fill_parent"     	android:layout_height="wrap_content"     />    <Button  	android:id="@+id/timeBtn"        android:layout_width="fill_parent"         android:layout_height="wrap_content"         android:text="@string/done"        android:textSize="20sp"        android:onClick="setAlarm"    /></LinearLayout>

?

就像这样,线性布局,TimePicker在上,Button在下。我们要实现的就是上边选一个时间,然后点一下button,这个闹钟就在你设定的时间响起来,想停都停不了。

然后再onCreate里,把布局搞上去。

?

?

?

        @Override	protected void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		setContentView(R.layout.activity_main);		timePicker = (TimePicker)findViewById(R.id.timePicker);		time = (Button)findViewById(R.id.timeBtn);		timePicker.setIs24HourView(true);			}

?然后注册Button事件

 public void setAlarm(View view) {	     int hour = timePicker.getCurrentHour();	     int minu = timePicker.getCurrentMinute();	     Calendar cal = Calendar.getInstance();	     cal.set(Calendar.HOUR_OF_DAY, hour);	     cal.set(Calendar.MINUTE, minu);	     if(cal.before(Calendar.getInstance())){	    	 cal.add(Calendar.DATE, 1);	     }	     Toast.makeText(this, cal.getTime().toString(), Toast.LENGTH_LONG).show();	     alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);	     Intent intent = new Intent(this, AlarmReceiver.class);	     alarmIntent = PendingIntent.getBroadcast(this, 0, intent, 0);	     alarmMgr.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmIntent);	     /*alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),	    	        AlarmManager.INTERVAL_DAY, alarmIntent);*/	 }

?

首先从TimePicker中取到小时和分钟,分别是hour 和minu。

创建一个Calendar对象,然后把Calendar中的hour和minu替换成我们设置的时间,然后对现在的时间比较一下,如果在现在时间之后,就设置为calendar中储存的时间,如果是在之前,就把calendar中的时间加一天。

然后是闹钟比较重要的几个类。首先得到AlarmManager这个系统服务。然后创建一个PendingIntent,AlarmManager通过set方法设置唤醒方式,时间和到时候抛出的intent。

01.alarmMgr.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmIntent);  

?

RTC_WAKEUP代表绝对时间方式,切手机处于休眠状态时也会fire,第二个参数得到要fire的绝对时间,就是我们刚刚设置的时间,第三个参数是到时候抛出的intent。

代码跑到这里,intent应该能抛出来了,还得设计一个BroadcastRecevier来接这个Intent。认真看代码的应该已经看到了,这个intent已经写明白了,将被传递给AlarmReceiver.class,就是它。下面是代码:

@Override	public void onReceive(Context context, Intent intent) {		// TODO Auto-generated method stub		Log.d("REC", "The time is up,start the alarm...");		Toast.makeText(context, "This the time", Toast.LENGTH_LONG).show();		Intent serviceIntent = new Intent(context, MusicService.class);                          context.startService(serviceIntent); 	}

?

如果细心应该发现我在上一个代码段中有一行注释

 /*alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),	    	        AlarmManager.INTERVAL_DAY, alarmIntent);*/

?

这是官方的推荐方法。所以首先是用的这个,但是不知道为什么总是不成功。所以我还是得好好研究下。

回到原来话题,认真看下上边代码发现他够简单,只是打开了一个service。恩,播放音乐就放在这个service里边。

public class MusicService extends Service implements OnCompletionListener {	//为日志工具设置标签	private static String TAG = "MusicService";	//定义音乐播放器变量	private MediaPlayer mPlayer;		@Override	public void onCreate() {		// TODO Auto-generated method stub		Log.d(TAG, "MusicSerice onCreate()");		mPlayer = MediaPlayer.create(getApplicationContext(), R.raw.smoke);		mPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);		super.onCreate();	}	@Override	public int onStartCommand(Intent intent, int flags, int startId) {		// TODO Auto-generated method stub		Log.d(TAG, "MusicSerice onStart()");		mPlayer.start();		return super.onStartCommand(intent, flags, startId);	}	@Override	public void onDestroy() {		// TODO Auto-generated method stub		Log.d(TAG, "MusicSerice onDestroy()");		mPlayer.stop();		super.onDestroy();	}	public void onCompletion(MediaPlayer player) {		// TODO Auto-generated method stub		stopSelf();	}}

?

onCreate的时候创建MediaPlayer对象。onStartCommand时开始播放。onCompletion在播放完毕时调用,于是在这里stop这个service。很简单。

这么快,功能都实现了。

在设置里看到service并没有自己停掉,这个有点奇怪,需要重新研究下。

?

大意了。。忘记了给MediaPlayer注册Listener导致的onCompletion方法没有被调用,所以歌曲播放完毕后service并没有被停掉。修改后的service代码如下

@Overridepublic void onCreate() {	// TODO Auto-generated method stub	Log.e(TAG, "MusicSerice onCreate()");	mPlayer = MediaPlayer.create(getApplicationContext(), R.raw.smoke);	mPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);	<SPAN style="COLOR: #ff0000">mPlayer.setOnCompletionListener(this);</SPAN>	super.onCreate();}

?

大功告成。核心功能都实现了,就剩下交互设计和UI了。慢慢丰满吧。

?

PS:我是直接把音乐资源功能打包在apk里的,所以闹铃是不能换的,而我打包了一首Smoke on the water,每天早上都要被嘈杂的电吉他身影弄醒,痛苦不堪。

所以最后的结果是,我用了两天,早起了两天后,把这个应用卸载了。。。。。

?

  相关解决方案