【WP 8.1開發】解決調用真實攝像頭會死機的問題


無論你是用Silverlight還是用RT的API來開發,在使用MediaCapture拍照片或錄視頻時,要是在模擬器上運行會萬事大吉;但是,一旦放到真實手機上運行,肯定有人發現了,細心的朋友肯定發現了——不知道為什么,會經常導致手機重啟,或者死機。

啊,順便給大家說說,死機不可怕,也不用重置,也不用刷機,不會丟失資料的,你只要同時按下“音量減”+“電源”兩個鍵,要同時按住,不要放開,大約等10多秒后,會關機,然后你再放開這兩個鍵,這樣手機就軟啟了,不會丟失數據。

不過,如果你的運營商(如中國聯通)的基站沒有實時更新時間的功能,那么,手機在軟啟后時間會不准,你可以手動調整一下。有些人說:不是設置了自動更新時間嗎?怎么會不准了呢?注意WP上的自動更新時間不是用網絡連接來更新的,而是通過移動運營商的基站來更新的,我的中國移動卡會得到基站的數據,但時間不准,會慢了半個小時。

好了,上面說的廢話太多,我擔心有人會扔磚頭。我們當Coder的一定要有耐心做事的好習慣,不然你真的不是好Coder,不要一遇到問題就在那里罵外公罵娘的,也不要在那里踢桌子砸凳子,因為你沒有那樣的功力,桌子沒踢壞你的腳就會痛得不行。

調用攝像頭API導致死機的原因是:應用程序占用了系統的資源,也就是說你的應用沒有及時釋放相關資源導致的,一般這種情況多發生在調試的時候,因為我們通常在調試時會直接在VS上結束應用程序,如此一來,清理資源的代碼就沒有執行,系統資源仍然被你占着,所以一旦再次執行應用程序,或者運行其他相機應用,就會導致系統在無限等待,於是就死機了。

 

要釋放MediaCapture對象其實很簡單,只要調用它的Dispose方法即可,關鍵是,要在哪里調用。

為了安全保險,應該中導航離開頁面時釋放(處理OnNavigatingFrom方法),或者在應用程序不在前台運行時釋放,當再次回到應用程序時,重新實例化MediaCapture對象。這樣做的好處既能及時釋放資源,而且在你的應用程序發送到后台后,你不能保證其他程序不會調用攝像頭,不然,資源老被你占着,別人沒法用了。

 

以Silverlight框架為例,可以在App類中定義一些成員來初始化和清理MediaCapture。

    public sealed partial class App
    {
        MediaCapture capture = null;

        /// <summary>
        /// 通過該屬性獲得MediaCapture實例
        /// </summary>
        internal MediaCapture PhotoCaptureForCurrent
        {
            get { return capture; }
        }

        /// <summary>
        /// 初始化
        /// </summary>
        internal async Task InitailizeCapture ()
        {
            var devs = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
            DeviceInformation bc = devs.FirstOrDefault(d => d.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Back);
            if (bc != null)
            {
                MediaCaptureInitializationSettings settings = new MediaCaptureInitializationSettings();
                settings.AudioDeviceId = "";
                settings.VideoDeviceId = bc.Id;
                capture = new MediaCapture();
                await capture.InitializeAsync(settings);
            }

        }

        /// <summary>
        /// 清理
        /// </summary>
        internal void ClearupCapture ()
        {
            if (capture != null)
            {
                capture.Dispose();
                capture = null;
            }
        }

    }

在調用Dispose方法后,把MediaCapture變量設置為null引用,這樣就算清理方法被多次調用也不會出錯。

為了安全保險,清理方法有可能被重復調用。因為我會考慮在頁面離開時調用一次,在應用程序被放入后台時調用一次,在應用程序關閉時調用一次。

有人會問,為什么要這樣?因為1、離開頁面;2、應用被停用(不在前台);3、應用關閉

這三件事你無法保證它都發生,有時候,可能1發生,但2和3不會發生。

例如:

當運行應用程序后,我突然按了一個“開始”鍵,這時候會回到開始屏幕。此時,導航離開頁面會發生,應用程序的DeActived事件會發生,但是,應用程序的關閉事件不會發生。

總之,在這三件事發生時都清理一次,可保萬全。

 

A、在導航離開頁面時,清理。

        protected override void OnNavigatingFrom ( NavigatingCancelEventArgs e )
        {
           ……
            (App.Current as App).ClearupCapture();
        }


B、應用被發送到后台時,清理。

        private void Application_Deactivated ( object sender, DeactivatedEventArgs e )
        {
            ClearupCapture();
        }

即響應Deactivated事件。

C、當應用關閉時,清理。

        private void Application_Closing ( object sender, ClosingEventArgs e )
        {
            ClearupCapture();
        }

即處理Closing事件。

用Runtime API調用攝像頭時要謹慎,尤其是在調試的時候,最好,先在手機上先把應用關閉,再從VS上結束應用程序

不是騙你,經過我近一個星期N多次的測試,這樣做確實不會死機,在測試過程中,我那台可憐的Lumia 920不知道死了多少次。記住,有借有還,再借不難。占用系統資源一定要釋放

 

下面,順便附上我寫的一個測試示例,如果大家不嫌我這個示例太垃圾的話,可以下來玩玩。

 http://files.cnblogs.com/tcjiaan/AppCamera.zip

 

我比較頭痛的另一件事是:不同手機的硬件差異,攝像頭的角度經常會偏了,920的攝像頭是旋轉了90度,這個問題說好辦也好辦,說不好辦也挺難辦,因為目前移植的RT庫中,貌似不能旋轉。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM