react-native-video-trim 4.1.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +89 -76
  3. package/VideoTrim.podspec +3 -3
  4. package/android/build.gradle +6 -53
  5. package/android/gradle.properties +1 -1
  6. package/android/src/main/AndroidManifest.xml +1 -1
  7. package/android/src/main/java/com/{margelo/nitro/videotrim/VideoTrim.kt → videotrim/VideoTrimModule.kt} +246 -232
  8. package/android/src/main/java/com/videotrim/VideoTrimPackage.kt +33 -0
  9. package/android/src/main/java/com/{margelo/nitro/videotrim → videotrim}/enums/ErrorCode.java +1 -1
  10. package/android/src/main/java/com/{margelo/nitro/videotrim → videotrim}/interfaces/IVideoTrimmerView.java +1 -1
  11. package/android/src/main/java/com/{margelo/nitro/videotrim → videotrim}/interfaces/VideoTrimListener.java +5 -4
  12. package/android/src/main/java/com/{margelo/nitro/videotrim → videotrim}/utils/MediaMetadataUtil.java +1 -1
  13. package/android/src/main/java/com/{margelo/nitro/videotrim → videotrim}/utils/StorageUtil.java +1 -1
  14. package/android/src/main/java/com/{margelo/nitro/videotrim → videotrim}/utils/VideoTrimmerUtil.java +20 -18
  15. package/android/src/main/java/com/{margelo/nitro/videotrim → videotrim}/widgets/VideoTrimmerView.java +44 -45
  16. package/ios/AssetLoader.h +19 -0
  17. package/ios/AssetLoader.mm +87 -0
  18. package/ios/ErrorCode.h +9 -0
  19. package/ios/ProgressAlertController.h +15 -0
  20. package/ios/ProgressAlertController.mm +78 -0
  21. package/ios/VideoTrim.h +31 -0
  22. package/ios/VideoTrim.mm +663 -0
  23. package/ios/VideoTrimmer.h +67 -0
  24. package/ios/VideoTrimmer.mm +863 -0
  25. package/ios/VideoTrimmerThumb.h +23 -0
  26. package/ios/VideoTrimmerThumb.mm +175 -0
  27. package/ios/VideoTrimmerViewController.h +52 -0
  28. package/ios/VideoTrimmerViewController.mm +533 -0
  29. package/lib/module/NativeVideoTrim.js +5 -0
  30. package/lib/module/NativeVideoTrim.js.map +1 -0
  31. package/lib/module/index.js +22 -24
  32. package/lib/module/index.js.map +1 -1
  33. package/lib/typescript/src/NativeVideoTrim.d.ts +107 -0
  34. package/lib/typescript/src/NativeVideoTrim.d.ts.map +1 -0
  35. package/lib/typescript/src/index.d.ts +13 -10
  36. package/lib/typescript/src/index.d.ts.map +1 -1
  37. package/package.json +15 -18
  38. package/src/NativeVideoTrim.ts +113 -0
  39. package/src/index.tsx +26 -31
  40. package/android/CMakeLists.txt +0 -24
  41. package/android/src/main/cpp/cpp-adapter.cpp +0 -6
  42. package/android/src/main/java/com/margelo/nitro/videotrim/VideoTrimPackage.kt +0 -22
  43. package/ios/AssetLoader.swift +0 -99
  44. package/ios/ErrorCode.swift +0 -17
  45. package/ios/ProgressAlertController.swift +0 -100
  46. package/ios/VideoTrim.swift +0 -67
  47. package/ios/VideoTrimImpl.swift +0 -957
  48. package/ios/VideoTrimmer.swift +0 -872
  49. package/ios/VideoTrimmerThumb.swift +0 -175
  50. package/ios/VideoTrimmerViewController.swift +0 -557
  51. package/lib/module/VideoTrim.nitro.js +0 -4
  52. package/lib/module/VideoTrim.nitro.js.map +0 -1
  53. package/lib/typescript/src/VideoTrim.nitro.d.ts +0 -257
  54. package/lib/typescript/src/VideoTrim.nitro.d.ts.map +0 -1
  55. package/nitrogen/generated/android/c++/JEditorConfig.hpp +0 -237
  56. package/nitrogen/generated/android/c++/JFileValidationResult.hpp +0 -61
  57. package/nitrogen/generated/android/c++/JFunc_void.hpp +0 -74
  58. package/nitrogen/generated/android/c++/JFunc_void_std__string_std__unordered_map_std__string__std__string_.hpp +0 -89
  59. package/nitrogen/generated/android/c++/JHybridVideoTrimSpec.cpp +0 -151
  60. package/nitrogen/generated/android/c++/JHybridVideoTrimSpec.hpp +0 -68
  61. package/nitrogen/generated/android/c++/JTrimOptions.hpp +0 -109
  62. package/nitrogen/generated/android/kotlin/com/margelo/nitro/videotrim/EditorConfig.kt +0 -72
  63. package/nitrogen/generated/android/kotlin/com/margelo/nitro/videotrim/FileValidationResult.kt +0 -28
  64. package/nitrogen/generated/android/kotlin/com/margelo/nitro/videotrim/Func_void.kt +0 -80
  65. package/nitrogen/generated/android/kotlin/com/margelo/nitro/videotrim/Func_void_std__string_std__unordered_map_std__string__std__string_.kt +0 -80
  66. package/nitrogen/generated/android/kotlin/com/margelo/nitro/videotrim/HybridVideoTrimSpec.kt +0 -86
  67. package/nitrogen/generated/android/kotlin/com/margelo/nitro/videotrim/TrimOptions.kt +0 -40
  68. package/nitrogen/generated/android/kotlin/com/margelo/nitro/videotrim/videotrimOnLoad.kt +0 -35
  69. package/nitrogen/generated/android/videotrim+autolinking.cmake +0 -78
  70. package/nitrogen/generated/android/videotrim+autolinking.gradle +0 -27
  71. package/nitrogen/generated/android/videotrimOnLoad.cpp +0 -50
  72. package/nitrogen/generated/android/videotrimOnLoad.hpp +0 -25
  73. package/nitrogen/generated/ios/VideoTrim+autolinking.rb +0 -60
  74. package/nitrogen/generated/ios/VideoTrim-Swift-Cxx-Bridge.cpp +0 -96
  75. package/nitrogen/generated/ios/VideoTrim-Swift-Cxx-Bridge.hpp +0 -374
  76. package/nitrogen/generated/ios/VideoTrim-Swift-Cxx-Umbrella.hpp +0 -56
  77. package/nitrogen/generated/ios/VideoTrimAutolinking.mm +0 -33
  78. package/nitrogen/generated/ios/VideoTrimAutolinking.swift +0 -25
  79. package/nitrogen/generated/ios/c++/HybridVideoTrimSpecSwift.cpp +0 -11
  80. package/nitrogen/generated/ios/c++/HybridVideoTrimSpecSwift.hpp +0 -127
  81. package/nitrogen/generated/ios/swift/EditorConfig.swift +0 -541
  82. package/nitrogen/generated/ios/swift/FileValidationResult.swift +0 -57
  83. package/nitrogen/generated/ios/swift/Func_void.swift +0 -46
  84. package/nitrogen/generated/ios/swift/Func_void_FileValidationResult.swift +0 -46
  85. package/nitrogen/generated/ios/swift/Func_void_bool.swift +0 -46
  86. package/nitrogen/generated/ios/swift/Func_void_double.swift +0 -46
  87. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +0 -46
  88. package/nitrogen/generated/ios/swift/Func_void_std__string.swift +0 -46
  89. package/nitrogen/generated/ios/swift/Func_void_std__string_std__unordered_map_std__string__std__string_.swift +0 -54
  90. package/nitrogen/generated/ios/swift/Func_void_std__vector_std__string_.swift +0 -46
  91. package/nitrogen/generated/ios/swift/HybridVideoTrimSpec.swift +0 -54
  92. package/nitrogen/generated/ios/swift/HybridVideoTrimSpec_cxx.swift +0 -241
  93. package/nitrogen/generated/ios/swift/TrimOptions.swift +0 -189
  94. package/nitrogen/generated/shared/c++/EditorConfig.hpp +0 -253
  95. package/nitrogen/generated/shared/c++/FileValidationResult.hpp +0 -77
  96. package/nitrogen/generated/shared/c++/HybridVideoTrimSpec.cpp +0 -27
  97. package/nitrogen/generated/shared/c++/HybridVideoTrimSpec.hpp +0 -80
  98. package/nitrogen/generated/shared/c++/TrimOptions.hpp +0 -125
  99. package/src/VideoTrim.nitro.ts +0 -263
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Mai Trung Duc
3
+ Copyright (c) 2025 Duc Trung Mai
4
4
  Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  of this software and associated documentation files (the "Software"), to deal
6
6
  in the Software without restriction, including without limitation the rights
package/README.md CHANGED
@@ -4,7 +4,8 @@
4
4
  * [For Expo project](#for-expo-project)
5
5
  * [Usage](#usage)
6
6
  - [Methods](#methods)
7
- * [showEditor(videoPath: string, config?: EditorConfig, onEvent?: (eventName: string, payload: Record<string, string>) => void)](#showeditorvideopath-string-config-editorconfig-onevent-eventname-string-payload-record--void)
7
+ * [showEditor(videoPath: string, config?: EditorConfig) => void)](#showeditorvideopath-string-config-editorconfig--void)
8
+ * [trim(url: string, options: TrimOptions): Promise<string>](#trimurl-string-options-trimoptions-promise)
8
9
  * [isValidFile(videoPath: string)](#isvalidfilevideopath-string)
9
10
  * [closeEditor()](#closeeditor)
10
11
  * [listFiles()](#listfiles)
@@ -13,10 +14,11 @@
13
14
  - [Callbacks (New arch)](#callbacks-new-arch)
14
15
  * [showEditor](#showeditor)
15
16
  * [closeEditor](#closeeditor-1)
16
- - [Events (Old arch)](#events-old-arch)
17
17
  - [Audio support](#audio-support)
18
18
  - [Cancel trimming](#cancel-trimming)
19
19
  - [Fail to load media](#fail-to-load-media)
20
+ - [Rotation](#rotation)
21
+ - [Use FFMPEG HTTPS version](#use-ffmpeg-https-version)
20
22
  - [Android: update SDK version](#android-update-sdk-version)
21
23
  - [Thanks](#thanks)
22
24
 
@@ -45,7 +47,7 @@
45
47
 
46
48
  ```sh
47
49
  # new arch
48
- npm install react-native-video-trim react-native-nitro-modules
50
+ npm install react-native-video-trim
49
51
 
50
52
  # old arch
51
53
  npm install react-native-video-trim@^3.0.0
@@ -53,14 +55,12 @@ npm install react-native-video-trim@^3.0.0
53
55
  # or with yarn
54
56
 
55
57
  # new arch
56
- yarn add react-native-video-trim react-native-nitro-modules
58
+ yarn add react-native-video-trim
57
59
 
58
60
  # old arch
59
61
  yarn add react-native-video-trim@^3.0.0
60
62
  ```
61
63
 
62
- > `react-native-nitro-modules` is required in New Arch as this library relies on [Nitro Modules](https://nitro.margelo.com/).
63
-
64
64
  ## For iOS (React Native CLI project)
65
65
  Run the following command to setup for iOS:
66
66
  ```
@@ -92,7 +92,7 @@ showEditor(videoUrl, {
92
92
  ```
93
93
  Usually this library will be used along with other library to select video file, Eg. [react-native-image-picker](https://github.com/react-native-image-picker/react-native-image-picker). Below is real world example:
94
94
 
95
- ```tsx
95
+ ```jsx
96
96
  import * as React from 'react';
97
97
 
98
98
  import {
@@ -102,11 +102,84 @@ import {
102
102
  TouchableOpacity,
103
103
  NativeEventEmitter,
104
104
  NativeModules,
105
+ type EventSubscription,
105
106
  } from 'react-native';
106
107
  import { isValidFile, showEditor } from 'react-native-video-trim';
107
108
  import { launchImageLibrary } from 'react-native-image-picker';
108
109
 
109
110
  export default function App() {
111
+ const listenerSubscription = useRef<Record<string, EventSubscription>>({});
112
+
113
+ useEffect(() => {
114
+ listenerSubscription.current.onLoad = NativeVideoTrim.onLoad(
115
+ ({ duration }) => console.log('onLoad', duration)
116
+ );
117
+
118
+ listenerSubscription.current.onStartTrimming =
119
+ NativeVideoTrim.onStartTrimming(() => console.log('onStartTrimming'));
120
+
121
+ listenerSubscription.current.onCancelTrimming =
122
+ NativeVideoTrim.onCancelTrimming(() => console.log('onCancelTrimming'));
123
+ listenerSubscription.current.onCancel = NativeVideoTrim.onCancel(() =>
124
+ console.log('onCancel')
125
+ );
126
+ listenerSubscription.current.onHide = NativeVideoTrim.onHide(() =>
127
+ console.log('onHide')
128
+ );
129
+ listenerSubscription.current.onShow = NativeVideoTrim.onShow(() =>
130
+ console.log('onShow')
131
+ );
132
+ listenerSubscription.current.onFinishTrimming =
133
+ NativeVideoTrim.onFinishTrimming(
134
+ ({ outputPath, startTime, endTime, duration }) =>
135
+ console.log(
136
+ 'onFinishTrimming',
137
+ `outputPath: ${outputPath}, startTime: ${startTime}, endTime: ${endTime}, duration: ${duration}`
138
+ )
139
+ );
140
+ listenerSubscription.current.onLog = NativeVideoTrim.onLog(
141
+ ({ level, message, sessionId }) =>
142
+ console.log(
143
+ 'onLog',
144
+ `level: ${level}, message: ${message}, sessionId: ${sessionId}`
145
+ )
146
+ );
147
+ listenerSubscription.current.onStatistics = NativeVideoTrim.onStatistics(
148
+ ({
149
+ sessionId,
150
+ videoFrameNumber,
151
+ videoFps,
152
+ videoQuality,
153
+ size,
154
+ time,
155
+ bitrate,
156
+ speed,
157
+ }) =>
158
+ console.log(
159
+ 'onStatistics',
160
+ `sessionId: ${sessionId}, videoFrameNumber: ${videoFrameNumber}, videoFps: ${videoFps}, videoQuality: ${videoQuality}, size: ${size}, time: ${time}, bitrate: ${bitrate}, speed: ${speed}`
161
+ )
162
+ );
163
+ listenerSubscription.current.onError = NativeVideoTrim.onError(
164
+ ({ message, errorCode }) =>
165
+ console.log('onError', `message: ${message}, errorCode: ${errorCode}`)
166
+ );
167
+
168
+ return () => {
169
+ listenerSubscription.current.onLoad?.remove();
170
+ listenerSubscription.current.onStartTrimming?.remove();
171
+ listenerSubscription.current.onCancelTrimming?.remove();
172
+ listenerSubscription.current.onCancel?.remove();
173
+ listenerSubscription.current.onHide?.remove();
174
+ listenerSubscription.current.onShow?.remove();
175
+ listenerSubscription.current.onFinishTrimming?.remove();
176
+ listenerSubscription.current.onLog?.remove();
177
+ listenerSubscription.current.onStatistics?.remove();
178
+ listenerSubscription.current.onError?.remove();
179
+ listenerSubscription.current = {};
180
+ };
181
+ });
182
+
110
183
  return (
111
184
  <View style={styles.container}>
112
185
  <TouchableOpacity
@@ -122,11 +195,7 @@ export default function App() {
122
195
 
123
196
  showEditor(result.assets![0]?.uri || '', {
124
197
  maxDuration: 20,
125
- },
126
- (eventName, payload) => {
127
- console.log('Event:', eventName, 'Payload:', payload);
128
- }
129
- );
198
+ });
130
199
  }}
131
200
  style={{ padding: 10, backgroundColor: 'red' }}
132
201
  >
@@ -159,7 +228,7 @@ const styles = StyleSheet.create({
159
228
 
160
229
  # Methods
161
230
 
162
- ## showEditor(videoPath: string, config?: EditorConfig, onEvent?: (eventName: string, payload: Record<string, string>) => void)
231
+ ## showEditor(videoPath: string, config?: EditorConfig) => void)
163
232
  Main method to show Video Editor UI.
164
233
 
165
234
  *Params*:
@@ -243,7 +312,7 @@ If you face issue when building Android app related to `file_paths`, then you ma
243
312
  </paths>
244
313
  ```
245
314
 
246
- # trim(url: string, options: TrimOptions): Promise<string>
315
+ ## trim(url: string, options: TrimOptions): Promise<string>
247
316
 
248
317
  Directly trim a file without showing editor
249
318
 
@@ -269,75 +338,15 @@ Delete a file in app storage. Return `true` if success
269
338
  ## showEditor
270
339
 
271
340
  ```ts
272
- showEditor('file', config, (eventName, payload) => {
273
- console.log(eventName, payload)
274
- })
341
+ showEditor('file', config)
275
342
  ```
276
343
 
277
344
  ## closeEditor
278
345
 
279
346
  ```ts
280
- closeEditor(() => {
281
- console.log('Editor closed')
282
- })
347
+ closeEditor()
283
348
  ```
284
349
 
285
-
286
- # Events (Old arch)
287
- To listen for events you interest, do the following:
288
- ```js
289
- useEffect(() => {
290
- const eventEmitter = new NativeEventEmitter(NativeModules.VideoTrim);
291
- const subscription = eventEmitter.addListener('VideoTrim', (event) => {
292
- switch (event.name) {
293
- case 'onLoad': {
294
- console.log('onLoadListener', event);
295
- break;
296
- }
297
- case 'onShow': {
298
- console.log('onShowListener', event);
299
- break;
300
- }
301
- case 'onHide': {
302
- console.log('onHide', event);
303
- break;
304
- }
305
- case 'onStartTrimming': {
306
- console.log('onStartTrimming', event);
307
- break;
308
- }
309
- case 'onFinishTrimming': {
310
- console.log('onFinishTrimming', event);
311
- break;
312
- }
313
- case 'onCancelTrimming': {
314
- console.log('onCancelTrimming', event);
315
- break;
316
- }
317
- case 'onCancel': {
318
- console.log('onCancel', event);
319
- break;
320
- }
321
- case 'onError': {
322
- console.log('onError', event);
323
- break;
324
- }
325
- case 'onLog': {
326
- console.log('onLog', event);
327
- break;
328
- }
329
- case 'onStatistics': {
330
- console.log('onStatistics', event);
331
- break;
332
- }
333
- }
334
- });
335
-
336
- return () => {
337
- subscription.remove();
338
- };
339
- }, []);
340
- ```
341
350
  # Audio support
342
351
  <div align="left">
343
352
  <img src="images/audio_android.jpg" width="200" />
@@ -369,6 +378,10 @@ If there's error while loading media, there'll be a prompt
369
378
 
370
379
  Related props: `alertOnFailToLoad, alertOnFailTitle, alertOnFailMessage, alertOnFailCloseText`
371
380
 
381
+ # Rotation
382
+
383
+ To trim & rotate video you can pass `enableRotation` and `rotationAngle` to `showEditor`/`trim`. But note that it doesn't re-encode the video, instead the lib uses `display_rotation` metadata from ffmpeg, and some players/platforms may show differently.
384
+
372
385
  # Use FFMPEG HTTPS version
373
386
 
374
387
  If you want to trim a remote file, you need to use `https` version (default is `min` which does not support remote file).
package/VideoTrim.podspec CHANGED
@@ -13,12 +13,12 @@ Pod::Spec.new do |s|
13
13
  s.platforms = { :ios => min_ios_version_supported }
14
14
  s.source = { :git => "https://github.com/maitrungduc1410/react-native-video-trim.git", :tag => "#{s.version}" }
15
15
 
16
- s.source_files = "ios/**/*.{h,m,mm,swift}"
16
+ s.source_files = "ios/**/*.{h,m,mm,cpp}"
17
+ s.private_header_files = "ios/**/*.h"
17
18
 
18
19
  s.dependency "ffmpeg-mobile-#{ENV['FFMPEGKIT_PACKAGE'] || 'min'}", ENV['FFMPEGKIT_PACKAGE_VERSION'] || '~> 6.0'
19
20
 
20
- load 'nitrogen/generated/ios/VideoTrim+autolinking.rb'
21
- add_nitrogen_files(s)
21
+ s.frameworks = 'AVFoundation', 'AVKit', 'UIKit', 'Photos'
22
22
 
23
23
  install_modules_dependencies(s)
24
24
  end
@@ -15,14 +15,9 @@ buildscript {
15
15
  }
16
16
  }
17
17
 
18
- def reactNativeArchitectures() {
19
- def value = rootProject.getProperties().get("reactNativeArchitectures")
20
- return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
21
- }
22
18
 
23
19
  apply plugin: "com.android.library"
24
20
  apply plugin: "kotlin-android"
25
- apply from: '../nitrogen/generated/android/videotrim+autolinking.gradle'
26
21
 
27
22
  apply plugin: "com.facebook.react"
28
23
 
@@ -39,62 +34,17 @@ def getPackageVersionOrDefault() {
39
34
  }
40
35
 
41
36
  android {
42
- namespace "com.margelo.nitro.videotrim"
37
+ namespace "com.videotrim"
43
38
 
44
39
  compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
45
40
 
46
41
  defaultConfig {
47
42
  minSdkVersion getExtOrIntegerDefault("minSdkVersion")
48
43
  targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
49
-
50
- externalNativeBuild {
51
- cmake {
52
- cppFlags "-frtti -fexceptions -Wall -fstack-protector-all"
53
- arguments "-DANDROID_STL=c++_shared"
54
- abiFilters (*reactNativeArchitectures())
55
-
56
- buildTypes {
57
- debug {
58
- cppFlags "-O1 -g"
59
- }
60
- release {
61
- cppFlags "-O2"
62
- }
63
- }
64
- }
65
- }
66
- }
67
-
68
- externalNativeBuild {
69
- cmake {
70
- path "CMakeLists.txt"
71
- }
72
- }
73
-
74
- packagingOptions {
75
- excludes = [
76
- "META-INF",
77
- "META-INF/**",
78
- "**/libc++_shared.so",
79
- "**/libfbjni.so",
80
- "**/libjsi.so",
81
- "**/libfolly_json.so",
82
- "**/libfolly_runtime.so",
83
- "**/libglog.so",
84
- "**/libhermes.so",
85
- "**/libhermes-executor-debug.so",
86
- "**/libhermes_executor.so",
87
- "**/libreactnative.so",
88
- "**/libreactnativejni.so",
89
- "**/libturbomodulejsijni.so",
90
- "**/libreact_nativemodule_core.so",
91
- "**/libjscexecutor.so"
92
- ]
93
44
  }
94
45
 
95
46
  buildFeatures {
96
47
  buildConfig true
97
- prefab true
98
48
  }
99
49
 
100
50
  buildTypes {
@@ -132,8 +82,11 @@ def kotlin_version = getExtOrDefault("kotlinVersion")
132
82
  dependencies {
133
83
  implementation "com.facebook.react:react-android"
134
84
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
135
- implementation project(":react-native-nitro-modules")
136
-
137
85
  implementation 'io.github.maitrungduc1410:ffmpeg-kit-' + getPackageNameOrDefault() +':' + getPackageVersionOrDefault()
138
86
  }
139
87
 
88
+ react {
89
+ jsRootDir = file("../src/")
90
+ libraryName = "VideoTrim"
91
+ codegenJavaPackageName = "com.videotrim"
92
+ }
@@ -4,4 +4,4 @@ VideoTrim_targetSdkVersion=34
4
4
  VideoTrim_compileSdkVersion=35
5
5
  VideoTrim_ndkVersion=27.1.12297006
6
6
  VideoTrim_ffmpeg_package=min
7
- VideoTrim_ffmpeg_version=6.0.1
7
+ VideoTrim_ffmpeg_version=6.0.1
@@ -1,6 +1,6 @@
1
1
  <manifest
2
2
  xmlns:android="http://schemas.android.com/apk/res/android"
3
- package="com.margelo.nitro.videotrim">
3
+ package="com.videotrim">
4
4
 
5
5
  <uses-permission android:name="android.permission.VIBRATE" />
6
6