主頁 > 移動端開發 > 不會吧,這也行?iOS后臺鎖屏監聽搖一搖

不會吧,這也行?iOS后臺鎖屏監聽搖一搖

2020-10-09 13:12:26 移動端開發

目錄
  • 背景介紹
  • 探索程序
    • 其他 APP 有沒有類似功能
    • 系統提供的搖一搖回呼能否滿足
    • 其他方法能否實作
      • 利用 CoreMotion 框架,監聽加速計原始資料
        • 通過加速計監聽搖一搖
        • 控制器相關邏輯和代碼
      • APP 申請后臺運行權限后,能否監聽到搖一搖
    • 多 APP 都實作此功能時,搖一搖是何效果
    • 后臺定位權限 + 系統搖一搖,是否可行?
  • 文章小結
  • 參考文章
  • Demo 鏈接

背景介紹

一般情況下,出于省電、權限、合理性等因素考慮,給人的感覺是很多奇怪的需求安卓可以實作,但是iOS就無法實作!今天要介紹的需求也有這種感覺,就是“當 APP 處于后臺或鎖屏狀態時,依舊可以監聽到搖一搖,進而觸發某些功能,比如:語音播報”,

在產品經理提出此需求的一瞬間,仿佛周邊的空氣都凝固了,我也猶如五雷轟頂,愣在原地無法動彈,不由心想:“蘋果爸爸怎么可能允許開發者實作這種功能!這得多費電啊!要是所有 APP 都這么做了,那還了得!” 與此同時,之前網上瘋傳、遠近聞名的的需求--“做一個會根據手機殼顏色而改變主題顏色的APP”,清晰地浮現在腦海中,頓時一萬只xx??從心中奔騰而過,此時,產品經理解釋到,這是咱們好多視力障礙用戶提的需求,他們經常鎖屏或把 APP 退到后臺,且因為視力不佳原因,導致重新找到 APP 并切到前臺的操作很是麻煩,所以十分希望我們能實作這個功能,

在短暫的心理活動后,秉著“客戶第一,產品????”的原則,于是回復說:“這功能太少見了,我先在網上看看吧,要是有其他 APP 有類似的功能,麻煩跟我說我參考一下,”然后,就祭出了程式員利器--Google,輸入“iOS 后臺 搖一搖”,只搜索出來的一個思路:利用 CoreMotion 框架,監聽加速計原始資料,然后在 APP 退到后臺后,可以實作監聽搖一搖的效果,然而,并沒有完整的代碼或 demo ,頓時,Talk is cheap, show me the code!這句經典臺詞突然地出現在腦海中!也看到有人評論說 CoreMotion 的確可以實作跟系統搖一搖類似的效果,但是退到后臺或鎖屏后,沒辦法監聽到搖一搖事件,

看到這條評論時,我不禁開始懷疑此功能是否真的可以被實作,

玩歸玩,鬧歸鬧,開始 code,不開玩笑,

接下來,開始自己的探索之旅,

本文 demo 鏈接為 OCDailyTests/BackgroundShakeTest,可自行下載,方便運行和驗證,

探索程序

其他 APP 有沒有類似功能

經過一番 Google,終于找到一款 APP 有類似功能::酷狗音樂 APP,對,就是那個在 PC 端一打開就會大喊 Hello KuGou!的音樂軟體對應的 APP,萬萬沒想到,手機 APP 也是這樣,一句Hello KuGou!把我嚇一跳,按如下步驟,在設定里打開此功能后,后臺或鎖屏時,搖一搖手機,可實作切歌的效果,

既然的確有 APP 實作了此功能,那就踏踏實實地探索它可能是怎么實作的吧,

系統提供的搖一搖回呼能否滿足

系統搖一搖回呼方法:

- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event{
    NSLog(@"%s", __FUNCTION__);
}

經測驗,此方法只有在 APP 處于前臺時,才會被回呼,APP 處于后臺或鎖屏時,此方法不會回呼,故初步判定此方法不能滿足需求,

其他方法能否實作

此時,還是先根據網上各路大神提供的思路進行嘗試,即利用 CoreMotion 框架,監聽加速計原始資料,然后在 APP 退到后臺后,實作監聽搖一搖的效果,

好,我們先利用 CoreMotion 框架,監聽加速計原始資料,實作類似系統搖一搖回呼的效果,

利用 CoreMotion 框架,監聽加速計原始資料

通過加速計監聽搖一搖

因加速計回呼比較頻繁,因此比較占用資源,故把此功能設計為單例,

  • 快速實作單例效果

    //具體實作詳見 demo 中檔案
    #import "HMSingleton.h"
    
    @interface MYAccelerometerTool : NSObject
    HMSingleton_h(MYAccelerometerTool);
    @end
    
    @implementation MYAccelerometerTool
    HMSingleton_m(MYAccelerometerTool);
    @end
    
  • 宣告和懶加載運動管理員屬性

    @property(nonatomic, strong) CMMotionManager *gMotionMnger;
    
    - (CMMotionManager *)gMotionMnger{
        if (nil == _gMotionMnger) {
            CMMotionManager *lMnger = [[CMMotionManager alloc] init];
            lMnger.accelerometerUpdateInterval = 0.1;
            [lMnger startAccelerometerUpdates];
            _gMotionMnger = lMnger;
        }
        return _gMotionMnger;
    }
    
  • 宣告和實作時間戳屬性,用于實作節流效果(為防止頻繁回呼,每次檢測成功后,停止搖動 1s 后才繼續回應下次搖一搖,)

    @property(nonatomic, strong) NSDate *gDateLastShakeSuc;
    - (NSDate *)gDateLastShakeSuc{
        if (nil == _gDateLastShakeSuc) {
            _gDateLastShakeSuc = [NSDate distantPast];
        }
        return _gDateLastShakeSuc;
    }
    
  • 開始監聽搖一搖動作

    - (BOOL)startMonitorShake{
        if (NO == self.gMotionMnger.isAccelerometerAvailable) {
            return NO;
        }
        
        //監聽中,直接回傳YES
        if (self.gMotionMnger.isAccelerometerActive) {
            return YES;
        }
        
        [self.gMotionMnger startAccelerometerUpdatesToQueue:[NSOperationQueue new] withHandler:^(CMAccelerometerData * _Nullable accelerometerData, NSError * _Nullable error) {
            
            CMAcceleration acceleration = accelerometerData.acceleration;
            
            //綜合x、y兩個方向的加速度(z方向速度無意義,用的話,走路上下抖手機時會誤觸發,系統搖一搖也不會被z軸加速度觸發)
            //當綜合加速度大于2.3時,就激活效果(資料越小,用戶搖動的動作就越小,越容易激活)
            double accelerameter = sqrt( pow( acceleration.x , 2 ) + pow( acceleration.y , 2 ));
            
            if (accelerameter > 2.3) {
                
                //節流效果:距離上次搖一搖成功事件,間隔時間小于1s時,認為無效
                NSDate *lCrtDate = [NSDate date];
                if ([lCrtDate timeIntervalSinceDate:self.gDateLastShakeSuc] < 1) {
                    self.gDateLastShakeSuc = lCrtDate;
                    return ;
                }
                
                self.gDateLastShakeSuc = lCrtDate;
                [[NSNotificationCenter defaultCenter] postNotificationName:KNTFY_SHAKE_SUCCESS object:nil];
            }
        }];
        
        return YES;
    }
    
  • 為了代碼的對稱美和可能的相關業務,實作停止監聽搖一搖方法

    - (void)stopMonitorShake{
        [self.gMotionMnger stopAccelerometerUpdates];
        self.gMotionMnger = nil;
        self.gDateLastShakeSuc = nil;
    }
    

控制器相關邏輯和代碼

  • 開始監聽搖一搖

     BOOL lRes = [[MYAccelerometerTool sharedMYAccelerometerTool] startMonitorShake];
     NSLog(@"lRes:%d", lRes);
     NSAssert(lRes, @"開始監聽搖一搖失敗");
    
  • 監聽搖一搖成功的通知

     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(nmShakeSuccess:) name:KNTFY_SHAKE_SUCCESS object:nil];
    
    //在搖一搖的同時,通過觀察此方法是否有log,可以判斷是否有監聽到,
    - (void)nmShakeSuccess:(NSNotification *)ntfy{
        NSLog(@"%s", __FUNCTION__);
    }
    
  • dealloc方法中取消監聽

    - (void)dealloc{
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    

    運行 demo 工程,測驗可知,通過上述方法,的確可以在 APP 處于前臺時,實作監聽搖一搖動作的效果,可是,當把 APP 退到后臺或鎖屏時,nmShakeSuccess 方法不再有 log,即:APP 處于后臺時,通過監聽加速計的方法,默認也無法在 APP 處于后臺或鎖屏時實作監聽效果,這也印證了上文提到的那個評論者的疑問,

    可是 Hello KuGou! 明明實作了后臺或鎖屏時搖一搖的效果啊!難道是需要額外的配置?聯想 iOS 處于后臺時,默認會把 APP 的服務給掛起(suspended),只有當 APP 通過某種方式(后臺定位/播放音樂/藍牙掃描等)具有后臺運行權限時,才可以一直保活,可猜想,也許賦予 APP 具有后臺運行的權限后,就可以實作想要的功能了,于是,開始進行驗證如下,

APP 申請后臺運行權限后,能否監聽到搖一搖

因為作業中很多 APP 具有后臺定位權限和相關功能,所以本文通過為 APP 申請后臺定位權限來驗證,

APP 申請后臺定位權限

  • plist 檔案中增加”定位請求描述資訊“

    <key>NSLocationAlwaysUsageDescription</key>
    	<string>我們需要根據您的定位提供周邊搜索和導航服務</string>
    	<key>NSLocationWhenInUseUsageDescription</key>
    	<string>我們需要根據您的定位提供周邊搜索和導航服務</string>
    

    增加”后臺定位權限“

    <key>UIBackgroundModes</key>
    	<array>
    		<string>location</string>
    	</array>
    
  • 宣告定位管理員屬性

    @property(nonatomic, strong) CLLocationManager *gMnger;
    
  • 懶加載定位管理員,請求定位權限、允許后臺位置更新

    - (CLLocationManager *)gMnger{
        if (nil == _gMnger) {
            _gMnger = [[CLLocationManager alloc] init];
            _gMnger.delegate = self;
            _gMnger.allowsBackgroundLocationUpdates = YES;
            [_gMnger requestWhenInUseAuthorization];
        }
        return _gMnger;
    }
    
  • 代理 3 步走(用于驗證后臺定位是否生效)

    • 遵守代理協議

      @interface ViewController ()<CLLocationManagerDelegate>

    • 指定代理物件

      _gMnger.delegate = self;

    • 實作代理方法

      #pragma mark -  delegate
      - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
          NSLog(@"%s", __FUNCTION__);
      }
      
      - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
          NSLog(@"%s", __FUNCTION__);
      }
      
  • APP 后臺或鎖屏后,測驗能否成功監聽搖一搖

    運行 demo 工程,經測驗,把 APP 退到后臺或鎖屏,或即退到后臺又鎖屏,都能夠檢測到搖一搖事件,

多 APP 都實作此功能時,搖一搖是何效果

這里用 demo APP 和酷狗音樂 APP 進行測驗,

  • 同時打開這兩個 APP,其中酷狗音樂 APP 打開后臺搖一搖切歌的功能,
  • 酷狗音樂 APP 開始放歌,退到后臺,
  • demo APP 打開后,退到后臺,
  • 搖一搖,查看效果:
    • 當搖動的力度不是很大時,demo APP 回呼方法會被觸發;
    • 當搖動的力度很大時,demo APP 回呼方法和酷狗 APP 切歌會同時被觸發;
  • 由此可見,如果多個 APP 同時實作了此功能時,那么后臺或鎖屏搖一搖時,只要滿足了某個 APP 實作的加速計相關判定條件,就可以同時觸發多個 APP 對應的效果,

后臺定位權限 + 系統搖一搖,是否可行?

經測驗,還是不行,果然,系統搖一搖還是比較受限的,只能在前臺回呼,

文章小結

想要實作”iOS后臺鎖屏監聽搖一搖“功能,

首次,必須滿足一個硬性條件:APP 具有某種后臺運行的權限,

其次,技術實作上必須使用CoreMotion框架,通過監聽加速計回呼自己實作對搖一搖事件的監聽判定

最后,可通過增加時間屬性,實作對搖一搖事件監聽時的節流效果,防止持續搖動時,太過頻繁的事件回呼,

此外,多 APP 都實作此功能時,搖一搖的效果是:只要搖動力度很大,加速計資料滿足 APP 實作的搖一搖判定條件,就可以同時觸發多個 APP 各自對應的效果

因此,如果不是 APP 特別需要此功能,盡量不要這樣實作,畢竟,比較占用系統資源,而且太多 APP 同時實作時,可能會出現效果上的相互干擾,不過,如果合理利用此功能,卻可以為特殊用戶群體提供極大的便利

通過探索,滿足了視力障礙用戶的迫切需求,還是蠻有成就感的!

偷偷的告訴大家,寫到這里時,產品經理還沒告訴我他所知道的哪個 APP 實作了這個功能,可能他太忙,給忘記了吧......

參考文章

iOS應用退出到后臺后怎樣監聽搖晃事件

Demo 鏈接

OCDailyTests/BackgroundShakeTest

最后,感謝“技術創作101訓練營”!通過參加訓練營,讓我對寫作有了更深入的認識和更高的心里覺悟,

本文由博客群發一文多發等運營工具平臺 OpenWrite 發布

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/164502.html

標籤:其他

上一篇:Android連載37-跨程式共享資料

下一篇:android學習(2)service的使用以及個人理解

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more