Android 您所在的位置:网站首页 OPPO手机如何设置动态壁纸有声音 Android

Android

2024-01-08 07:46| 来源: 网络整理| 查看: 265

前言:

  最近遇到了几个很恶心的问题,第一个是手机录制视频发现资源不够用,第二个是手机播放视频发现卡顿。找了半天两个问题的root cause都是手机动态壁纸。我们手机动态壁纸的实现是无论当前壁纸是否处于前台,video instance都是一直活跃的。不得不说,这个设计真的很过分,一是浪费资源,二是会引起很多video的问题。所以今天就了解下动态壁纸的具体实现过程,看看是否可以优化这个设计……

Android壁纸的实现和管理概述:

Android壁纸的实现和管理分为三层:

WallpaperService与Engine

  壁纸运行在一个Android服务之中,这个服务的名字叫做WallpaperService。当用户选择了一个壁纸之后,此壁纸所对应的WallpaperService便会启动并开始进行壁纸的绘制工作。Engine是WallpaperService中的一个内部类,实现了壁纸窗口的创建以及Surface的维护工作。这一层次的内容主要体现了壁纸的实现原理。

WallpaperManagerService

  这个系统服务用于管理壁纸的运行与切换,并通过WallpaperManager类向外界提供操作壁纸的接口。这一层次主要体现了Android对壁纸的管理方式。

WindowManagerService

  用于计算壁纸窗口的Z序、可见性以及为壁纸应用窗口动画。这一层次主要体现了Android对壁纸窗口的管理方式。

 上层调用component_deinit的过程:

MediaCodec: stop  or release ACodec::initiateShutdown 在此函数中会判断keepComponentAllocated是否为false,如果是false就发送kWhatReleaseCodecInstance status_t err = mCodec->mOMXNode->freeNode(); Omx::freeNode // 此处调用mMaster->destroyComponentInstance QComOMXPlugin::destroyComponentInstance // (*mFreeHandle)(reinterpret_cast(component)); // mFreeHandle = (FreeHandleFunc)dlsym(mLibHandle, "OMX_FreeHandle"); OMX_FreeHandle // qc_omx_component_deinit qc_omx_component_deinit   // eRet = pThis->component_deinit(hComp);

Android动态壁纸的具体实现:

  安卓壁纸的实现都是在WallpaperService中完成的,动态壁纸只是对壁纸功能的扩展,所以动态壁纸的实现首先会创建一个服务并集成WallpaperService。WallpaperService中有一个内部类Engine,Engine实现了实现了壁纸窗口的创建以及Surface的维护工作。就是说我们可以获取到一个SurfaceHolder,拿到这个东西就好办了,我们可以在上面画自己想要的东西或者把视频输出到上面去。下面直接看代码:

// packages/apps/ThemeManager/src/com/android/thememanager/service/VideoWallpaperService.java public class VideoWallpaperService extends WallpaperService { private static final String TAG = "VideoWallpaper"; public Engine onCreateEngine() { // 创建VideoEngine,VideoWallpaperService实现的内容都在VideoEngine中 return new VideoEngine(); } private class VideoEngine extends WallpaperService.Engine { private MediaPlayer mediaPlayer = new MediaPlayer(); // 创建播放器MediaPlayer private String path; private boolean isAudioOn; private AudioManager mAudioManager; // 创建AudioFocusChangeListener private AudioManager.OnAudioFocusChangeListener mOnAudioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() { @Override public void onAudioFocusChange(int focusChange) { // 略 } }; private BroadcastReceiver mUpdateVideoReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); // 略 initEngine(); // 初始化Engine } } }; @Override public void onCreate(SurfaceHolder surfaceHolder) { // 略 } @Override public void onDestroy() { super.onDestroy(); mediaPlayer.release(); // 释放mediaPlayer unregisterReceiver(mUpdateVideoReceiver); } @Override public void onSurfaceCreated(SurfaceHolder holder) { super.onSurfaceCreated(holder); initEngine(); } @Override public void onVisibilityChanged(boolean visible) { // 当壁纸有前后台的切换 super.onVisibilityChanged(visible); try { if (visible) { mediaPlayer.start(); // 如果切换为前台,开始播放 } else { mediaPlayer.pause(); // 如果切换为后台,暂停播放 // 调用pause只会pause source和render不会释放decoder. } } catch (IllegalStateException e) { Log.e(TAG, "onVisibilityChanged video exception ", e); } } private void initEngine() { // 在此函数中实现了对视频文件的处理,及对player的操作 Log.d(TAG, "initEngine"); File videoFile = null; InputStream inputStream = null; FileOutputStream outputStream = null; try { Context context = VideoWallpaperService.this; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { context = context.createDeviceProtectedStorageContext(); } File filesDir = context.getFilesDir(); String videoPath = filesDir.getAbsolutePath() + "/video"; File videoFileDir = new File(videoPath); final String fileName = FileUtils.getFileName(path); videoFile = new File(videoFileDir, fileName); if (!videoFile.exists()) { // Clean all video FileUtils.rm(videoPath); videoFileDir.mkdir(); // Write current video inputStream = new FileInputStream(new File(path)); outputStream = new FileOutputStream(videoFile); // 16k buffer byte buffer[] = new byte[16384]; int length = 0; while ((length = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, length); } } } catch (Exception e) { Log.e(TAG, "load video file error : ", e); } finally { Utils.closeQuietly(outputStream); Utils.closeQuietly(inputStream); } try { if (videoFile != null && videoFile.exists()) { mediaPlayer.reset(); Surface surface = getSurfaceHolder().getSurface(); mediaPlayer.setSurface(surface); mediaPlayer.setDataSource(new FileInputStream(videoFile).getFD()); setAudioState(isAudioOn); mediaPlayer.setLooping(true); mediaPlayer.prepare(); mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.start(); } }); mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { mp.reset(); return false; } }); } } catch (Exception e) { Log.e(TAG, "configVideoEngine err ", e); } } private void setAudioState(boolean isOn) { // 设置音频 try { float volume = isOn ? 0.5f : 0; mediaPlayer.setVolume(volume, volume);  } catch (IllegalStateException e) { Log.e(TAG, "setAudioState err", e); } } }

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有