diff --git a/NdkQoS/entry/build-profile.json5 b/NdkQoS/entry/build-profile.json5 index c55d07243fd079a446d490ef5f603debb4879b14..e9ff86246f834a19369c5760a794b6ead7a300eb 100644 --- a/NdkQoS/entry/build-profile.json5 +++ b/NdkQoS/entry/build-profile.json5 @@ -31,10 +31,7 @@ "arkOptions": { "obfuscation": { "ruleOptions": { - "enable": true, - "files": [ - "./obfuscation-rules.txt" - ] + "enable": false } } }, diff --git a/avscreen-capture-screen-record-master/README.en.md b/avscreen-capture-screen-record-master/README.en.md index 9b5ef2b1c06496dc74a482af292a2d4618e26f74..d8f69d3c5127ffd9f38ceb0cb02bae924e4ccae6 100644 --- a/avscreen-capture-screen-record-master/README.en.md +++ b/avscreen-capture-screen-record-master/README.en.md @@ -1,36 +1,75 @@ -# AVScreenCaptureScreenRecord +# Screen Recording Based on AVScreenCapture -#### Description -{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**} +### Overview -#### Software Architecture -Software architecture description +This sample demonstrates how to implement screen recording using AVScreenCapture, including recording to a file using ArkTS, recording to a file using C/C++, and recording and transcoding stream using C/C++. Based on this case, you can master the screen recording capabilities of AVScreenCapture. -#### Installation +### Preview -1. xxxx -2. xxxx -3. xxxx + -#### Instructions +### How to Use -1. xxxx -2. xxxx -3. xxxx +On the home page, the user taps the corresponding button to navigate to the page for a specific scenario. Each scenario page contains a video playback area and two buttons. Tapping **Record** will trigger a request for necessary permissions. After the user grants permissions, screen recording starts. During this period, recording can continue even if it exits to the background. The user taps **Stop**, or **Stop** in the screen capsule at the top left, to stop video recording. After recording is complete, the page refreshes to display the recorded file. With a tap on **Play**, it starts to play in the playback area. -#### Contribution +### Project Structure** -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request +``` +├──entry/src/main/cpp // C++ code area. +│ ├──CAVScreenCaptureToFile // Recording the video to the file module using C/C++. +│ │ ├──CAVScreenCaptureToFile.cpp +│ │ └──CAVScreenCaptureToFile.h +│ ├──CAVScreenCaptureToStream // Recording and transcoding stream module using C/C++. +│ │ ├──AudioCapturer.cpp // Audio recording file. +│ │ ├──AudioCapturer.h +│ │ ├──AudioEncoder.cpp // Audio encoder file. +│ │ ├──AudioEncoder.h +│ │ ├──CAVScreenCaptureToStream.cpp // Recording and transcoding stream. +│ │ ├──CAVScreenCaptureToStream.h +│ │ ├──Muxer.cpp // Multiplexer file. +│ │ ├──Muxer.h +│ │ ├──SampleInfo.h // Custom data type. +│ │ ├──VideoEncoder.cpp // Video encoder file. +│ │ └──VideoEncoder.h +│ ├──types +│ │ └──libentry // C++ APIs. +│ │ ├──Index.d.ts +│ │ └──oh-package.json5 +│ ├──CMakeLists.txt // CMake configuration file. +│ └──napi_init.cpp // Native-side code entry. +├──entry/src/main/ets // ArkTS code area. +│ ├──entryability +│ │ └──EntryAbility.ets +│ ├──entrybackupability +│ │ └──EntryBackupAbility.ets +│ ├──common +│ │ ├──constants // Constant definitions. +│ │ │ └──CommonConstants.ets +│ │ └──utils // Video time conversion utilities. +│ │ └──TimeUtils.ets +│ ├──model +│ │ └──MyAVScreenCapture.ets // Module for screen recording to files using ArkTS. +│ └──pages // ArkTS side pages. +│ ├──ArkTSAVScreenCapture.ets // Page for screen recording to files using ArkTS. +│ ├──CAVScreenCaptureToFile.ets // Page for screen recording to files using C/C++. +│ ├──CAVScreenCaptureToStream.ets // Page for recording and transcoding streams using C/C++. +│ └──Index.ets // Home page. +└──entry/src/main/resources // Application resource files. +``` +### Required Permissions -#### Gitee Feature +1. **ohos.permission.KEEP_BACKGROUND_RUNNING**: required for background continuous task permission. -1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md -2. Gitee blog [blog.gitee.com](https://blog.gitee.com) -3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) -4. The most valuable open source project [GVP](https://gitee.com/gvp) -5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) -6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) +2. **ohos.permission.MICROPHONE**: required for microphone permission. + +### References + +N/A + +### Restrictions + +1. This sample is only supported on Huawei phones running standard systems. +2. The HarmonyOS version must be HarmonyOS 5.1.0 Release or later. +3. The DevEco Studio version must be DevEco Studio 5.1.0 Release or later. +4. The HarmonyOS SDK version must be HarmonyOS 5.1.0 Release SDK or later. \ No newline at end of file diff --git a/avscreen-capture-screen-record-master/entry/oh-package-lock.json5 b/avscreen-capture-screen-record-master/entry/oh-package-lock.json5 index 7c36300c3272430b97f5cda7cb1a835421298382..05149e9a0799aca540bf4cd16ae71233319d991b 100644 --- a/avscreen-capture-screen-record-master/entry/oh-package-lock.json5 +++ b/avscreen-capture-screen-record-master/entry/oh-package-lock.json5 @@ -12,7 +12,7 @@ "libentry.so@src/main/cpp/types/libentry": { "name": "libentry.so", "version": "1.0.0", - "resolved": "src/main/cpp/types/libentry", + "resolved": "", "registryType": "local" } } diff --git a/avscreen-capture-screen-record-master/entry/src/main/ets/entryability/EntryAbility.ets b/avscreen-capture-screen-record-master/entry/src/main/ets/entryability/EntryAbility.ets index 408df0cf25684feb1c1e10f58495a51bc12d0fb3..464cc12c729f50ae9713e8787a78081d42f0d7dd 100644 --- a/avscreen-capture-screen-record-master/entry/src/main/ets/entryability/EntryAbility.ets +++ b/avscreen-capture-screen-record-master/entry/src/main/ets/entryability/EntryAbility.ets @@ -54,6 +54,8 @@ export default class EntryAbility extends UIAbility { }).catch((err: BusinessError) => { hilog.error(DOMAIN, 'testTag', 'Failed to operation startBackgroundRunning. %{public}s', JSON.stringify(err)); }); + }).catch((err: BusinessError) => { + hilog.error(DOMAIN, 'testTag', 'Failed to operation getWantAgent. %{public}s', JSON.stringify(err)); }); } @@ -66,8 +68,13 @@ export default class EntryAbility extends UIAbility { } onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { - this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); - hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + try { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } catch (error) { + let err = error as BusinessError; + hilog.error(0x0000, 'testTag', `setColorMode fail. code = ${err.code}, message = ${err.message}`); + } } onDestroy(): void { @@ -99,10 +106,16 @@ export default class EntryAbility extends UIAbility { } hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); }); - // [Start get_size] - let displayInfo = display.getDefaultDisplaySync(); - // [End get_size] - AppStorage.setOrCreate('displayInfo', displayInfo); + + try { + // [Start get_size] + let displayInfo = display.getDefaultDisplaySync(); + // [End get_size] + AppStorage.setOrCreate('displayInfo', displayInfo); + } catch (error) { + let err = error as BusinessError; + hilog.error(0x0000, 'testTag', `getDefaultDisplaySync fail. code = ${err.code}, message = ${err.message}`); + } } onWindowStageDestroy(): void { diff --git a/avscreen-capture-screen-record-master/entry/src/main/ets/model/MyAVScreenCapture.ets b/avscreen-capture-screen-record-master/entry/src/main/ets/model/MyAVScreenCapture.ets index d01bcceec9a4e174911849e4b1f1316bc3580d2a..6625e57e613e010fd382627d117ed7525d2e60eb 100644 --- a/avscreen-capture-screen-record-master/entry/src/main/ets/model/MyAVScreenCapture.ets +++ b/avscreen-capture-screen-record-master/entry/src/main/ets/model/MyAVScreenCapture.ets @@ -14,7 +14,7 @@ */ import { media } from '@kit.MediaKit'; import { fileIo as fs } from '@kit.CoreFileKit'; -import { systemDateTime } from '@kit.BasicServicesKit'; +import { systemDateTime, BusinessError } from '@kit.BasicServicesKit'; import { display } from '@kit.ArkUI'; import { hilog } from '@kit.PerformanceAnalysisKit'; import { CommonConstants } from '../common/constants/CommonConstants'; @@ -28,14 +28,19 @@ export class MyAVScreenCapture { private file: fs.File | null = null; private displayInfo: display.Display = AppStorage.get('displayInfo') as display.Display; - // 开始屏幕录制 public async startRecording(filesDir: string) { // [Start create_record] // 获取fd this.updateFileFd(filesDir); // 实例化对象 - this.screenCapture = await media.createAVScreenCaptureRecorder(); + try { + this.screenCapture = await media.createAVScreenCaptureRecorder(); + } catch (error) { + let err = error as BusinessError; + hilog.error(0x0000, 'testTag', + `createAVScreenCaptureRecorder fail. code = ${err.code}, message = ${err.message}`); + } if (this.screenCapture != undefined) { hilog.info(0xFF00, CommonConstants.LOG_TAG, 'ScreenCapture has been created successfully.'); } else { @@ -113,15 +118,20 @@ export class MyAVScreenCapture { displayId: 0, }; // [End set_config] - - // [Start init_config] - await this.screenCapture?.init(captureConfig); - // [End init_config] - - // [Start start_record] - await this.screenCapture?.startRecording(); - // [End start_record] + try { + // [Start init_config] + await this.screenCapture?.init(captureConfig); + // [End init_config] + + // [Start start_record] + await this.screenCapture?.startRecording(); + // [End start_record] + } catch (error) { + let err = error as BusinessError; + hilog.error(0x0000, 'testTag', `start fail. code = ${err.code}, message = ${err.message}`); + } } + // [Start stop_record] // 停止录屏 public async stopRecording() { @@ -129,14 +139,21 @@ export class MyAVScreenCapture { hilog.info(0xFF00, CommonConstants.LOG_TAG, 'ScreenCapture exception.'); return; } - await this.screenCapture?.stopRecording(); - // 调用release()方法来销毁实例并释放资源 - await this.screenCapture?.release(); + try { + await this.screenCapture?.stopRecording(); - // 关闭文件 - fs.close((this.file as fs.File).fd); + // 调用release()方法来销毁实例并释放资源 + await this.screenCapture?.release(); + + // 关闭文件 + fs.close((this.file as fs.File).fd); + } catch (error) { + let err = error as BusinessError; + hilog.error(0x0000, 'testTag', `stop fail. code = ${err.code}, message = ${err.message}`); + } } + // [End stop_record] // [Start get_file_fd] @@ -144,8 +161,14 @@ export class MyAVScreenCapture { // 获取文件fd this.fileName = systemDateTime.getTime(true).toString() + '.mp4'; this.path = filesDir + '/' + this.fileName; - this.file = fs.openSync(this.path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); + try { + this.file = fs.openSync(this.path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); + } catch (error) { + let err = error as BusinessError; + hilog.error(0x0000, 'testTag', `openSync fail. code = ${err.code}, message = ${err.message}`); + } } + // [End get_file_fd] public getPath(): string { diff --git a/avscreen-capture-screen-record-master/entry/src/main/ets/pages/CAVScreenCaptureToFile.ets b/avscreen-capture-screen-record-master/entry/src/main/ets/pages/CAVScreenCaptureToFile.ets index 47dfc247c18f840146801f7a45cab218cf6f399c..9014ba7ba82fca0fde2831e5a8432069f8c09fab 100644 --- a/avscreen-capture-screen-record-master/entry/src/main/ets/pages/CAVScreenCaptureToFile.ets +++ b/avscreen-capture-screen-record-master/entry/src/main/ets/pages/CAVScreenCaptureToFile.ets @@ -51,29 +51,41 @@ export struct CAVScreenCaptureToFile { this.filepath = this.getUIContext().getHostContext()?.filesDir + '/' + this.tmpFileNameTwo; hilog.info(0xFF00, CommonConstants.LOG_TAG, 'filepath uri: %{public}s', this.filepath); - // 获取文件信息 - this.file = fs.openSync(this.filepath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); - // [StartExclude create_file_fd1] - avScreenCapture.setStopCallbackToFile(this.StopCallback); - // [EndExclude create_file_fd1] + try { + // 获取文件信息 + this.file = fs.openSync(this.filepath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); + // [StartExclude create_file_fd1] + avScreenCapture.setStopCallbackToFile(this.StopCallback); + // [EndExclude create_file_fd1] - // 调用native方法开启录制并传递fd、宽高 - avScreenCapture.startScreenCaptureToFile(this.file.fd, this.displayInfo.width, this.displayInfo.height); + // 调用native方法开启录制并传递fd、宽高 + avScreenCapture.startScreenCaptureToFile(this.file.fd, this.displayInfo.width, this.displayInfo.height); - // [StartExclude create_file_fd1] - this.videoSrc = 'file://' + this.filepath; - AppStorage.setOrCreate('videoSrcTwo', this.videoSrc); - // [EndExclude create_file_fd1] + // [StartExclude create_file_fd1] + this.videoSrc = 'file://' + this.filepath; + AppStorage.setOrCreate('videoSrcTwo', this.videoSrc); + // [EndExclude create_file_fd1] + } catch (error) { + let err = error as BusinessError; + hilog.error(0x0000, 'testTag', `startScreenCaptureToFile fail. code = ${err.code}, message = ${err.message}`); + } } + // [End create_file_fd1] // [Start release_fd1] async releaseFD() { if (this.file?.fd != undefined && this.file.fd?.valueOf() > 0) { // 关闭文件 - fs.close(this.file.fd); + try { + fs.close(this.file.fd); + } catch (error) { + let err = error as BusinessError; + hilog.error(0x0000, 'testTag', `close fail. code = ${err.code}, message = ${err.message}`); + } } } + // [End release_fd1] diff --git a/avscreen-capture-screen-record-master/entry/src/main/ets/pages/CAVScreenCaptureToStream.ets b/avscreen-capture-screen-record-master/entry/src/main/ets/pages/CAVScreenCaptureToStream.ets index c707ac072a08cb4ada1d2d05c971f294e82e5fa0..9cecce608823286cce0cae1cc1b5491ce4d77da1 100644 --- a/avscreen-capture-screen-record-master/entry/src/main/ets/pages/CAVScreenCaptureToStream.ets +++ b/avscreen-capture-screen-record-master/entry/src/main/ets/pages/CAVScreenCaptureToStream.ets @@ -50,31 +50,42 @@ export struct CAVScreenCaptureToStream { // [EndExclude create_file_fd2] this.filepath = this.getUIContext().getHostContext()?.filesDir + '/' + this.tmpFileNameThree; hilog.info(0xFF00, CommonConstants.LOG_TAG, 'filepath uri: %{public}s', this.filepath); + try { + // 获取文件信息 + this.file = fs.openSync(this.filepath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); - // 获取文件信息 - this.file = fs.openSync(this.filepath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); + // [StartExclude create_file_fd2] + avScreenCapture.setStopCallbackToStream(this.StopCallback); + // [EndExclude create_file_fd2] - // [StartExclude create_file_fd2] - avScreenCapture.setStopCallbackToStream(this.StopCallback); - // [EndExclude create_file_fd2] - - // 调用native方法开启录制并传递fd、宽高 - avScreenCapture.startScreenCaptureToStream(this.file.fd, this.displayInfo.width, this.displayInfo.height) + // 调用native方法开启录制并传递fd、宽高 + avScreenCapture.startScreenCaptureToStream(this.file.fd, this.displayInfo.width, this.displayInfo.height) - // [StartExclude create_file_fd2] - this.videoSrc = 'file://' + this.filepath; - AppStorage.setOrCreate('videoSrcThree', this.videoSrc); - // [EndExclude create_file_fd2] + // [StartExclude create_file_fd2] + this.videoSrc = 'file://' + this.filepath; + AppStorage.setOrCreate('videoSrcThree', this.videoSrc); + // [EndExclude create_file_fd2] + } catch (error) { + let err = error as BusinessError; + hilog.error(0x0000, 'testTag', `startScreenCaptureToStream fail. code = ${err.code}, message = ${err.message}`); + } } + // [End create_file_fd2] // [Start release_fd2] async releaseFD() { if (this.file?.fd != undefined && this.file.fd?.valueOf() > 0) { // 关闭文件 - fs.close(this.file.fd); + try { + fs.close(this.file.fd); + } catch (error) { + let err = error as BusinessError; + hilog.error(0x0000, 'testTag', `close fail. code = ${err.code}, message = ${err.message}`); + } } } + // [End release_fd2] build() { diff --git a/avscreen-capture-screen-record-master/screenshots/device/PreviewImage_EN.png b/avscreen-capture-screen-record-master/screenshots/device/PreviewImage_EN.png index 826c4e01d43f0aece5e00b52d92c8c0133865072..3557d96be7da5c39d338d51477f15e7db5ea334b 100644 Binary files a/avscreen-capture-screen-record-master/screenshots/device/PreviewImage_EN.png and b/avscreen-capture-screen-record-master/screenshots/device/PreviewImage_EN.png differ diff --git a/avscreen-capture-screen-record-master/screenshots/device/PreviewImage_ZH.png b/avscreen-capture-screen-record-master/screenshots/device/PreviewImage_ZH.png index 5bb4150a2091c6dede9102b8e97e75393a3e626a..7f2c08aa88a7b35130053f4087a0edf13bd6af42 100644 Binary files a/avscreen-capture-screen-record-master/screenshots/device/PreviewImage_ZH.png and b/avscreen-capture-screen-record-master/screenshots/device/PreviewImage_ZH.png differ