Android开发之倒计时应用(三)

如需转载,请注明出处,谢谢!



这篇文章是主要是把剩下的Service和BroadcastReceiver讲完,即倒计时的具体实现。因为代码中有一些比较细节的地方,我讲得不够清楚的欢迎提问。

我写了一个继承自Service的TimerService类,除了默认要实现的onBind方法外,还重写了onCreate、onStartCommand、onDestroy方法。

onCreate方法中主要做一些初始化的操作:

@Override
public void onCreate() {
	super.onCreate();
	mTimer = new Timer();
	preferences = getSharedPreferences(ConstantUtil.PREFERENCE, Context.MODE_PRIVATE);
}

需要注意的是,这里的preference与MainActivity中的preference不是同一个。在这里顺带讲一下Sharedpreferences:

Sharedpreferences本身是一个接口,可通过以下几个方法获得:

getPreferences(int mode);  // 只属于该Activity,一个Activity只有一个

PreferenceManager.getDefaultSharedPreferences(this); // 属于整个应用程序,只有一个

getSharedpreferences(String name, int mode); // 属于整个应用程序,可以有多个

这里用到preference的原因下面会讲到。


onDestroy方法主要做一些变量的销毁,没什么好讲的。

@Override
public void onDestroy() {
	super.onDestroy();
	if (mTimer != null) {
		mTimer = null;
	}
	if (mTask != null) {
		mTask.cancel();
		mTask = null;
	}
	if (preferences != null) {
		preferences = null;
	}
}

主要的代码在 onStartCommand中:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
	// 必须判断一下,否则可能导致程序无法运行
	if (intent == null) {
		return super.onStartCommand(intent, flags, startId);
	}
	String action = intent.getAction();
	if (action.equals(ConstantUtil.START)) {
		currentProgress = intent.getIntExtra(ConstantUtil.CURRENT_PROGRESS, 0);
		progress = intent.getIntExtra(ConstantUtil.PROGRESS, 0);
		start();
	} else if (action.equals(ConstantUtil.PAUSE)) {
		pause();
	} else if (action.equals(ConstantUtil.STOP)) {
		stop();
	}
	return super.onStartCommand(intent, flags, startId);
}


接下来分别讲start、pause和stop方法。

程序中可能会出现这种情况:倒计时任务正在进行,但用户继续点击开始按钮,因此在这里先判断一下mTask是否为空再进一步操作。(为了防止这种情况出现,也可以让任务在进行的时候讲开始按钮设置为不可点击。)然后再通过mTimer启动mTask任务进行倒计时。关于Timer和TimerTask,这里就不做介绍了。

private void start() {
	// 有任务正在进行,发送广播通知Activity
	if (mTask != null) {
		Intent intent = new Intent(ConstantUtil.ALREADY_RUN);
		sendBroadcast(intent);
		return;
	}
	mTask = new MyTimerTask();
	mTimer.schedule(mTask, 1000, 1000);
}

pause方法中,我没找到可以使TimerTask暂停的方法,所以就直接cancel掉了,然后把状态保存下来。

private void pause() {
	if (mTask != null) {
		mTask.cancel();
		mTask = null;
	}
	// 将当前进度发回activity保存
	Intent intent = new Intent(ConstantUtil.PAUSE);
	intent.putExtra(ConstantUtil.CURRENT_PROGRESS, currentProgress);
	sendBroadcast(intent);
}

关于stop方法,这里指的是点击停止按钮强行停止倒计时。
/**
 * 人为停止计时器
 */
private void stop() {
	if (mTask != null) {
		mTask.cancel();
		mTask = null;
	}
}


说了那么久的TimerTask在这里终于要来啦!这也是倒计时的主要实现,但其实代码很简单的!

private class MyTimerTask extends TimerTask {

	@Override
	public void run() {
		if (++currentProgress >= progress) {
			timeout();
		} else {
			running();
		}
	}
}

running方法中,只是向Activity发送广播,通知Activity更新UI

private void running() {
	// 发送广播使activity更新UI
	Intent intent = new Intent(ConstantUtil.RUNNING);
	intent.putExtra(ConstantUtil.CURRENT_PROGRESS, currentProgress);
	sendBroadcast(intent);
}

timeout方法中要做的工作就比较多了,上面在onCreate方法中声明的preferences在这里就要用到了。
/**
 * 倒计时完成,停止计时器
 */
private void timeout() {
	if (mTask != null) {
		mTask.cancel();
		mTask = null;
	}
		
	Intent intent = new Intent(ConstantUtil.TIMEOUT);
	sendBroadcast(intent);
		
	// 当activity无法收到倒计时完成的消息时,将停止状态保存在sharedpreference中
	// activity再次启动时便可以判断倒计时是否已完成
	Editor editor = preferences.edit();
	editor.putBoolean(ConstantUtil.STOP, true);
	editor.commit();
		
	// 创建通知
	createNotification();
}

private void createNotification() {
	Intent contentIntent = new Intent();
	contentIntent.setClass(this, MainActivity.class);
	PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, contentIntent, 0);
		
	if (MainActivity.isDestroy) {
		NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		Notification notification = new Notification.Builder(getApplicationContext())
		.setContentTitle("Timeout")
		.setContentText("恭喜你,消耗了" +progress +"秒")
		.setSmallIcon(R.drawable.ic_launcher)
		.setContentIntent(pendingIntent)
		.setAutoCancel(true)
		.build();
			
		mNotificationManager.notify(0, notification);
	}
		
	// 发出系统通知声音和调用震动
	ringAndVibrator();
}

private void ringAndVibrator() {
	// 控制震动
	Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
	long pattern[] = {100, 300, 100, 400};
	vibrator.vibrate(pattern, -1);
		
	// 获取系统通知声音
	Uri alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);  
        MediaPlayer player = new MediaPlayer();  
        try {
		player.setDataSource(this, alert);
	} catch (Exception e) {
		e.printStackTrace();
	} 
        final AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);  
        if (audioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION) != 0) {  
        	player.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);  
        	player.setLooping(false);  
        	try {
        		player.prepare();
        	} catch (Exception e) {
        		e.printStackTrace();
        	}
        	player.start();  
        }  
}

在service中发送的广播都是发给Activity的,因此,在Activity中创建一个BroadcastReceiver,然后在onCreate中注册并在onDestroy中注销掉。

private class ServiceReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		String action = intent.getAction();
		if (action.equals(ConstantUtil.ALREADY_RUN)) {
			toast = Toast.makeText(getApplicationContext(), "任务正在进行中...", SHORT);
			toast.show();
		} else if (action.equals(ConstantUtil.PAUSE)) {
			int data = intent.getIntExtra(ConstantUtil.CURRENT_PROGRESS, 0);
			currentProgress = data;
		} else if (action.equals(ConstantUtil.RUNNING)) {
			int data = intent.getIntExtra(ConstantUtil.CURRENT_PROGRESS, 0);
			currentProgress = data;
			showView.setText((progress - currentProgress) + "");
		} else if (action.equals(ConstantUtil.TIMEOUT)) {
			currentProgress = 0;
			showView.setText(getResources().getString(R.string.default_text));
			AlertDialog dialog = new AlertDialog.Builder(MainActivity.this)
			.setTitle("Timeout")
			.setMessage("恭喜你消耗了" + progress + "秒")
			.setPositiveButton("好的", null)
			.create();
			dialog.show();
		}
	}
		
}

好了,到了这里,整个应用就算完成了!

附上源码链接: 源码下载

如果发现Bug或者是对代码的实现有什么建议,欢迎大家指出来~~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值