上一篇讲了VLC整个程序的模块划分和界面主要使用的技术,今天分析一下VLC程序初始化过程,主要是初始化界面、加载解码库的操作。今天主要分析一下org.videolan.vlc.gui.MainActivity类,这个是VLC的整个程序入口。当然,严格来说,整个程序入口是VLCApplication类,因为VLC重载了Application,在我分析过的代码里面,貌似稍微复杂一点的程序,都喜欢重载Application。我自己写的一些程序也喜欢重载Application,因为可以提供一些全局功能和方便多页面数据交互。

  给出上一篇的截图,方便后面讲解程序初始化。

(PS:新建的QQ群,有兴趣可以加入一起讨论:Android群:322599434)

  

1、VLCApplication类

  这里简单说一下VLCApplication,如果你对Application的作用的功能不了解,请仔细查阅相关资料,这是一个很重要知识点。VLCApplication做的事情不多,简单来说,做了两件事。第一个是一个本地配置的初始化,主要是Locale的配置,而且都是针对中文做特别处理,另外就是当系统内存不多的时候,回收一些bitmap的内存。剩下的就是保存一个全局的静态对象供其他类使用。

  本地配置初始化这里不多说,都是简单的SharedPreferences读写和Locale配置,有兴趣自己看看源码。下面给出系统内存低的时候,回收bitmap缓存。这个平时可能不会太留意。

  1. //Edited by mythou
    //http://www.cnblogs.com/mythou/
  1.   public void onLowMemory()
  2. {
  3. super.onLowMemory();
  4. Log.w(TAG, "System is running low on memory");
  5.      //系统内存降低的时候,回收bitmap缓存
  6. BitmapCache.getInstance().clear();
  7. }

2、CPU类型检查

  这个功能基本上是用第三方库做解码器的,都需要做。因为我们编译FFMpeg解码库和其他解码库的时候,一般都需要指定CPU类型,例如现在的智能手机CPU架构有ARM和Intel的X86还有一些MIPS架构CPU。ARM里面又区分好几种类别。所以我们编译的时候都需要针对不同类型CPU做优化。这也导致了,我们需要检查我们的解码库跟机器的CPU类型是否匹配。

  之所以把这个能拿出来讲,是因为以后做一些跟CPU有关应用的时候,我们也需要检查CPU类型。

  1. //Edited by mythou
    //http://www.cnblogs.com/mythou/
  1.   public static boolean hasCompatibleCPU(Context context)
  2. {
  3. if(errorMsg != null || isCompatible) return isCompatible;
  4.      //读取VLC解码库,这一部分里面还有很多处理,下面会讲解
  5. ElfData elf = readLib(context.getApplicationInfo().dataDir + "/lib/libvlcjni.so");
  6. if(elf == null)
  7. {
  8. Log.e(TAG, "WARNING: Unable to read libvlcjni.so; cannot check device ABI!");
  9. Log.e(TAG, "WARNING: Cannot guarantee correct ABI for this build (may crash)!");
  10. return true;
  11. }
  12.      //记录CPU的类型,注意android2.2以后,会有两个CPU类型
  13. String CPU_ABI = android.os.Build.CPU_ABI;
  14. String CPU_ABI2 = "none";
  15. if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) { // CPU_ABI2 since 2.2
  16. try {
  17. CPU_ABI2 = (String)android.os.Build.class.getDeclaredField("CPU_ABI2").get(null);
  18. } catch (Exception e) { }
  19. }
  20.      //各种CPU参数记录,对这些不了解,可以百度一下。
  21. boolean hasNeon = false, hasFpu = false, hasArmV6 = false,
  22. hasArmV7 = false, hasMips = false, hasX86 = false;
  23. float bogoMIPS = -;
  24. int processors = ;
  25.      //判断CPU的架构
  26. if(CPU_ABI.equals("x86"))
  27. {
  28. hasX86 = true;
  29. }
  30. else if(CPU_ABI.equals("armeabi-v7a") ||
  31. CPU_ABI2.equals("armeabi-v7a"))
  32. {
  33. hasArmV7 = true;
  34. hasArmV6 = true; /* Armv7 is backwards compatible to < v6 */
  35. }
  36. else if(CPU_ABI.equals("armeabi") ||
  37. CPU_ABI2.equals("armeabi"))
  38. {
  39. hasArmV6 = true;
  40. }
  41.       
         //......下面还有一些CPU参数识别,这里就省略了
         //把CPU参数保存起来
  42. machineSpecs = new MachineSpecs();
  43. machineSpecs.hasArmV6 = hasArmV6;
  44. machineSpecs.hasArmV7 = hasArmV7;
  45. machineSpecs.hasFpu = hasFpu;
  46. machineSpecs.hasMips = hasMips;
  47. machineSpecs.hasNeon = hasNeon;
  48. machineSpecs.hasX86 = hasX86;
  49. machineSpecs.bogoMIPS = bogoMIPS;
  50. machineSpecs.processors = processors;
  51. return true;
  52. }

  上面的CPU参数属性里面说到了好几种参数,如果你对ARM不了解,建议百度查一下。这里简单讲解一下ABI,CPU_ABI是我们经常都会碰见的,例如我们在Android工程里面的libs库下面就有armeabi-v7a类型的库。这里的ABI是指Application Binary Interface。

  ABI描述了应用程序和操作系统之间,一个应用和它的库之间,或者应用的组成部分之间的低层接口。ABI不同于应用程序接口(API),API定义了源代码和库之间的接口,因此同样的代码可以在支持这个API的任何系统中编译,然而ABI允许编译好的目标代码在使用兼容ABI的系统中无需改动就能运行。

  ABI掩盖了各种细节,例如:调用约定(控制着函数的参数如何传送以及如何接受返回值);系统调用的编码和一个应用如何向操作系统进行系统调用;以及在一个完整的操作系统ABI中,对象文件的二进制格式、程序库等等。一个完整的ABI,像Intel二进制兼容标准 (iBCS) ,允许支持它的操作系统上的程序不经修改在其他支持此ABI的操作体统上运行。其他的 ABI 标准化细节包括 C++ name decoration 和同一个平台上的编译器之间的调用约定,但是不包括跨平台的兼容性。

  简单的说,ABI规范了应用程序对寄存器的使用方法,Call procedure,以及如何进入trap。符合某一平台ABI规范的应用程序就可以在这一平台上运行。这一规范是针对binary,而不是source的。所以同样的高级语言代码,使用不同的toolchain,可以得到符合不同ABI规范的binary。

  至于其他参数,如果有不清楚,请百度一下,其他参数比较好理解,这里不多说。

3、VLCLib解码库初始化

  1. //Edited by mythou
    //http://www.cnblogs.com/mythou/
  1.   static {
  2. try {
  3. if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1)
  4. System.loadLibrary("iomx-gingerbread"); //第一个解码库
  5. else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB_MR2)
  6. System.loadLibrary("iomx-hc"); //第二个解码库
  7. else
  8. System.loadLibrary("iomx-ics"); //第三个解码库
  9. } catch (Throwable t) {
  10. Log.w(TAG, "Unable to load the iomx library: " + t);
  11. }
  12. try {
  13. System.loadLibrary("vlcjni"); //第四个解码库
  14. } catch (UnsatisfiedLinkError ule) {
  15. Log.e(TAG, "Can't load vlcjni library: " + ule);
  16. /// FIXME Alert user
  17. System.exit();
  18. } catch (SecurityException se) {
  19. Log.e(TAG, "Encountered a security issue when loading vlcjni library: " + se);
  20. /// FIXME Alert user
  21. System.exit();
  22. }
  23. }

  解码库初始化没有什么特别,这里主要是想讲讲VLC用到的解码库总共有4个,都是在LibVLC.java类里面的静态代码块加载。至于每个解码库具体作用,还没有仔细分析,后面分析清楚再说。

4、界面初始化

  1.  
  1. //Edited by mythou
    //http://www.cnblogs.com/mythou/
  1.     //设置主界面画面
  2. View v_main = LayoutInflater.from(this).inflate(R.layout.main, null);
  3. mMenu.setContent(v_main);
  4. //SlidingMenu的view视图
  5. View sidebar = LayoutInflater.from(this).inflate(R.layout.sidebar, null);
  6. final ListView listView = (ListView)sidebar.findViewById(android.R.id.list);
  7. listView.setFooterDividersEnabled(true);
  8. mSidebarAdapter = new SidebarAdapter();
  9. listView.setAdapter(mSidebarAdapter);
  10. mMenu.setMenu(sidebar);
  11. //底下的信息条
  12. mInfoLayout = v_main.findViewById(R.id.info_layout);
  13. mInfoProgress = (ProgressBar) v_main.findViewById(R.id.info_progress);
  14. mInfoText = (TextView) v_main.findViewById(R.id.info_text);
  15. //ActionBar初始化
  16. prepareActionBar();

  界面初始化工作主要分为下面几个部分,可以对照我上面给出的效果图来分析。

  • 设置主Activity的Layout配置
  • SlidingMenu初始化
  • 底下信息条初始化
  • Actionbar初始化

  SlidingMenu的使用,我在另一篇(Android 开发自己的网络收音机2——电台列表(SlidingMenu侧滑栏))里面有详细使用介绍,这里不多说。Activity设置View这个也没什么好说。底下信息条,主要就是一个进度条,主要是搜索文件和生成视频缩略图的时候,给用户提示。本质上是ProgressBar和TextView的组合。最后Actionbar是使用了一个开源项目——ActionBarSherlock,在4.0的系统里面使用这个开源项目,会直接使用系统的ActionBar,所以跟我们使用系统的Actionbar差别不大,后面我们专门写一篇文章说明如何修改Actionbar。

5、主Activity布局

  1. //Edited by mythou
    //http://www.cnblogs.com/mythou/
  1. <LinearLayout
  2. xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent">
  6. <!-- 这里的FrameLayout负责显示切换的Fragment,是整个程序界面的主要显示模块-->
  7. <FrameLayout
  8. android:id="@+id/fragment_placeholder"
  9. android:layout_weight=""
  10. android:layout_width="fill_parent"
  11. android:layout_height="0dip" />
  12.  
  13.   <!-- 下面缩略图生成进度-->
  14. <RelativeLayout
  15. android:id="@+id/info_layout"
  16. android:layout_width="fill_parent"
  17. android:layout_height="wrap_content"
  18. android:visibility="gone">
  19. <ProgressBar
  20. android:id="@+id/info_progress"
  21. style="?android:attr/progressBarStyleHorizontal"
  22. android:layout_width="fill_parent"
  23. android:layout_height="wrap_content"
  24. android:progressDrawable="@drawable/progress"/>
  25. <TextView
  26. android:id="@+id/info_text"
  27. android:layout_width="wrap_content"
  28. android:layout_height="wrap_content"
  29. android:layout_marginLeft="5dip"
  30. android:layout_marginRight="5dip"
  31. android:singleLine="true"
  32. android:textColor="#FFFFFFFF"
  33. android:shadowColor="#CC000000"
  34. android:shadowRadius="1.5"
  35. android:shadowDx=""
  36. android:shadowDy=""/>
  37. </RelativeLayout>
  38.  
  39. <!-- 音乐后台播放的小的控制台-->
  40. <FrameLayout
  41. android:id="@+id/audio_mini_player"
  42. android:layout_height="wrap_content"
  43. android:layout_width="fill_parent"/>
  44. </LinearLayout>

  最后说说主Activity的布局,这个主Activity布局很简单,上一篇文章我也说过,VLC里面大部分界面都是用Fragment作为显示模块,所以使用的Activity并不多,这里负责切换Fragment显示的Layout是一个FrameLayout,在切换不同的Fragment的时候,都是依靠这个Layout来显示。

  另外就是一个由ProgressBar和TextView组成的信息条,显示缩略图生成的进度。以及下面一个小控件显示,主要是当音乐后台播放的时候,切换到非音乐播放界面,会在底下显示一个音乐播放的控制台。也是使用一个FrameLayout实现。

系列文章

Linux 下编译Android-VLC开源播放器详解(附源码下载)

Android VLC播放器二次开发1——程序结构分析

Edited by mythou

原创博文,转载请标明出处:http://www.cnblogs.com/mythou/p/3236071.html 

Android VLC播放器二次开发2——CPU类型检查+界面初始化的更多相关文章

  1. Android VLC播放器二次开发3——音乐播放(歌曲列表+歌词同步滚动)

    今天讲一下对VLC播放器音频播放功能进行二次开发,讲解如何改造音乐播放相关功能.最近一直在忙着优化视频解码部分代码,因为我的视频播放器需要在一台主频比较低的机器上跑(800M主频),所以视频解码能力受 ...

  2. Android VLC播放器二次开发1——程序结构分析

    最近因为一个新项目需要一个多媒体播放器,所以需要做个视频.音频.图片方面的播放器.也查阅了不少这方面的资料,如果要从头做一个播放器工作量太大了,而且难度也很大.所以最后选择了VLC作为基础,进行二次开 ...

  3. 搭建rtmp直播流服务之4:videojs和ckPlayer开源播放器二次开发(播放rtmp、hls直播流及普通视频)

    前面几章讲解了使用 nginx-rtmp搭建直播流媒体服务器; ffmpeg推流到nginx-rtmp服务器; java通过命令行调用ffmpeg实现推流服务; 从数据源获取,到使用ffmpeg推流, ...

  4. android音乐播放器开发教程

    android音乐播放器开发教程 Android扫描sd卡和系统文件 Android 关于录音文件的编解码 实现米聊 微信一类的录音上传的功能 android操作sdcard中的多媒体文件——音乐列表 ...

  5. 使用vlc播放器做rtsp流媒体服务器

    可参考: 使用vlc播放器播放rtsp视频 web网页中使用vlc插件播放相机rtsp流视频 使用vlc进行二次开发做自己的播放器 首先需要安装vlc播放器,下载及安装步骤略 使用vlc播放器做rts ...

  6. 使用vlc播放器播放rtsp流视频

    可参考: 使用vlc播放器做rtsp服务器 web网页中使用vlc插件播放相机rtsp流视频 使用vlc进行二次开发做自己的播放器 首先需要安装vlc播放器,下载及安装步骤略 使用vlc播放器播放rt ...

  7. 使用Vitamio打造自己的Android万能播放器(6)——在线播放(播放列表)

    前言 新版本的VPlayer由设计转入开发阶段,预计开发周期为一个月,这也意味着新版本的Vitamio将随之发布,开发者们可以和本系列文章一样,先开发其他功能.本章内容为"在线视频播放列表& ...

  8. 使用Vitamio打造自己的Android万能播放器(3)——本地播放(主界面、播放列表)

    前言 打造一款完整可用的Android播放器有许多功能和细节需要完成,也涉及到各种丰富的知识和内容,本章将结合Fragment.ViewPager来搭建播放器的主界面,并实现本地播放基本功能.系列文章 ...

  9. 使用Vitamio打造自己的Android万能播放器(1)——准备

    前言 虽然Android已经内置了VideoView组件和MediaPlayer类来支持开发视频播放器,但支持格式.性能等各方面都十分有限,这里与大家一起利用免费的Vitamio来打造属于自己的And ...

随机推荐

  1. SDL相关学习

    原文地址:https://www.cnblogs.com/landmark/category/311822.html 介绍SDL图形库的使用 SDL显示文字 摘要: 前面教程里,我们只显示图片,没提到 ...

  2. 中小研发团队架构实践之生产环境诊断工具WinDbg 三分钟学会.NET微服务之Polly 使用.Net Core+IView+Vue集成上传图片功能 Fiddler原理~知多少? ABP框架(asp.net core 2.X+Vue)模板项目学习之路(一) C#程序中设置全局代理(Global Proxy) WCF 4.0 使用说明 如何在IIS上发布,并能正常访问

    中小研发团队架构实践之生产环境诊断工具WinDbg 生产环境偶尔会出现一些异常问题,WinDbg或GDB是解决此类问题的利器.调试工具WinDbg如同医生的听诊器,是系统生病时做问题诊断的逆向分析工具 ...

  3. Linux下实现脚本监测特定进程占用内存情况

    Linux系统下,我们可以利用以下命令来获取特定进程的运行情况: cat /proc/$PID/status 其中PID是具体的进程号,这个命令打印出/proc/特定进程/status文件的内容,信息 ...

  4. C#数组之 []、List、Array、ArrayList应用

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...

  5. [转]gdb调试多进程和多线程命令

    1. 默认设置下,在调试多进程程序时GDB只会调试主进程.但是GDB(>V7.0)支持多进程的分别以及同时调试,换句话说,GDB可以同时调试多个程序.只需要设置follow-fork-mode( ...

  6. jenkins执行shell命令提示找不到命令解决办法

    用jenkins执行shell脚本,执行一条命令: #唤醒休眠手机 adb shell input keyevent 提示: [adb] $ /bin/sh -xe /Users/xxxxx/tool ...

  7. Java操作XML的JAXB工具

    在java中操作XML的工作中中,比较方便的工具是JAXB(Java Architecture for XML Binding). 利用这个工具很方便生成XML的tag和Java类的对应关系.参照网上 ...

  8. Python Tkinter基础控件入门实例

    分享一个Python Tkinter基础控件用法的入门例子,包括窗口的显示.显示内置图片.弹出窗口.菜单等. 例子,Python Tkinter基础控件的用法 # -*- coding: utf-8 ...

  9. python代码制作configure文件

    在lua中,一直用lua作为config文件,或承载数据的文件 - 好处是lua本身就很好阅读,然后无需额外写解析的代码,还支持在configure文件中读环境变量,条件判断等. 在lua中通过loa ...

  10. 利用javapns对IOS进行推送

    start package com.jynine.javapns; import java.io.FileNotFoundException; import java.io.IOException; ...