@@ -31,7 +31,8 @@ import { wantAgent, WantAgent } from '@kit.AbilityKit';
31
31
import { AbilityConstant , Want } from '@kit.AbilityKit' ;
32
32
import fs from '@ohos.file.fs' ;
33
33
import Logger from './Logger' ;
34
- import { AVAudioSessionCategory , AvplayerStatus , AvplayerSessionCategory } from './ts' ;
34
+ import { AVAudioSessionCategory , AvplayerStatus , AvplayerSessionCategory } from './ts' ;
35
+
35
36
const TAG : string = "[RNOH] Sound"
36
37
37
38
export interface PrepareProps {
@@ -44,7 +45,7 @@ interface E {
44
45
message : string
45
46
}
46
47
47
- enum Speed {
48
+ enum Speed {
48
49
ZERO = 0 ,
49
50
ONE = 1 ,
50
51
TWO = 2 ,
@@ -56,9 +57,10 @@ export class AVPlayerController {
56
57
private audioManager = audio . getAudioManager ( ) ;
57
58
public playerPool = new Map < Object , media . AVPlayer > ( ) ;
58
59
public isPlaying : boolean = false ;
59
- private category :AVAudioSessionCategory = "Playback" ;
60
- private mixWithOthers :Boolean = true ;
60
+ private category : AVAudioSessionCategory = "Playback" ;
61
+ private mixWithOthers : Boolean = true ;
61
62
private context = getContext ( this ) ;
63
+ private previousSrc : fs . File | string | undefined = undefined
62
64
63
65
//创建后台长任务
64
66
onCreate ( want : Want , launchParam : AbilityConstant . LaunchParam ) {
@@ -83,7 +85,7 @@ export class AVPlayerController {
83
85
wantAgent . getWantAgent ( wantAgentInfo ) . then ( ( wantAgentObj : WantAgent ) => {
84
86
try {
85
87
backgroundTaskManager . startBackgroundRunning ( this . context ,
86
- backgroundTaskManager . BackgroundMode . LOCATION , wantAgentObj , ( error : BusinessError , data : void ) => {
88
+ backgroundTaskManager . BackgroundMode . LOCATION , wantAgentObj , ( error : BusinessError , data : void ) => {
87
89
88
90
} )
89
91
} catch ( error ) {
@@ -99,13 +101,13 @@ export class AVPlayerController {
99
101
// 创建session
100
102
async createSession ( ) {
101
103
let type : AVSessionManager . AVSessionType = 'audio' ;
102
- let session = await AVSessionManager . createAVSession ( this . context , 'SESSION_NAME' , type ) ;
104
+ let session = await AVSessionManager . createAVSession ( this . context , 'SESSION_NAME' , type ) ;
103
105
104
106
// 激活接口要在元数据、控制命令注册完成之后再执行
105
107
await session . activate ( ) ;
106
108
}
107
109
108
- setAudioRendererInfo ( mediaPlayer : media . AVPlayer ) {
110
+ setAudioRendererInfo ( mediaPlayer : media . AVPlayer ) {
109
111
if ( this . category != null ) {
110
112
switch ( this . category ) {
111
113
case AvplayerSessionCategory . AMBIENT : //游戏模式
@@ -131,13 +133,13 @@ export class AVPlayerController {
131
133
}
132
134
}
133
135
134
- mediaPrepare ( mediaPlayer : media . AVPlayer , callBack : ( error : E | null , props :PrepareProps | null ) => void ) {
135
- mediaPlayer . prepare ( ) . then ( ( ) => {
136
- const props :PrepareProps = {
137
- duration :mediaPlayer . duration ,
136
+ mediaPrepare ( mediaPlayer : media . AVPlayer , callBack : ( error : E | null , props : PrepareProps | null ) => void ) {
137
+ mediaPlayer . prepare ( ) . then ( ( ) => {
138
+ const props : PrepareProps = {
139
+ duration : mediaPlayer . duration ,
138
140
}
139
141
callBack ( null , props ) ;
140
- } , ( err : BusinessError ) => {
142
+ } , ( err : BusinessError ) => {
141
143
const e : E = {
142
144
code : - 1 ,
143
145
message : `avPlay prepare error:${ err . name } message ${ err . message } }`
@@ -146,31 +148,55 @@ export class AVPlayerController {
146
148
} ) ;
147
149
}
148
150
149
- async prepare ( fileName : string , key : number , option : object , callBack : ( error : E | null , props :PrepareProps | null ) => void ) {
151
+ closeFsRawFd ( ) {
152
+ if ( typeof this . previousSrc === "string" ) {
153
+ try {
154
+ this . context . resourceManager . closeRawFdSync ( this . previousSrc ) ;
155
+ Logger . debug ( TAG , `aboutToDisappear, closeRawFd file succeed` ) ;
156
+ } catch ( error ) {
157
+ Logger . debug ( TAG , `aboutToDisappear, closeRawFd error is${ error . message } error code:${ error . code } ` ) ;
158
+ }
159
+ } else if ( typeof this . previousSrc === "object" ) {
160
+ try {
161
+ fs . closeSync ( this . previousSrc )
162
+ Logger . debug ( TAG , `aboutToDisappear, close file succeed` ) ;
163
+ } catch ( error ) {
164
+ Logger . debug ( TAG , `aboutToDisappear, close file failed with error message:${ error . message } ,error code:${ error . code } ` ) ;
165
+ }
166
+ }
167
+ }
168
+
169
+
170
+ async prepare ( fileName : string , key : number , option : object ,
171
+ callBack : ( error : E | null , props : PrepareProps | null ) => void ) {
172
+ this . closeFsRawFd ( )
150
173
const mediaPlayer : media . AVPlayer = await media . createAVPlayer ( ) ;
151
174
let fileUrl : string = '' ;
152
- if ( fileName . startsWith ( 'asset' ) ) { //在npm run dev起服务的时候 用require('./frog.wav') 引入的文件
175
+ if ( fileName . startsWith ( 'asset' ) ) { //在npm run dev起服务的时候 用require('./frog.wav') 引入的文件
153
176
fileUrl = fileName . split ( '//' ) [ 1 ] ;
154
177
let fileDescriptor = await this . context . resourceManager . getRawFd ( `assets/${ fileUrl } ` ) ;
178
+ this . previousSrc = `assets/${ fileUrl } `
155
179
mediaPlayer . fdSrc = fileDescriptor ;
156
- } else if ( fileName . startsWith ( "http://" ) || fileName . startsWith ( "https://" ) ) { //音频资源是网络资源和npm run start起服务的时候 用require('./frog.wav') 引入的文件
180
+ } else if ( fileName . startsWith ( "http://" ) ||
181
+ fileName . startsWith ( "https://" ) ) { //音频资源是网络资源和npm run start起服务的时候 用require('./frog.wav') 引入的文件
157
182
mediaPlayer . url = fileName ;
158
- } else if ( fileName . startsWith ( '/data' ) ) {
159
- let resFile = fs . openSync ( fileName , fs . OpenMode . READ_ONLY )
160
- mediaPlayer . url = `fd://${ resFile . fd } ` ;
161
- } else { //资源在resources/rawfile 下的资源 url: 'whoosh.mp3',
183
+ this . previousSrc = undefined
184
+ } else if ( fileName . startsWith ( '/data' ) || fileName . startsWith ( 'file:' ) ) {
185
+ this . previousSrc = fs . openSync ( fileName , fs . OpenMode . READ_ONLY )
186
+ mediaPlayer . url = `fd://${ this . previousSrc . fd } ` ;
187
+ } else { //资源在resources/rawfile 下的资源 url: 'whoosh.mp3',
162
188
let fileDescriptor = await this . context . resourceManager . getRawFd ( fileName ) ;
189
+ this . previousSrc = fileName
163
190
mediaPlayer . fdSrc = fileDescriptor ;
164
191
}
165
-
166
192
mediaPlayer . on ( 'stateChange' , async ( state , reason ) => {
167
193
switch ( state ) {
168
194
case AvplayerStatus . IDLE :
169
195
Logger . info ( TAG , 'stateChange AVPlayerstate initialized called. idle' ) ;
170
196
break ;
171
197
case AvplayerStatus . INITIALIZED : // avplayer 设置播放源后触发该状态上报
172
198
this . setAudioRendererInfo ( mediaPlayer ) ;
173
- this . mediaPrepare ( mediaPlayer , callBack ) ;
199
+ this . mediaPrepare ( mediaPlayer , callBack ) ;
174
200
break ;
175
201
default :
176
202
Logger . info ( TAG , 'stateChange AVPlayer state unknown called.' ) ;
@@ -195,12 +221,14 @@ export class AVPlayerController {
195
221
196
222
//播放错误监听
197
223
mediaPlayer . on ( 'error' , ( err : BusinessError ) => {
198
- Logger . error ( TAG , `failed, code is ${ err . code } , message is ${ err . message } ` ) ;
224
+ Logger . error ( TAG , `failed, code is ${ err . code } , message is ${ err . message } ` ) ;
199
225
mediaPlayer . reset ( ) ; // 调用reset重置资源,触发idle状态
200
226
} )
227
+
228
+
201
229
}
202
230
203
- play ( key : number , ctx , callback ?: ( success : boolean ) => void ) : void {
231
+ play ( key : number , ctx , callback ?: ( success : boolean ) => void ) : void {
204
232
const player : media . AVPlayer | undefined = this . playerPool . get ( key ) ;
205
233
if ( player === null && player === undefined ) {
206
234
if ( callback != null ) {
@@ -211,10 +239,10 @@ export class AVPlayerController {
211
239
player ?. on ( 'stateChange' , ( state , reason ) => {
212
240
switch ( state ) {
213
241
case AvplayerStatus . COMPLETED : // 播放结束后触发该状态机上报
214
- ctx . rnInstance . emitDeviceEvent ( "onPlayChange" , { isPlaying :false , playerKey :key } ) ;
215
- setTimeout ( ( ) => {
242
+ ctx . rnInstance . emitDeviceEvent ( "onPlayChange" , { isPlaying : false , playerKey : key } ) ;
243
+ setTimeout ( ( ) => {
216
244
callback ?.( true ) ;
217
- } , 1000 )
245
+ } , 1000 )
218
246
this . isPlaying = false ;
219
247
break ;
220
248
case AvplayerStatus . PLAYING : // play成功调用后触发该状态机上报
@@ -228,9 +256,9 @@ export class AVPlayerController {
228
256
229
257
player ?. play ( ( err : BusinessError ) => {
230
258
if ( err ) {
231
- ctx . rnInstance . emitDeviceEvent ( "onPlayChange" , { isPlaying :false , playerKey :key } )
259
+ ctx . rnInstance . emitDeviceEvent ( "onPlayChange" , { isPlaying : false , playerKey : key } )
232
260
} else {
233
- ctx . rnInstance . emitDeviceEvent ( "onPlayChange" , { isPlaying :true , playerKey :key } )
261
+ ctx . rnInstance . emitDeviceEvent ( "onPlayChange" , { isPlaying : true , playerKey : key } )
234
262
}
235
263
} )
236
264
@@ -239,10 +267,10 @@ export class AVPlayerController {
239
267
pause ( key : number , cb ?: ( ) => void ) : void {
240
268
const player : media . AVPlayer | undefined = this . playerPool . get ( key ) ;
241
269
if ( this . isPlaying ) {
242
- player ?. pause ( ) . then ( ( ) => {
270
+ player ?. pause ( ) . then ( ( ) => {
243
271
Logger . info ( TAG , `sound: AVPlayer pause success` ) ;
244
272
cb ?.( ) ;
245
- } , ( err : Error ) => {
273
+ } , ( err : Error ) => {
246
274
Logger . error ( TAG , `sound: AVPlayer pause error${ err . name } , message is ${ err . message } ` ) ;
247
275
} ) ;
248
276
}
@@ -265,12 +293,13 @@ export class AVPlayerController {
265
293
try {
266
294
player ?. reset ( ) ;
267
295
} catch ( e ) {
268
- Logger . info ( TAG , `sound reset error: ${ e } } ` ) ;
296
+ Logger . info ( TAG , `sound reset error: ${ e } } ` ) ;
269
297
}
270
298
}
271
299
272
300
release ( key : number ) : void {
273
301
const player : media . AVPlayer | undefined = this . playerPool . get ( key ) ;
302
+ this . closeFsRawFd ( )
274
303
player ?. release ( ) ;
275
304
}
276
305
@@ -284,7 +313,7 @@ export class AVPlayerController {
284
313
player ?. setVolume ( volume )
285
314
}
286
315
287
- getCurrentTime ( key : number , callback ?: ( currentPosition : number | undefined , isPlaying : boolean ) => void ) {
316
+ getCurrentTime ( key : number , callback ?: ( currentPosition : number | undefined , isPlaying : boolean ) => void ) {
288
317
const player : media . AVPlayer | undefined = this . playerPool . get ( key ) ;
289
318
if ( player === null && player === undefined ) {
290
319
callback ?.( - 1 , false ) ;
@@ -295,7 +324,7 @@ export class AVPlayerController {
295
324
296
325
setCurrentTime ( key : number , value : number ) : void {
297
326
const player : media . AVPlayer | undefined = this . playerPool . get ( key ) ;
298
- if ( player !== null && player !== undefined ) {
327
+ if ( player !== null && player !== undefined ) {
299
328
if ( value < 0 ) {
300
329
value = 0
301
330
} else if ( value > player . duration ) {
@@ -307,9 +336,9 @@ export class AVPlayerController {
307
336
}
308
337
309
338
// value is : 0,1,2,3,4
310
- setSpeed ( key :number , value : number ) : void {
339
+ setSpeed ( key : number , value : number ) : void {
311
340
const player : media . AVPlayer | undefined = this . playerPool . get ( key ) ;
312
- if ( player !== null && player !== undefined ) {
341
+ if ( player !== null && player !== undefined ) {
313
342
player ?. setSpeed ( value )
314
343
}
315
344
}
@@ -326,14 +355,14 @@ export class AVPlayerController {
326
355
327
356
}
328
357
329
- setNumberOfLoops ( key :number , value : boolean ) : void {
358
+ setNumberOfLoops ( key : number , value : boolean ) : void {
330
359
const player : media . AVPlayer | undefined = this . playerPool . get ( key ) ;
331
- if ( player !== null && player !== undefined ) {
360
+ if ( player !== null && player !== undefined ) {
332
361
player . loop = value
333
362
}
334
363
}
335
364
336
- setCategory ( category : AVAudioSessionCategory , mixWithOthers : boolean ) :void {
365
+ setCategory ( category : AVAudioSessionCategory , mixWithOthers : boolean ) : void {
337
366
this . category = category
338
367
this . mixWithOthers = mixWithOthers
339
368
}
0 commit comments