Android节拍器&定时程序

      写完Java节拍器,本以为能够很容易的过渡到Android节拍器。后来发现不对。在网上查询了之后,才知道,Android考虑到线程安全问题,不允许在线程中执行UI线程。这里我们要学到一个Android中重要的类:android.os.Handler,这个可以实现各处线程间的消息传递。

      我们可以在原先的TimerTask子类MyTimerTask的方法run()中,只是给Handler发送一个Message。我们让Handler进行UI线程上的操作(在节拍器的例子中,指的是更新那个显示节拍的控件的数值)。

      最终节拍器打节拍的同时发生。(由于时间原因,音量控制尚未实现)实现截图如下:

 
    
 

 

package com.Android.Jiapaiqi;

import android.app.Activity;
import android.content.Context;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.SeekBar.OnSeekBarChangeListener;

import java.util.Timer;
import java.util.TimerTask;

public class ActivityMain extends Activity {
	
	Button button_start;
	Button button_stop;
	EditText edit_sudu;
	EditText edit_paishu;
	TextView result;
	SeekBar seekbar;
	public float tempo;
	public int section;
	public int pp;
	Handler handler;
	Timer mytimer;
	
	private SoundPool sndHigh;
	private SoundPool sndLow;
	private int hitOfHigh;
	private int hitOfLow;
	
	//声音控制
	private AudioManager audioManager;
	//声音变量
	private int volume=0;
	//声音模式
	//private int mode;
	//是否有声音
	private int flag=1;
	
	//内部类
	class MyTimerTask extends TimerTask{

		@Override
		public void run() {			
			Message message=new Message();
			message.what=1;
			handler.sendMessage(message);
		}	
	};
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        pp=1;
        setContentView(R.layout.main);
		
		final EditText edit_sudu = (EditText)this.findViewById(R.id.edit_sudu);
		final EditText edit_paishu = (EditText)this.findViewById(R.id.edit_paishu);
		final TextView result = (TextView)findViewById(R.id.result);
		
		handler = new Handler()
		{
			public void handleMessage(Message msg)
			{
				switch(msg.what)
				{
				case 1:
					result.setText(String.valueOf(pp));
						if(pp==1)
							// play (int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate)
							//播放音频,可以对左右音量分别设置,还可以设置优先级,循环次数以及速率
							sndHigh.play(hitOfHigh, 1, 1, 0, 0, 1);
						else
							sndLow.play(hitOfLow, 1, 1, 0, 0, 1);
					if(pp!=section)
					{
						pp++;
					}
					else
					{
						pp=1;
					}
						break;
				}
				super.handleMessage(msg);
			}
		};
		
		button_start = (Button) findViewById(R.id.button_start);
		button_start.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				tempo=Float.parseFloat(edit_sudu.getText().toString()); 
				section=Integer.parseInt(edit_paishu.getText().toString()); 
				mytimer=new Timer();
				float tempFloat=60/tempo*1000;
				mytimer.schedule(new MyTimerTask(),0, (long)tempFloat);
			}
		});
			
		button_stop = (Button) findViewById(R.id.button_stop);
		button_stop.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				mytimer.cancel();
				sndHigh.pause(hitOfHigh);
				sndLow.pause(hitOfLow);
			}
		});
			
		final SeekBar seekbar = (SeekBar) findViewById(R.id.seekbar);
		//设置拖动条的初始值和文本框的初始值
		seekbar.setMax(7);
		seekbar.setProgress(5);
		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
			}
		});
		audioManager = (AudioManager) getBaseContext().getSystemService(Context.AUDIO_SERVICE);
		//通过getStreamVolume获得当前音量大小
		volume=audioManager.getStreamVolume(AudioManager.STREAM_RING);
		//把当前音量的值 设置给进度条
		//seekbar.setProgress(volume);
		
		sndHigh = new SoundPool(10, AudioManager.STREAM_SYSTEM,5);
		//载入音频流
		hitOfHigh = sndHigh.load(getBaseContext(), R.drawable.high, 0);
		
		sndLow = new SoundPool(10, AudioManager.STREAM_SYSTEM,5);
		//载入音频流
		hitOfLow = sndLow.load(getBaseContext(), R.drawable.low, 0);
    }
}

 

再给出一篇比较好的文章:

Android计时器正确应用方式解析

http://developer.51cto.com/art/201001/180254.htm

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Android Studio中实现节拍器功能,可以按照以下步骤进行操作: 1. 创建一个新的Android项目或打开现有项目。 2. 在项目的布局文件中添加一个按钮和一个文本视图,用于控制和显示节拍器的信息。 3. 在活动类中找到按钮的引用,并设置一个点击事件监听器。 4. 在点击事件监听器中初始化一个计时器,并设置计时器的定时任务。 5. 在定时任务中执行节拍器的逻辑。可以使用`MediaPlayer`类播放声音或使用`Vibrator`类控制震动。 下面是一个简单的示例代码: ```java public class MainActivity extends AppCompatActivity { private Button startButton; private TextView beatTextView; private Timer timer; private int beatCount; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startButton = findViewById(R.id.start_button); beatTextView = findViewById(R.id.beat_textview); startButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startMetronome(); } }); } private void startMetronome() { if (timer != null) { timer.cancel(); } timer = new Timer(); beatCount = 0; TimerTask timerTask = new TimerTask() { @Override public void run() { // 执行节拍器逻辑 beatCount++; playSound(); // 播放声音或控制震动 updateBeatCount(); } }; // 以1000毫秒为间隔执行定时任务 timer.scheduleAtFixedRate(timerTask, 0, 1000); } private void playSound() { // 在这里实现播放声音或控制震动的逻辑 } private void updateBeatCount() { runOnUiThread(new Runnable() { @Override public void run() { beatTextView.setText("当前节拍数:" + beatCount); } }); } } ``` 请注意,上述代码只是一个简单的示例,你还需要根据自己的需求进行更多的定制和扩展。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值