一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - IOS - iOS實現后臺長時間運行

iOS實現后臺長時間運行

2021-05-14 16:00macro小K IOS

這篇文章主要為大家詳細介紹了iOS實現后臺長時間運行,具有一定的參考價值,感興趣的小伙伴們可以參考一下

前言

一般app在按下home鍵被掛起后,這時app的 backgroundtimeremaining 也就是后臺運行時間大約只有3分鐘,如果在退出app后,過十幾二十二分鐘或者更長時間再回到app,app就會回到剛打開時的狀態,也就是首頁;有的項目在被掛起后需要在后臺運行一段時間,使有足夠的時間來完成與服務器對接的操作,或者需要一直運行的需求;如果需要,則在app被掛起后,申請后臺,來延長后臺運行時間。

app申請后臺運行的方式有幾種:

播放音樂

定位

newsstand downloads

fetch 等;

iOS實現后臺長時間運行

這里主要說下后臺播放無聲音樂(其實是不播放),采用哪種方式,對應勾選上圖;我的項目中有音頻播放需求,如果沒有,那就找一個播放音頻的理由,或者用其他方式實現。

實現

這里采用了兩個單例:電話監控(xktelmanager)、后臺運行(xkbgrunmanager),電話監控可以忽略,視情況而用;采用單例是為了方便管理;

xktelmanager.h

?
1
2
3
4
5
6
7
8
9
10
11
#import <foundation/foundation.h>
 
@interface xktelmanager : nsobject
///是否在后臺運行
@property (nonatomic,assign) bool inbackgroundrun;
+ (xktelmanager *)sharedmanager;
/**
 來電監聽
 */
- (void)startmonitor;
@end

xktelmanager.m

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#import "xktelmanager.h"
#import "xkbgrunmanager.h"
#import <coretelephony/ctcallcenter.h>
#import <coretelephony/ctcall.h>
 
static xktelmanager *_sharedmanger;
@interface xktelmanager()
@property (nonatomic, strong) ctcallcenter *callcenter;
@end
@implementation xktelmanager
+ (xktelmanager *)sharedmanager{
  static dispatch_once_t oncetelsingle;
  dispatch_once(&oncetelsingle, ^{
    if (!_sharedmanger) {
      _sharedmanger = [[xktelmanager alloc]init];
    }
  });
  return _sharedmanger;
}
- (instancetype)init{
  self = [super init];
  if (self) {
    _inbackgroundrun = no;
  }
  return self;
}
#pragma mark -********* 監聽電話相關
- (void)startmonitor {
  __weak typeof(self) weakself = self;
  _callcenter = [[ctcallcenter alloc] init];
  _callcenter.calleventhandler = ^(ctcall * call) {
    ///如果已經進入后臺了,不做任何操作
    if (weakself.inbackgroundrun) {
      return;
    }
    ///app未進入后臺
    if ([call.callstate isequaltostring:ctcallstatedisconnected]){
      nslog(@"電話 --- 斷開連接");
      [[xkbgrunmanager sharedmanager] stopbgrun];
    }
    else if ([call.callstate isequaltostring:ctcallstateconnected]){
      nslog(@"電話 --- 接通");
    }
    else if ([call.callstate isequaltostring:ctcallstateincoming]){
      nslog(@"電話 --- 待接通");
      [[xkbgrunmanager sharedmanager] startbgrun];
    }
    else if ([call.callstate isequaltostring:ctcallstatedialing]){
      nslog(@"電話 --- 撥號中");
      [[xkbgrunmanager sharedmanager] startbgrun];
    }
    else {
      nslog(@"電話 --- 無操作");
    }
    
  };
}
@end

xkbgrunmanager.h

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#import <foundation/foundation.h>
 
@interface xkbgrunmanager : nsobject
+ (xkbgrunmanager *)sharedmanager;
 
/**
 開啟后臺運行
 */
- (void)startbgrun;
 
/**
 關閉后臺運行
 */
- (void)stopbgrun;
@end

xkbgrunmanager.m

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#import "xkbgrunmanager.h"
///循環時間
static nsinteger _circuladuration = 60;
static xkbgrunmanager *_sharedmanger;
@interface xkbgrunmanager()
@property (nonatomic,assign) uibackgroundtaskidentifier task;
///后臺播放
@property (nonatomic,strong) avaudioplayer *playerback;
@property (nonatomic, strong) nstimer *timerad;
///用來打印測試
@property (nonatomic, strong) nstimer *timerlog;
@property (nonatomic,assign) nsinteger count;
@end
@implementation xkbgrunmanager{
  cfrunloopref _runloopref;
  dispatch_queue_t _queue;
}
+ (xkbgrunmanager *)sharedmanager{
  static dispatch_once_t oncerunsingle;
  dispatch_once(&oncerunsingle, ^{
    if (!_sharedmanger) {
      _sharedmanger = [[xkbgrunmanager alloc]init];
    }
  });
  return _sharedmanger;
}
/// 重寫init方法,初始化音樂文件
- (instancetype)init {
  if (self = [super init]) {
    [self setupaudiosession];
    _queue = dispatch_queue_create("com.audio.inbackground", null);
    //靜音文件
    nsstring *filepath = [[nsbundle mainbundle] pathforresource:@"****" oftype:@"mp3"];
    nsurl *fileurl = [[nsurl alloc] initfileurlwithpath:filepath];
    self.playerback = [[avaudioplayer alloc] initwithcontentsofurl:fileurl error:nil];
    [self.playerback preparetoplay];
    // 0.0~1.0,默認為1.0
    self.playerback.volume = 0.01;
    // 循環播放
    self.playerback.numberofloops = -1;
  }
  return self;
}
 
- (void)setupaudiosession {
  // 新建audiosession會話
  avaudiosession *audiosession = [avaudiosession sharedinstance];
  // 設置后臺播放
  nserror *error = nil;
  [audiosession setcategory:avaudiosessioncategoryplayback withoptions:avaudiosessioncategoryoptionmixwithothers error:&error];
  if (error) {
    nslog(@"error setcategory avaudiosession: %@", error);
  }
  nslog(@"%d", audiosession.isotheraudioplaying);
  nserror *activeseterror = nil;
  // 啟動audiosession,如果一個前臺app正在播放音頻則可能會啟動失敗
  [audiosession setactive:yes error:&activeseterror];
  if (activeseterror) {
    nslog(@"error activating avaudiosession: %@", activeseterror);
  }
}
 
/**
 啟動后臺運行
 */
- (void)startbgrun{
  [self.playerback play];
  [self applyforbackgroundtask];
  ///確保兩個定時器同時進行
  dispatch_async(_queue, ^{
    self.timerlog = [[nstimer alloc] initwithfiredate:[nsdate date] interval:1 target:self selector:@selector(log) userinfo:nil repeats:yes];
    self.timerad = [[nstimer alloc] initwithfiredate:[nsdate date] interval:_circuladuration target:self selector:@selector(startaudioplay) userinfo:nil repeats:yes];
    _runloopref = cfrunloopgetcurrent();
    [[nsrunloop currentrunloop] addtimer:self.timerad formode:nsdefaultrunloopmode];
    [[nsrunloop currentrunloop] addtimer:self.timerlog formode:nsdefaultrunloopmode];
    cfrunlooprun();
  });
}
 
/**
 申請后臺
 */
- (void)applyforbackgroundtask{
  _task =[[uiapplication sharedapplication] beginbackgroundtaskwithexpirationhandler:^{
    dispatch_async(dispatch_get_main_queue(), ^{
      [[uiapplication sharedapplication] endbackgroundtask:_task];
      _task = uibackgroundtaskinvalid;
    });
  }];
}
 
/**
 打印
 */
- (void)log{
  _count = _count + 1;
  nslog(@"_count = %ld",_count)
}
 
/**
 檢測后臺運行時間
 */
- (void)startaudioplay{
  _count = 0;
  dispatch_async(dispatch_get_main_queue(), ^{
    if ([[uiapplication sharedapplication] backgroundtimeremaining] < 61.0) {
      nslog(@"后臺快被殺死了");
      [self.playerback play];
      [self applyforbackgroundtask];
    }
    else{
      nslog(@"后臺繼續活躍呢");
    }///再次執行播放器停止,后臺一直不會播放音樂文件
    [self.playerback stop];
  });
}
 
/**
 停止后臺運行
 */
- (void)stopbgrun{
  if (self.timerad) {
    cfrunloopstop(_runloopref);
    [self.timerlog invalidate];
    self.timerlog = nil;
    // 關閉定時器即可
    [self.timerad invalidate];
    self.timerad = nil;
    [self.playerback stop];
  }
  if (_task) {
    [[uiapplication sharedapplication] endbackgroundtask:_task];
    _task = uibackgroundtaskinvalid;
  }
}
 
@end

最后在 appdelegate.m 對應的方法中,實現開啟和停止后臺運行即可!

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://www.cnblogs.com/wangkejia/archive/2018/10/11/9773285.html

延伸 · 閱讀

精彩推薦
  • IOSiOS中UILabel實現長按復制功能實例代碼

    iOS中UILabel實現長按復制功能實例代碼

    在iOS開發過程中,有時候會用到UILabel展示的內容,那么就設計到點擊UILabel復制它上面展示的內容的功能,也就是Label長按復制功能,下面這篇文章主要給大...

    devilx12792021-04-02
  • IOS詳解iOS中多個網絡請求的同步問題總結

    詳解iOS中多個網絡請求的同步問題總結

    這篇文章主要介紹了詳解iOS中多個網絡請求的同步問題總結,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧...

    liang199111312021-03-15
  • IOSiOS開發之視圖切換

    iOS開發之視圖切換

    在iOS開發中視圖的切換是很頻繁的,獨立的視圖應用在實際開發過程中并不常見,除非你的應用足夠簡單。在iOS開發中常用的視圖切換有三種,今天我們將...

    執著丶執念5282021-01-16
  • IOSiOS實現控制屏幕常亮不變暗的方法示例

    iOS實現控制屏幕常亮不變暗的方法示例

    最近在工作中遇到了要將iOS屏幕保持常亮的需求,所以下面這篇文章主要給大家介紹了關于利用iOS如何實現控制屏幕常亮不變暗的方法,文中給出了詳細的...

    隨風13332021-04-02
  • IOSiOS中MD5加密算法的介紹和使用

    iOS中MD5加密算法的介紹和使用

    MD5加密是最常用的加密方法之一,是從一段字符串中通過相應特征生成一段32位的數字字母混合碼。對輸入信息生成唯一的128位散列值(32個字符)。這篇文...

    LYSNote5432021-02-04
  • IOSiOS開發技巧之狀態欄字體顏色的設置方法

    iOS開發技巧之狀態欄字體顏色的設置方法

    有時候我們需要根據不同的背景修改狀態欄字體的顏色,下面這篇文章主要給大家介紹了關于iOS開發技巧之狀態欄字體顏色的設置方法,文中通過示例代碼...

    夢想家-mxj8922021-05-10
  • IOSiOS自定義UICollectionViewFlowLayout實現圖片瀏覽效果

    iOS自定義UICollectionViewFlowLayout實現圖片瀏覽效果

    這篇文章主要介紹了iOS自定義UICollectionViewFlowLayout實現圖片瀏覽效果的相關資料,需要的朋友可以參考下...

    jiangamh8882021-01-11
  • IOSiOS中滑動控制屏幕亮度和系統音量(附加AVAudioPlayer基本用法和Masonry簡單使用)

    iOS中滑動控制屏幕亮度和系統音量(附加AVAudioPlayer基本用法和

    這篇文章主要介紹了iOS中滑動控制屏幕亮度和系統音量(附加AVAudioPlayer基本用法和Masonry簡單使用)的相關資料,需要的朋友可以參考下...

    CodingFire13652021-02-26
主站蜘蛛池模板: 九九99亚洲精品久久久久 | yjsp妖精视频在线观看免费 | 麻豆最新 | 我的男友是消防员在线观看 | 日韩国产成人 | 四虎免费入口 | 亚洲国产欧美在线成人aaaa | 女人是男人的未来1分49分 | 亚洲精品国产A久久久久久 亚洲精品福利一区二区在线观看 | 男人摸女人下面 | 国产高清视频 | 美女撒尿部位无遮挡 | 999资源站| www久久精品| 四虎影院最新网址 | 被强迫调教的高辣小说 | 久久成人国产精品一区二区 | blackedvideos黑人| 国产九九在线观看播放 | 午夜免费啪视频观看视频 | 青青青国产手机在线播放 | 国产精品一区二区国产 | 日韩性事 | 国产成人精品一区二三区2022 | 日韩久久精品 | 欧美性xxxxx 欧美性bbbbbxxxxxddd | 草草视频免费在线观看 | 欧美黑人成人免费全部 | 欧美色成人tv在线播放 | 青青在线观看视频 | 亚洲精品中文字幕在线 | 深夜免费网站 | 日本h片在线| 国产一区日韩二区欧美三区 | 91se精品免费观看 | 男人的天堂在线观看免费 | 九九热只有精品 | 色综合久久天天综合观看 | 特级毛片全部免费播放器 | 亚州在线| freexxxxxhd张柏芝 |