当前位置: 首页 > news >正文

前端做网站商城 购物车怎么做海南省零售户电商网站

前端做网站商城 购物车怎么做,海南省零售户电商网站,宿州论坛,怎么自己创建小程序文章目录 问题描述车载蓝牙音乐流程Music 监听焦点变化流程BT请求焦点的流程MediaSession 服务端的流程BT和music 之间的相互影响 问题描述 问题 AAOS界面连接蓝牙的情况下#xff0c;Music应用播放音乐会暂停。 分析 暂停是应用的行为#xff0c;Music应用会监听focus的变化… 文章目录 问题描述车载蓝牙音乐流程Music 监听焦点变化流程BT请求焦点的流程MediaSession 服务端的流程BT和music 之间的相互影响 问题描述 问题 AAOS界面连接蓝牙的情况下Music应用播放音乐会暂停。 分析 暂停是应用的行为Music应用会监听focus的变化监听到焦点失去的情况会调用暂停。但是Music 应用刚启动播放的时候 也会请求焦点焦点第一次是在bt这边的。bt失去焦点但立马又重新请求了焦点。 BT请求焦点就导致Music应用失去焦点而暂停。 了解问题之前首先要理解 蓝牙音乐在哪里调用到音频框架音频焦点carMediaService 车载蓝牙音乐流程 A2DP端 代码位置 system\bt\btif\src\btif_avrcp_audio_track.cc system\bt\stack\a2dp\a2dp_aac.cc 在上述的BtifAvrcpAudioTrackCreate()函数中。在这里面会创建一个AAudioStreamBuilder AAudio 通过legacy的模式 的audiotrack 来进行处理 写数据。 AAudio端 蓝牙音乐 车载端是一个sink 端作为播放来使用。 对应的流程在btif_avrcp_audio_track 是通过调用AAudio的接口来实现播放。其中AAudio 没有实现mmap的方式 走的是legacy模式 代码在frameworks\av\media\libaaudio\src\legacy\AudioStreamTrack.cpp中 也就是通过创建audiotrack然后设置参数、往里面写数据实现的。audiotrack start 的时候 同样会getoutputAttr获取到设备 这个时候的路由信息已经由AAOS 根据car_audio_policy.xml 进行注册。 整体流程 从source端也就是手机通过蓝牙发送过来的是aac或者ldac编码的数据 数据在a2dp中继续解码 并不是进入到audiotrack。 a2dp中有相当于播放器中解码器的功能解码后的数据才调用audiotrak进行播放。 Music 监听焦点变化流程 实现AudioFocusListener 然后注册到AudioMananger private OnAudioFocusChangeListener mAudioFocusListener new OnAudioFocusChangeListener() {public void onAudioFocusChange(int focusChange) {mMediaplayerHandler.obtainMessage(FOCUSCHANGE, focusChange, 0).sendToTarget();}};mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); 在框架层焦点发生变化的时候 回调到外部注册进去的listener Music 中MediaPlayBackService的实现 通过looper发送消息进行处理而如果是focus丢失的时候所做的操作是pause。 case AudioManager.AUDIOFOCUS_LOSS: Log.v(LOGTAG, AudioFocus: received AUDIOFOCUS_LOSS);if (isPlaying()) {mPausedByTransientLossOfFocus false;}pause(); break; case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:Log.v(LOGTAG, AudioFocus: received AUDIOFOCUS_LOSS_TRANSIENT);if (isPlaying()) {mPausedByTransientLossOfFocus true;}pause(); break;BT请求焦点的流程 监听mediassion 的onPrepare事件 有Prepare事件发生后会调用requestFocus。其usage是USAGE_MEDIA。这个会回调到AAOS的CarAudioFocus 进行处理 其就是根据交互矩阵进行处理的。当前持有的是music应用在BT 请求焦点后会发送消息通知music 焦点失去了。 在上面的流程知道 失去焦点后 会调用player的 pause 进行暂停操作。 packages\apps\Bluetooth\src\com\android\bluetooth\avrcpcontroller\AvrcpControllerStateMachine.java BluetoothMediaBrowserService.addressedPlayerChanged(mSessionCallbacks); sBluetoothMediaBrowserService.mSession.setCallback(callback);MediaSessionCompat.Callback mSessionCallbacks new MediaSessionCompat.Callback() {Overridepublic void onPrepare() {logD(onPrepare);A2dpSinkService a2dpSinkService A2dpSinkService.getA2dpSinkService();if (a2dpSinkService ! null) {a2dpSinkService.requestAudioFocus(mDevice, true);}} }private synchronized int requestAudioFocus() {if (DBG) Log.d(TAG, requestAudioFocus());// Bluetooth A2DP may carry Music, Audio Books, Navigation, or other sounds so mark content// type unknown.AudioAttributes streamAttributes new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN).build();// Bluetooth ducking is handled at the native layer at the request of AudioManager.AudioFocusRequest focusRequest new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).setAudioAttributes(streamAttributes).setOnAudioFocusChangeListener(mAudioFocusListener, this).build();int focusRequestStatus mAudioManager.requestAudioFocus(focusRequest);// If the request is granted begin streaming immediately and schedule an upgrade.if (focusRequestStatus AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {startFluorideStreaming();mAudioFocus AudioManager.AUDIOFOCUS_GAIN;}return focusRequestStatus;} 那现在的问题是 哪里触发了onPrepare 可以看到是实现了MediaSession的Callback。 理解MediaSession的概念 MediaSession 有客户端和服务端。 客户端对应的是UI 这一端服务端对应的是player。 UI这一端的实现是在packages/app/Car/Media 中。 主要是几个类 的封装分别是 MediaControl用来控制MediaSession 在上面的AVrcpControl中 实现的MessaionCompat的callback回调的 play prepare都是由MediaControl这边调用的。 packages\apps\Car\Media\src\com\android\car\media\service\MediaConnectorService.java packages\apps\Car\libs\car-media-common\src\com\android\car\media\common\playback\PlaybackViewModel.java MediaControllerCompat.TransportControls controls controller.getTransportControls(); controls.prepare();这里的prepare 会调用到AvrcpControllerStateMachine的onPrepare中。 如何监听到playstate的变化的 packages\apps\Music\src\com\android\music\MediaPlaybackService.java 可以确认是music 发送的play state 导致 carMusicApp这边MediaControl调用prepare的. 下面的RemoteControlClient实际是MediaSession的封装 private void notifyChange(String what) {Intent i new Intent(what);i.putExtra(id, Long.valueOf(getAudioId()));i.putExtra(artist, getArtistName());i.putExtra(album, getAlbumName());i.putExtra(track, getTrackName());i.putExtra(playing, isPlaying());sendStickyBroadcast(i);if (what.equals(PLAYSTATE_CHANGED)) {mRemoteControlClient.setPlaybackState(isPlaying()? RemoteControlClient.PLAYSTATE_PLAYING: RemoteControlClient.PLAYSTATE_PAUSED);} 代码位置 packages\services\Car\service\src\com\android\car\CarMediaService.java 是通过重新编写MediaController.Callback来实现的。MediaSession设置的状态变化会通过callback调用到MediaCotroller当中 private class MediaControllerCallback extends MediaController.Callback {public void onPlaybackStateChanged(Nullable PlaybackState state) {setPrimaryMediaSource(mediaSource, MEDIA_SOURCE_MODE_PLAYBACK);} }private void startMediaConnectorService(boolean startPlayback, UserHandle currentUser) {Intent serviceStart new Intent(MEDIA_CONNECTION_ACTION);Log.d(CarLog.TAG_MEDIA, Log.getStackTraceString(new Throwable()));serviceStart.setPackage(mContext.getResources().getString(R.string.serviceMediaConnection));serviceStart.putExtra(EXTRA_AUTOPLAY, startPlayback);mContext.startForegroundServiceAsUser(serviceStart, currentUser);} packages\apps\Car\Media\src\com\android\car\media\service\MediaConnectorService.java 在上述的startMediaConnectorService会启动一个service 这个service调用到MediaConnectorSerive中onStartCommand。 在startcommad 中会使用mediacontrol 进行prepare操作。 public int onStartCommand(Intent intent, int flags, int startId) {playbackViewModel.getPlaybackStateWrapper().observe(this,playbackStateWrapper - {if (playbackStateWrapper ! null) {// If the source to play was specified in the intent ignore others.ComponentName intentComp mCurrentTask.mMediaComp;ComponentName stateComp playbackStateWrapper.getMediaSource().getBrowseServiceComponentName();if (!Objects.equals(stateComp, intentComp)) {return;}if (playbackStateWrapper.isPlaying()) {stopTask();return;}if ((playbackStateWrapper.getSupportedActions() PlaybackStateCompat.ACTION_PREPARE) ! 0) {playbackViewModel.getPlaybackController().getValue().prepare();if (!autoplay) {stopTask();}}if (autoplay (playbackStateWrapper.getSupportedActions() PlaybackStateCompat.ACTION_PLAY) ! 0) {playbackViewModel.getPlaybackController().getValue().play();stopTask();}}});src\com\android\bluetooth\a2dpsink\A2dpSinkService.java 总结 单单看MediaSession 和 MediaControl。 MediaControl是UI端控制Service端的类在AAOS中所有的app播放控制客户端的实现都是carMediaApp中MediaControl的实现的包括蓝牙audio localplayer界面中暂停播放下一首 上一首等等。 MediaSession是服务端 这个服务端包括蓝牙的src\com\android\bluetooth 和/apps/Car/LocalMediaPlayer。这这里面实现了Mediassion 的callback 用来响应client 端UI的控制。 而响应之后的状态改变可以通过继承MediaControl的callback 在客户端实现。 而Music应用中会向session发送状态改变的消息客户端carMediaApp会响应这个消息响应这个消息的结果就是prepare播放器。这个prepare调用到蓝牙的MediaSeesion。MediaSeeion正常应该 一个客户端和服务器一一对应的。 问题的解决 对于没有MediaSource的session变化 不启动MediaConnectService。 MediaSession 服务端的流程 首先实现MediaSessionCompat.Callback()然后将这个callback 设置到MediaBrowserService的sesseion中。 BluetoothMediaBrowserService.addressedPlayerChanged(mSessionCallbacks); sBluetoothMediaBrowserService.mSession.setCallback(callback);session 中token的传递 为什么music 发送的消息 这边的session 可以接收到。 因为在CarMediaService 中已经注册了MediaSession变化的消息。 在音乐应用启动的时候 会新建MediaSession 而在这里就会监听了active MediaSession的变化同时传递当前所有的Mediacontrol, 然后对这些mediaControl注册callback。 在这个callback 中监听onPlaybackStateChanged事件。 而在这边对mediacontrol的管理是通过token实现的。 token 是在MediaSession 和 MdiaControl 直接建立连接的数据。可以通过getHashCode来打印其hash值确认。 private void initUser(UserIdInt int userId) {updateMediaSessionCallbackForCurrentUser();if (mSessionsListener ! null) {mMediaSessionManager.removeOnActiveSessionsChangedListener(mSessionsListener);}mSessionsListener new SessionChangedListener(ActivityManager.getCurrentUser());UserHandle currentUserHandle new UserHandle(ActivityManager.getCurrentUser());mMediaSessionManager.addOnActiveSessionsChangedListener(null, currentUserHandle,new HandlerExecutor(mHandler), mSessionsListener);}private class SessionChangedListener implements OnActiveSessionsChangedListener {private final int mCurrentUser;SessionChangedListener(int currentUser) {mCurrentUser currentUser;}Overridepublic void onActiveSessionsChanged(ListMediaController controllers) {if (ActivityManager.getCurrentUser() ! mCurrentUser) {Slog.e(CarLog.TAG_MEDIA, Active session callback for old user: mCurrentUser);return;}Log.d(CarLog.TAG_MEDIA, Log.getStackTraceString(new Throwable()));Log.d(CarLog.TAG_MEDIA, controllers szie controllers.size());mMediaSessionUpdater.registerCallbacks(controllers);}}private void registerCallbacks(ListMediaController newControllers) {ListMediaController additions new ArrayList(newControllers.size());MapMediaSession.Token, MediaControllerCallback updatedCallbacks new HashMap(newControllers.size());for (MediaController controller : newControllers) {MediaSession.Token token controller.getSessionToken();String newPackageName controller.getPackageName();Log.d(CarLog.TAG_MEDIA, Log.getStackTraceString(new Throwable()));MediaControllerCallback callback mCallbacks.get(token);if (callback null) {callback new MediaControllerCallback(controller);callback.register();additions.add(controller);}updatedCallbacks.put(token, callback);}private MediaControllerCallback(MediaController mediaController) {public void onPlaybackStateChanged(Nullable PlaybackState state) {} BT和music 之间的相互影响 本地音乐在播放手机播放蓝牙音乐 两个声音同时播放 这个是焦点管理的问题 按理理解蓝牙音乐播放的时候 应该去请求焦点。需要设置属性才会请求默认不会请求。 播放的时候 前面流程不用管最后会调用到SRC_STR_START中没有请求焦点music应用就会一直播。修改方法 解决方法通过配置shouldRequestFocus 让BT应用在每次播放的时候都强制请求焦点解决。强制请求之后music就会失去焦点暂停。 packages\apps\Bluetooth\src\com\android\bluetooth\a2dpsink\A2dpSinkStreamHandler.javaswitch (message.what) {case SRC_STR_START:mStreamAvailable true;if (isTvDevice() || shouldRequestFocus()) {requestAudioFocusIfNone();}break; 蓝牙音乐在播放的时候本地音乐播放会导致蓝牙直接stop掉。 这个stop 是在蓝牙的MediaSessions callback onstop中调用的。 而这个回调是在CarMediaService中被触发的。也是在上面的流程中music应用的playbackstate 回调中stop的。 解决方法不调用stop 调用pause进行暂停。 public void onPlaybackStateChanged(Nullable PlaybackState state)private void setPlaybackMediaSource(ComponentName playbackMediaSource) {stopAndUnregisterCallback();
http://www.w-s-a.com/news/740997/

相关文章:

  • 正规的网站建设工作室海外高延迟服务器做网站
  • 网站设计确认函合肥做网站维护的公司
  • 小说网站推荐网站开发语言怎么查
  • 网页制作基础教程慕课版电子版那种登录才能查看的网站怎么做优化
  • 制作网站用的域名网站域名注册信息查询
  • 公司域名查询官方网站女教师遭网课入侵直播录屏曝
  • 网站开发社交网络功能的作用腾讯公司网站
  • 网站建设需要微信账号和密码网站建设工作汇报
  • 国家城乡住房和建设部网站西安私人网站
  • 天津高端网站定制seo实战教程
  • 网站文章怎么做才能被快速收录网站备案核验系统
  • 子网站建设方案l建设银行网站
  • 免费看舆情网站网站备案用户名忘了怎么办
  • 地方门户网站的分类网站的方案
  • 沧州哪里做网站网站的建设是什么
  • 设计公司海报秦皇岛seo网站推广
  • 网站导航规划wordpress做漫画
  • jsp体育用品网站建设wordpress 10万篇文章
  • 沈阳做微信和网站的公司网站在线支付接口
  • 重庆整合网络营销百度seo快速提升排名
  • 设计师网站外网百度分析工具
  • 旅游网站建设技术解决方案wordpress主题安装后找不到
  • 网站图片文字排版错误管理系统界面设计
  • 网站建设 台州广州惠科互联网技术有限公司
  • 网站页面尺寸大小四川鸿业建设集团网站
  • 做女朋友的网站局网站建设方案word
  • 做阿里国际网站会有成效吗科技网站有哪些
  • 高端公司网站建设北京两学一做网站
  • 黄埔网站建设设计wordpress 文件夹改名
  • 怎么什么软件可以吧做网站最火的二十个电商app