代码已经托管到码云上,有兴趣的小伙伴可以下载看看

https://git.oschina.net/joy_yuan/MobilePlayer

先来一张目前的音乐播放器的效果图,当播放时,手机的状态通知栏也会有音乐信息显示。

这里可以看到有歌名、演唱者,还有歌曲的总时间,当前播放时间,当前播放进度,音乐暂停、下一首,上一首,音乐循环模式(单曲循环,顺序播放、循环播放)功能的实现。下一步就是把中间空白的部分填充歌词,然后做成根据进度显示歌词。

由于这次的内容有点多,是写了一天半的代码,讲的没那么细,具体的代码可以去下载源码看下。

一、要想做成即使推出播放器后(不是杀死进程),音乐播放器继续播放,那么就不能在activity里进行播放音乐,需要在service里播放音乐

1、aidl的使用,来连接activity和service。

这个aidl有点类似service的接口。

其实用来连接activity和service也可以用内部类IBindler 来做,具体的可以看我前面写的博客,四大组件之service,里面有详细写activity绑定service。

// IMusicPlayerService.aidl
package com.yuanlp.mobileplayer;// Declare any non-default types here with import statementsinterface IMusicPlayerService {/*** 根据对应位置打开音乐* @param position*/void openAudio(int position);/*** 播放音乐*/void startAudio();/*** 暂停音乐*/void pauseAudio();/*** 停止音乐*/void stopAudio();/*** 得到当前播放进度* @return*/int getCurrentPosition();/*** 得到总时长* @return*/long getDuration();/*** 得到演唱者* @return*/String getSinger();/*** 得到音乐大小* @return*/long getSize();/*** 得到歌名* @return*/String getSong();/*** 得到路径* @return*/String getAudioPath();/*** 得到下一首*/void getNext();/*** 得到上一首*/void getPre();/*** 设置播放模式* @param playMode*/void setPlayMode(int playMode);/*** 得到播放模式*/int  getPlayMode();/*** 是否播放*/boolean isPlaying();void seekTo(int progress);
}

2 、创建service,第一种可以直接写类,然后继承Service,需要手动重写oncreate()和onBind()方法,然后还要在AndroidManifext.xml里注册这个类;第二种,右键new一个service,这样就不用去重写方法,以及去注册了,因为IDE会自动帮我们做好。

package com.yuanlp.mobileplayer.service;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.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.RequiresApi;
import android.util.Log;import com.yuanlp.mobileplayer.IMusicPlayerService;
import com.yuanlp.mobileplayer.R;
import com.yuanlp.mobileplayer.activity.AudioPlayerAcivity;
import com.yuanlp.mobileplayer.bean.MediaItem;
import com.yuanlp.mobileplayer.utils.CacheUtils;import java.io.IOException;
import java.util.ArrayList;public class MusicPlayerService extends Service {private static final String TAG = "MusicPlayerService";public static final String OPENAUDIOPLAYER = "com.yuanlp.mobilePlayer_openAudioPlayer";private int position;private ArrayList<MediaItem> medialist;private MediaItem item;private MediaPlayer mediaPlayer;private NotificationManager manger;  //状态栏通知管理器public static final int REPEAT_NORMAL=1;  //默认播放模式,即顺序播放public static final int REPEAT_SINGLE=2;  //单曲循环public static final int REPEAT_ALL=3;  //循环播放private int playMode=REPEAT_NORMAL;  //播放模式public MusicPlayerService() {}@Overridepublic void onCreate() {super.onCreate();playMode=CacheUtils.getPlayMode(this,"playmode");}/***    在这里获取aidl的实例,需要在onBind()方法里返回这个实例。onBind()方法在activity与service绑定时自动调用。**/private IMusicPlayerService.Stub stub=new IMusicPlayerService.Stub() {MusicPlayerService service=MusicPlayerService.this;@Overridepublic void openAudio(int position) throws RemoteException {System.out.println("调取了内部的方法传递position为"+position);service.openAudio(position);}@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)@Overridepublic void startAudio() throws RemoteException {service.startAudio();}@Overridepublic void pauseAudio() throws RemoteException {service.pauseAudio();}@Overridepublic void stopAudio() throws RemoteException {service.stopAudio();}@Overridepublic int getCurrentPosition() throws RemoteException {return service.getCurrentPosition();}@Overridepublic long getDuration() throws RemoteException {return service.getDuration();}@Overridepublic String getSinger() throws RemoteException {return service.getSinger();}@Overridepublic long getSize() throws RemoteException {return service.getSize();}@Overridepublic String getSong() throws RemoteException {return service.getSong();}@Overridepublic String getAudioPath() throws RemoteException {return service.getAudioPath();}@Overridepublic void getNext() throws RemoteException {service.getNext();}@Overridepublic void getPre() throws RemoteException {service.getPre();}@Overridepublic void setPlayMode(int playMode) throws RemoteException {service.setPlayMode(playMode);}@Overridepublic int getPlayMode() throws RemoteException {return service.getPlayMode();}/*** 是否播放*/@Overridepublic boolean isPlaying() throws RemoteException {return service.isPlaying();}//把进度条调整到progress的位置public void seekTo(int progress){service.seekTo(progress);}};//  public class Mybinder extends Binder{
//      public MusicPlayerService getService(){
//          return MusicPlayerService.this;
//      }
//  }
//
//  public Mybinder binder=new Mybinder();
//    @Override
//    public IBinder onBind(Intent intent) {
//
//        return binder;
//
//    }@Overridepublic IBinder onBind(Intent intent) {System.out.println("绑定了服务------------");//当绑定时,获取activity通过intent传过来的序列化的list数据。medialist= (ArrayList<MediaItem>) intent.getSerializableExtra("medialist");System.out.println("获取服务里的数据。。。"+medialist.size());return stub;}/*** 根据对应位置打开音乐* @param position*/private void openAudio(int position){this.position=position;Log.d(TAG, "openAudio:当前位置 "+position);item=medialist.get(position);Log.d(TAG, "openAudio: 当前位置对应的歌名"+item.getName());if (mediaPlayer!=null){mediaPlayer.reset();mediaPlayer=null;}try {mediaPlayer=new MediaPlayer();mediaPlayer.setOnPreparedListener(new MyOnPreparedListener());mediaPlayer.setOnCompletionListener(new MyOnCompletionListener());mediaPlayer.setOnErrorListener(new MyOnErrorListener());mediaPlayer.setDataSource(item.getData());mediaPlayer.prepareAsync();} catch (IOException e) {e.printStackTrace();}}/*** 播放出错时回调*/class MyOnErrorListener implements MediaPlayer.OnErrorListener {@Overridepublic boolean onError(MediaPlayer mp, int what, int extra) {getNext();return true;}}/*** 播放完成时*/class MyOnCompletionListener implements MediaPlayer.OnCompletionListener {@Overridepublic void onCompletion(MediaPlayer mp) {getNext();}}/*** 准备好播放时回调*/class MyOnPreparedListener implements MediaPlayer.OnPreparedListener {@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)@Overridepublic void onPrepared(MediaPlayer mp) {startAudio();//在这里发送广播,通知activity,播放的进度、音乐名称、歌唱家等信息notifyChange(OPENAUDIOPLAYER);}}/*** 发送广播通知activity* @param openaudioplayer*/private void notifyChange(String openaudioplayer) {Intent intent=new Intent(openaudioplayer);sendBroadcast(intent);}/*** 播放音乐*/@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)public void startAudio(){mediaPlayer.start();manger= (NotificationManager) getSystemService(NOTIFICATION_SERVICE);  //获取系统的通知服务//Notification notifaction= null;Intent intent=new Intent(this, AudioPlayerAcivity.class);  //点击通知栏后,打开activity音乐界面Bundle bundle=new Bundle();bundle.putSerializable("mediallist",medialist);intent.putExtras(bundle); //把list数据回传给activity,不然会报错intent.putExtra("Notifaction",true);  //标识来自状态PendingIntent pendingintent=PendingIntent.getActivity(this,1,intent,PendingIntent.FLAG_UPDATE_CURRENT);Notification notifaction = new Notification.Builder(this).setSmallIcon(R.drawable.notification_music_playing).setContentTitle("原立鹏音乐播放器")  //状态通知栏标题.setContentText("正在播放:"+getSong())  //状态通知栏内容.setContentIntent(pendingintent).build();  //这个一定要写最后面,不然会出错manger.notify(1,notifaction);  //显示状态栏}/*** 暂停音乐*/public void pauseAudio(){mediaPlayer.pause();//停止播放时取消状态栏manger.cancel(1);}/*** 停止音乐*/public void stopAudio(){mediaPlayer.stop();}/*** 得到当前播放进度* @return*/public int getCurrentPosition(){return mediaPlayer.getCurrentPosition();}/*** 得到总时长* @return*/public long getDuration(){return mediaPlayer.getDuration();}/*** 得到演唱者* @return*/public String getSinger(){return item.getArtist();}/*** 得到音乐大小* @return*/public long getSize(){return item.getSize();}/*** 得到歌名* @return*/public String getSong(){return item.getName();}/*** 得到路径* @return*/public String getAudioPath(){return item.getData();}/*** 得到下一首*/public void getNext(){}/*** 得到上一首*/public void getPre(){}/*** 设置播放模式,并将播放模式写到sharepreferences里,记忆用户播放模式* @param playMode*/public void setPlayMode(int playMode){this.playMode=playMode;CacheUtils.putPlayMode(this,"playmode",playMode);}/*** 得到播放模式*/public int getPlayMode(){return playMode;}public boolean isPlaying(){return mediaPlayer.isPlaying();}public void seekTo(int progress){mediaPlayer.seekTo(progress);}
}

二、在activity里,接收audiopager传过来的list数据,并绑定服务,在绑定服务时,通过intent将list数据传给service;在开始播放音乐时,接收service发出的广播,来更新页面显示的歌名、时间等信息,并在handler里每秒刷新下时间。

package com.yuanlp.mobileplayer.activity;import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.graphics.drawable.AnimationDrawable;
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.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;import com.yuanlp.mobileplayer.IMusicPlayerService;
import com.yuanlp.mobileplayer.R;
import com.yuanlp.mobileplayer.bean.MediaItem;
import com.yuanlp.mobileplayer.service.MusicPlayerService;
import com.yuanlp.mobileplayer.utils.Utils;import java.util.ArrayList;import static android.content.ContentValues.TAG;/*** Created by 原立鹏 on 2017/7/27.*/public class AudioPlayerAcivity extends Activity implements View.OnClickListener {private static final int UPDATE_SEEKBAR = 0;  //更新进度条时的handler消息private ImageView iv_play_icon;private int position;  //获取从audiopager中从intent传过来的位置信息private ArrayList<MediaItem> medialist;private IMusicPlayerService mservice;private ImageView ivPlayIcon;private TextView tvSigner;private TextView tvSong;private TextView tvTime;private SeekBar seekbarAudio;private Button btAudioMode;private Button btAudioPre;private Button btAudioStartPause;private Button btAudioNext;private Button btLyrc;private boolean isPlaying;private MyBroadcast broadcast; //广播类实例private Utils utils;private boolean isNotifaction;  //判断是否是从notifaction那里传过来的intentprivate int currentposition;/*** Find the Views in the layout<br />* <br />* Auto-created on 2017-07-28 08:54:55 by Android Layout Finder* (http://www.buzzingandroid.com/tools/android-layout-finder)*/private void findViews() {System.out.println("初始化数据");ivPlayIcon = (ImageView)findViewById( R.id.iv_play_icon );tvSigner = (TextView)findViewById( R.id.tv_signer );tvSong = (TextView)findViewById( R.id.tv_song );tvTime = (TextView)findViewById( R.id.tv_time );seekbarAudio = (SeekBar)findViewById( R.id.seekbar_audio );btAudioMode = (Button)findViewById( R.id.bt_audio_mode );btAudioPre = (Button)findViewById( R.id.bt_audio_pre );btAudioStartPause = (Button)findViewById( R.id.bt_audio_start_pause );btAudioNext = (Button)findViewById( R.id.bt_audio_next );btLyrc = (Button)findViewById( R.id.bt_lyrc );btAudioMode.setOnClickListener( this );btAudioPre.setOnClickListener( this );btAudioStartPause.setOnClickListener( this );btAudioNext.setOnClickListener( this );btLyrc.setOnClickListener( this );}/*** Handle button click events<br />* <br />* Auto-created on 2017-07-28 08:54:55 by Android Layout Finder* (http://www.buzzingandroid.com/tools/android-layout-finder)*/@Overridepublic void onClick(View v) {if ( v == btAudioMode ) {// Handle clicks for btAudioModegetPlayMode();  //设置播放模式} else if ( v == btAudioPre ) {// Handle clicks for btAudioPreposition-=1;if (position<0){position=medialist.size()-1;}try {MediaItem item=medialist.get(position);tvSigner.setText(item.getArtist());tvSong.setText(item.getName());mservice.openAudio(position);} catch (RemoteException e) {e.printStackTrace();}} else if ( v == btAudioStartPause ) {try {isPlaying=mservice.isPlaying();if (isPlaying){  //表示此时在播放,应该把图片切换为播放界面,然后暂停播放mservice.pauseAudio();btAudioStartPause.setBackgroundResource(R.drawable.bt_audio_start_selector);}else{mservice.startAudio();btAudioStartPause.setBackgroundResource(R.drawable.bt_audio_pause_selector);}} catch (RemoteException e) {e.printStackTrace();}// Handle clicks for btAudioStartPause} else if ( v == btAudioNext ) {// Handle clicks for btAudioNextposition+=1;if (position>=medialist.size()){position=0;}try {MediaItem item=medialist.get(position);tvSigner.setText(item.getArtist());tvSong.setText(item.getName());mservice.openAudio(position);} catch (RemoteException e) {e.printStackTrace();}} else if ( v == btLyrc ) {// Handle clicks for btLyrc}}private void getPlayMode() {try {int playMode=mservice.getPlayMode();if (playMode==MusicPlayerService.REPEAT_NORMAL){playMode=MusicPlayerService.REPEAT_SINGLE;  //切换为单曲循环,并把按钮图片切换}else if (playMode==MusicPlayerService.REPEAT_SINGLE){playMode=MusicPlayerService.REPEAT_ALL;  //如果为单曲循环,切换为循环播放}else if (playMode==MusicPlayerService.REPEAT_ALL){playMode=MusicPlayerService.REPEAT_NORMAL; //如果为循环播放,则切换为顺序播放,播放全部后,停止播放}else {playMode=MusicPlayerService.REPEAT_NORMAL; //如果为循环播放,则切换为顺序播放,播放全部后,停止播放}mservice.setPlayMode(playMode);setPlayMode();} catch (RemoteException e) {e.printStackTrace();}}private void setPlayMode() {try {int playMode=mservice.getPlayMode();if (playMode==MusicPlayerService.REPEAT_NORMAL){btAudioMode.setBackgroundResource(R.drawable.bt_audio_mode_normal_selector);Toast.makeText(this,"顺序播放",Toast.LENGTH_SHORT).show();}else if (playMode==MusicPlayerService.REPEAT_SINGLE){btAudioMode.setBackgroundResource(R.drawable.bt_audio_mode_single_selector);Toast.makeText(this,"单曲循环",Toast.LENGTH_SHORT).show();}else if (playMode==MusicPlayerService.REPEAT_ALL){btAudioMode.setBackgroundResource(R.drawable.bt_audio_mode_all_selector);Toast.makeText(this,"循环播放",Toast.LENGTH_SHORT).show();}} catch (RemoteException e) {e.printStackTrace();}}public void checkPlayMode(){try {int playMode=mservice.getPlayMode();if (playMode==MusicPlayerService.REPEAT_NORMAL){btAudioMode.setBackgroundResource(R.drawable.bt_audio_mode_normal_selector);}else if (playMode==MusicPlayerService.REPEAT_SINGLE){btAudioMode.setBackgroundResource(R.drawable.bt_audio_mode_single_selector);}else if (playMode==MusicPlayerService.REPEAT_ALL){btAudioMode.setBackgroundResource(R.drawable.bt_audio_mode_all_selector);}} catch (RemoteException e) {e.printStackTrace();}}Handler handler=new Handler(){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what){case UPDATE_SEEKBAR://1 得到当前进度try {int currentPosition=mservice.getCurrentPosition();seekbarAudio.setProgress(currentPosition);String time=utils.stringForTime(currentPosition)+"/"+utils.stringForTime((int) mservice.getDuration());tvTime.setText(time);handler.removeMessages(UPDATE_SEEKBAR);/*** 每秒刷新下进度条*/handler.sendEmptyMessageDelayed(UPDATE_SEEKBAR,1000);} catch (RemoteException e) {e.printStackTrace();}break;}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Log.d(TAG, "onCreate: 音乐播放activity被创建了");System.out.println("音乐播放activity被创建了");setContentView(R.layout.activity_audioplayer);utils=new Utils();/*** 初始化音乐界面的图片变化的布局*/initView();/*** 实例化布局里的各个控件*/findViews();//注册广播registerBorader();/*** 根据位置获取音乐*/getData();/*** 绑定服务并启动服务*/bindAndStartService();seekbarAudio.setOnSeekBarChangeListener(new MyOnSeekBarChangeListener());}class MyOnSeekBarChangeListener implements SeekBar.OnSeekBarChangeListener {@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {if (fromUser){try {mservice.seekTo(progress);} catch (RemoteException e) {e.printStackTrace();}}}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}}private void bindAndStartService() {System.out.println("绑定服务 bindService。。。。。。");Intent intent=new Intent(this, MusicPlayerService.class);//intent.setAction("com.yuanlp.mobilePlayer");Bundle bundle=new Bundle();bundle.putSerializable("medialist",medialist);intent.putExtras(bundle);startService(intent);  //不至于多次实例化服务对象//System.out.println("数量是多少"+medialist.size());bindService(intent,conn,BIND_AUTO_CREATE);System.out.println("绑定后,再启动服务");// Bundle bundle=new Bundle();startService(intent);  //不至于多次实例化服务对象//        bundle.putSerializable("medialist",medialist);
//        intent.putExtras(bundle);}/*** 与服务创建连接*/private ServiceConnection conn=new ServiceConnection() {/*** 当连接成功时,回调方法* @param name* @param service*/@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {System.out.println("成功连接。。。");mservice=IMusicPlayerService.Stub.asInterface(service);if (mservice!=null){try {if (!isNotifaction){  //不是 从状态栏里过来的,是从列表过来的,那么重新播放System.out.println("成功连接后,service不为空");mservice.openAudio(position);}else{showViewData();}
//                    MediaItem item=medialist.get(position);
//                    String artist=item.getArtist();
//                    String song=item.getName();
//                    tvSigner.setText(artist);
//                    tvSong.setText(song);} catch (RemoteException e) {e.printStackTrace();}}}/*** 当连接失败时回调方法* @param name*/@Overridepublic void onServiceDisconnected(ComponentName name) {System.out.println("连接失败。。。");try {if (mservice!=null){mservice.stopAudio();mservice=null;}} catch (RemoteException e) {e.printStackTrace();}}};private void getData() {System.out.println("获取数据------");medialist=new ArrayList<MediaItem>();medialist= (ArrayList<MediaItem>) getIntent().getSerializableExtra("mediallist");System.out.println("当前的list数量------------------------"+medialist.size());//得到intent的数据isNotifaction = getIntent().getBooleanExtra("Notifaction",false);if (!isNotifaction){position = getIntent().getIntExtra("position", 0);}//currentposition = getIntent().getIntExtra("currentPosition",0);System.out.println("传到activity里获取的当前进度isNotifaction是------------"+isNotifaction);}private void initView() {System.out.println("初始化跳动的图片");iv_play_icon= (ImageView) findViewById(R.id.iv_play_icon);iv_play_icon.setBackgroundResource(R.drawable.animation_list);AnimationDrawable rocketAnimation= (AnimationDrawable) iv_play_icon.getBackground();rocketAnimation.start();}/*** 广播接收,接受来自service里开始播放后发送的广播*/class MyBroadcast extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {/*** 接收到广播后,显示歌曲名、歌曲时间等信息*/showViewData();checkPlayMode();}}/*** 接收到广播后,显示歌曲名、歌曲时间等信息*/private void showViewData() {try {tvSigner.setText(mservice.getSinger());tvSong.setText(mservice.getSong());//设置进度条seekbarAudio.setMax((int) mservice.getDuration());handler.sendEmptyMessage(UPDATE_SEEKBAR);} catch (RemoteException e) {e.printStackTrace();}}/*** 注册广播,接收service发送的广播*/private void registerBorader() {System.out.println("注册广播");broadcast=new MyBroadcast();IntentFilter intentfilter=new IntentFilter();intentfilter.addAction(MusicPlayerService.OPENAUDIOPLAYER);registerReceiver(broadcast,intentfilter);}/*** 在onDestroy里取消注册广播*/@Overrideprotected void onDestroy() {handler.removeCallbacksAndMessages(null);  //推出activity时,移除所有消息if (broadcast!=null){unregisterReceiver(broadcast);broadcast=null;  //这里为什么把广播设置为null,因为取消注册后,垃圾回收器不一定马上回收广播,如果设置为null,那么会优先回收这个}super.onDestroy();}
}

转载于:https://blog.51cto.com/cm0425/1951857

手机影音第十五天,利用service实现后台播放音乐,在通知栏显示当前音乐信息等...相关推荐

  1. 55.深度解密五十五:利用互联网思维进行实体行业“吸粉和变现”(实用性)

    网络营销推广技术.技巧深度解密(五十五)指南: 1.本文档适合零基础以及互联网营销推广工作者,主要讲解实体行业微信吸粉和变现的另类操作问题. 2.原创版权文档,任何抄袭或者全部.部分模仿都是侵权行为. ...

  2. Android 通过蒲公英pgyer的接口 Service 实现带进度下载App 通知栏显示 在线更新 自动更新Demo

    Android 通过蒲公英pgyer的接口 Service 实现带进度下载App 通知栏显示 在线更新 自动更新Demo 标签: app在线更新下载Update升级 2016-09-18 20:47  ...

  3. Android开发笔记(一百六十五)利用红外发射遥控电器

    红外遥控是一种无线控制技术,它具有功耗小.成本低.易实现等诸多优点,因而被各种电子设备特别是家用电器广泛采用,像日常生活中的电视遥控器.空调遥控器等等基本都采用红外遥控技术. 不过遥控器并不都是红外遥 ...

  4. 网易云视频播放器不使用Service实现后台播放

    最近在一家公司实习,要求我在Android上找到播放器实现后台播放的方法,通过研究网易云视频中的播放器,我找到了其中的方法,虽然我觉得网易的方法有点取巧. 1.  问题描述 网易云视频播放器在播放过程 ...

  5. Android开发笔记(一百七十五)利用Room简化数据库操作

    虽然Android提供了数据库帮助器,但是开发者在进行数据库编程时仍有诸多不便,比如每次增加一张新表,开发者都得手工实现以下代码逻辑: 1.重写数据库帮助器的onCreate方法,添加该表的建表语句: ...

  6. Android开发笔记(一百五十五)利用GL10描绘点、线、面

    上一篇文章介绍了GL10的常用方法,包括如何设置颜色.如何指定坐标系.如何调整镜头参数.如何挪动观测方位等等,不过这些方法只是绘图前的准备工作,真正描绘点.线.面的制图工作并未涉及,那么本文就来谈谈如 ...

  7. 第二十五篇、基于Arduino uno,获取max30205人体温度传感器的温度信息——结果导向

    0.结果 说明:先来看看串口调试助手显示的结果,显示的是温度值,因为是接触式传感器,可以测量人体体温,如果不接触,测量的就是空气温度.如果是你想要的,可以接着往下看. 1.外观 说明:虽然max302 ...

  8. Android使用本地Service实现后台播放音乐

    配置文件 <service android:name=".MyService"></service> 布局 <Buttonandroid:id=&qu ...

  9. opengl正方形绕点旋转_一题十五种解法够不够? 旋转,构造,四点共圆乐不停...

    平移,旋转,轴对称是我们初中学习的"几何三大变换".在我们初中阶段学习的几何知识中占据着核心的地位,特别是旋转,那更是核心中的核心(河南中考22题年年考). 如何更好的理解旋转,如 ...

  10. SAP UI5 应用开发教程之八十五 - 如何用 OPA5 编写测试用例来测试用户输入文本的功能试读版

    一套适合 SAP UI5 初学者循序渐进的学习教程 作者简介 Jerry Wang,2007 年从电子科技大学计算机专业硕士毕业后加入 SAP 成都研究院工作至今.Jerry 是 SAP 社区导师,S ...

最新文章

  1. JAVA - HashMap和HashTable
  2. 流API--使用并行流
  3. 【计算机网络】数据链路层 : 概述 ( 基本概念 | 功能 | 为 “网络层“ 提供的服务 )
  4. centos -bash-4.1$ 不显示用户名路径
  5. Could not load JDBC driver class [com.mysql.jdbc.Driver]
  6. SpringBoot 3.0最低版本要求的JDK 17,这几个新特性不能不知道!
  7. 活动目录建立IIS站点
  8. 利用CSS3 animation绘制动态卡通人物,无需使用JS代码
  9. 德鲁克:终生难忘的7堂课
  10. Edraw Max 9.x 安装
  11. 青岛理工计算机网络期末试题,青岛理工大学计算机网络试题2008~2009
  12. 详谈软件工程之软件开发方法(一)
  13. starUML4.0导出的图片去除水印的方法
  14. 10分钟教你用Python实现微信翻译机器人
  15. span标签的使用场景
  16. 鸿蒙测试机型微博,华为多款机型开启鸿蒙尝鲜:微博已适配 HarmonyOS 小尾巴
  17. A brief introduction to complex analysis
  18. Python经典实验4-字典和集合的应用
  19. 3d效果图制作傻瓜软件_3D效果图制作哪个软件是最适合的?
  20. 结构化分析与面向对象的区别_JAVA进阶 深入理解面向对象

热门文章

  1. JSON 标准 ECMA-404
  2. 2020学而思笔记小初课程百度云网盘分享下载
  3. 获得代理ippython_Python自动获取代理IP
  4. chrome设置socket5代理
  5. Springcloud微服务中多模块重复代码重构成公共模块的实现
  6. PVID和VID详解
  7. 麻省理工学院公开课:单变量微积分
  8. docker的常用命令(镜像、容器常用操作)
  9. macOS上显示隐藏文件
  10. 【愚公系列】2021年12月 攻防世界-简单题-CRYPTO-005(Railfence)