編輯:關於Android編程
上一篇講了VLC整個程序的模塊劃分和界面主要使用的技術,今天分析一下VLC程序初始化過程,主要是初始化界面、加載解碼庫的操作。今天主要分析一下org.videolan.vlc.gui.MainActivity類,這個是VLC的整個程序入口。當然,嚴格來說,整個程序入口是VLCApplication類,因為VLC重載了Application,在我分析過的代碼裡面,貌似稍微復雜一點的程序,都喜歡重載Application。我自己寫的一些程序也喜歡重載Application,因為可以提供一些全局功能和方便多頁面數據交互。
給出上一篇的截圖,方便後面講解程序初始化。
1、VLCApplication類
這裡簡單說一下VLCApplication,如果你對Application的作用的功能不了解,請仔細查閱相關資料,這是一個很重要知識點。VLCApplication做的事情不多,簡單來說,做了兩件事。第一個是一個本地配置的初始化,主要是Locale的配置,而且都是針對中文做特別處理,另外就是當系統內存不多的時候,回收一些bitmap的內存。剩下的就是保存一個全局的靜態對象供其他類使用。
本地配置初始化這裡不多說,都是簡單的SharedPreferences讀寫和Locale配置,有興趣自己看看源碼。下面給出系統內存低的時候,回收bitmap緩存。這個平時可能不會太留意。
//Edited by mythou //http://www.cnblogs.com/mythou/
public void onLowMemory() { super.onLowMemory(); Log.w(TAG, "System is running low on memory"); //系統內存降低的時候,回收bitmap緩存 BitmapCache.getInstance().clear(); }
2、CPU類型檢查
這個功能基本上是用第三方庫做解碼器的,都需要做。因為我們編譯FFMpeg解碼庫和其他解碼庫的時候,一般都需要指定CPU類型,例如現在的智能手機CPU架構有ARM和Intel的X86還有一些MIPS架構CPU。ARM裡面又區分好幾種類別。所以我們編譯的時候都需要針對不同類型CPU做優化。這也導致了,我們需要檢查我們的解碼庫跟機器的CPU類型是否匹配。
之所以把這個能拿出來講,是因為以後做一些跟CPU有關應用的時候,我們也需要檢查CPU類型。
//Edited by mythou //http://www.cnblogs.com/mythou/
public static boolean hasCompatibleCPU(Context context) { if(errorMsg != null || isCompatible) return isCompatible; //讀取VLC解碼庫,這一部分裡面還有很多處理,下面會講解 ElfData elf = readLib(context.getApplicationInfo().dataDir + "/lib/libvlcjni.so"); if(elf == null) { Log.e(TAG, "WARNING: Unable to read libvlcjni.so; cannot check device ABI!"); Log.e(TAG, "WARNING: Cannot guarantee correct ABI for this build (may crash)!"); return true; } //記錄CPU的類型,注意android2.2以後,會有兩個CPU類型 String CPU_ABI = android.os.Build.CPU_ABI; String CPU_ABI2 = "none"; if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) { // CPU_ABI2 since 2.2 try { CPU_ABI2 = (String)android.os.Build.class.getDeclaredField("CPU_ABI2").get(null); } catch (Exception e) { } } //各種CPU參數記錄,對這些不了解,可以百度一下。 boolean hasNeon = false, hasFpu = false, hasArmV6 = false, hasArmV7 = false, hasMips = false, hasX86 = false; float bogoMIPS = -1; int processors = 0; //判斷CPU的架構 if(CPU_ABI.equals("x86")) { hasX86 = true; } else if(CPU_ABI.equals("armeabi-v7a") || CPU_ABI2.equals("armeabi-v7a")) { hasArmV7 = true; hasArmV6 = true; /* Armv7 is backwards compatible to < v6 */ } else if(CPU_ABI.equals("armeabi") || CPU_ABI2.equals("armeabi")) { hasArmV6 = true; } //......下面還有一些CPU參數識別,這裡就省略了 //把CPU參數保存起來 machineSpecs = new MachineSpecs(); machineSpecs.hasArmV6 = hasArmV6; machineSpecs.hasArmV7 = hasArmV7; machineSpecs.hasFpu = hasFpu; machineSpecs.hasMips = hasMips; machineSpecs.hasNeon = hasNeon; machineSpecs.hasX86 = hasX86; machineSpecs.bogoMIPS = bogoMIPS; machineSpecs.processors = processors; return true; }
上面的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解碼庫初始化
//Edited by mythou //http://www.cnblogs.com/mythou/
static { try { if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) System.loadLibrary("iomx-gingerbread"); //第一個解碼庫 else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB_MR2) System.loadLibrary("iomx-hc"); //第二個解碼庫 else System.loadLibrary("iomx-ics"); //第三個解碼庫 } catch (Throwable t) { Log.w(TAG, "Unable to load the iomx library: " + t); } try { System.loadLibrary("vlcjni"); //第四個解碼庫 } catch (UnsatisfiedLinkError ule) { Log.e(TAG, "Can't load vlcjni library: " + ule); /// FIXME Alert user System.exit(1); } catch (SecurityException se) { Log.e(TAG, "Encountered a security issue when loading vlcjni library: " + se); /// FIXME Alert user System.exit(1); } }
解碼庫初始化沒有什麼特別,這裡主要是想講講VLC用到的解碼庫總共有4個,都是在LibVLC.java類裡面的靜態代碼塊加載。至於每個解碼庫具體作用,還沒有仔細分析,後面分析清楚再說。
4、界面初始化
//Edited by mythou //http://www.cnblogs.com/mythou/
//設置主界面畫面 View v_main = LayoutInflater.from(this).inflate(R.layout.main, null); mMenu.setContent(v_main); //SlidingMenu的view視圖 View sidebar = LayoutInflater.from(this).inflate(R.layout.sidebar, null); final ListView listView = (ListView)sidebar.findViewById(android.R.id.list); listView.setFooterDividersEnabled(true); mSidebarAdapter = new SidebarAdapter(); listView.setAdapter(mSidebarAdapter); mMenu.setMenu(sidebar); //底下的信息條 mInfoLayout = v_main.findViewById(R.id.info_layout); mInfoProgress = (ProgressBar) v_main.findViewById(R.id.info_progress); mInfoText = (TextView) v_main.findViewById(R.id.info_text); //ActionBar初始化 prepareActionBar();
界面初始化工作主要分為下面幾個部分,可以對照我上面給出的效果圖來分析。
SlidingMenu的使用,我在另一篇裡面有詳細使用介紹,這裡不多說。Activity設置View這個也沒什麼好說。底下信息條,主要就是一個進度條,主要是搜索文件和生成視頻縮略圖的時候,給用戶提示。本質上是ProgressBar和TextView的組合。最後Actionbar是使用了一個開源項目——ActionBarSherlock,在4.0的系統裡面使用這個開源項目,會直接使用系統的ActionBar,所以跟我們使用系統的Actionbar差別不大,後面我們專門寫一篇文章說明如何修改Actionbar。
5、主Activity布局
//Edited by mythou //http://www.cnblogs.com/mythou/
<framelayout android:id="@+id/fragment_placeholder" android:layout_height="0dip" android:layout_weight="1" android:layout_width="fill_parent"> <framelayout android:id="@+id/audio_mini_player" android:layout_height="wrap_content" android:layout_width="fill_parent"> </framelayout></framelayout>
最後說說主Activity的布局,這個主Activity布局很簡單,上一篇文章我也說過,VLC裡面大部分界面都是用Fragment作為顯示模塊,所以使用的Activity並不多,這裡負責切換Fragment顯示的Layout是一個FrameLayout,在切換不同的Fragment的時候,都是依靠這個Layout來顯示。
另外就是一個由ProgressBar和TextView組成的信息條,顯示縮略圖生成的進度。以及下面一個小控件顯示,主要是當音樂後台播放的時候,切換到非音樂播放界面,會在底下顯示一個音樂播放的控制台。也是使用一個FrameLayout實現。
這篇博客來介紹外觀模式(Facade Pattern),外觀模式也稱為門面模式,它在開發過程中運用頻率非常高,尤其是第三方 SDK 基本很大概率都會使用外觀模式。通過一個
自從騰訊QQ中的圓形頭像,火了起來後,現在我們在一些應用中都能看到圓形頭像的身影,在個人主頁或者個人資料面板中使用圓形頭像,會使整個布局變得更加優雅現在我們來進行第一步,
Android 破解視頻App去除廣告功能作為一個屌絲程序猿也有追劇的時候,但是當打開視頻app的時候,那些超長的廣告已經讓我這個屌絲無法忍受了,作為一個程序猿看視頻還要
前言在Android中,動畫Animation的實現有兩種方式:Tween Animation(補間動畫)和Frame Animation(幀動畫)。漸變動畫是通過對場景