mac开发-10.15检测屏幕录制权限
在Mac os 10.15之后,屏幕录制权限需要获取才能正确录屏,否则只能录制桌面背景以及自身app的影像。即可以截屏,但截不到其他app的内容。
文章目录
屏幕录制权限检测
屏幕录制授权申请
CGWindowListCreateImage
隐私页面跳转
清除某个App的权限记录
清除某个隐私权限的全部内容
遇到的问题
屏幕录制权限检测
对于Mac os 10.15的屏幕录制权限检测,使用如下方法为*佳:
1 | – (BOOL)canRecordScreen |
2 | { |
3 | if (@available(macOS 10.15, *)) { |
4 | CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID); |
5 | NSUInteger numberOfWindows = CFArrayGetCount(windowList); |
6 | NSUInteger numberOfWindowsWithName = 0; |
7 | for (int idx = 0; idx < numberOfWindows; idx++) { |
8 | NSDictionary *windowInfo = (NSDictionary *)CFArrayGetValueAtIndex(windowList, idx); |
9 | NSString *windowName = windowInfo[(id)kCGWindowName]; |
10 | if (windowName) { |
11 | numberOfWindowsWithName++; |
12 | } else { |
13 | //no kCGWindowName detected -> not enabled |
14 | break; //breaking early, numberOfWindowsWithName not increased |
15 | } |
16 | |
17 | } |
18 | CFRelease(windowList); |
19 | return numberOfWindows == numberOfWindowsWithName; |
20 | } |
21 | return YES; |
22 | } |
另外一种方法是下面这种?,在权限没有设置的时候没问题,但是在权限设置后,会导致mac os 10.15下的系统崩溃,直接回到登陆界面。所以没有使用这个
1 | – (BOOL)canRecord{ |
2 | CGDisplayStreamRef stream = CGDisplayStreamCreate(CGMainDisplayID() , 1, 1, kCVPixelFormatType_32ABGR, nil, ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef _Nullable frameSurface, CGDisplayStreamUpdateRef _Nullable updateRef) { |
3 | |
4 | }); |
5 | |
6 | BOOL canRecord = stream != NULL; |
7 | if (stream) { |
8 | CFRelease(stream); |
9 | } |
10 | |
11 | NSLog(@”canRecord : %ld”,canRecord); |
12 | return canRecord; |
13 | } |
屏幕录制授权申请
通过截屏都可以向系统获取权限
1 | – (void)showScreenRecordingPrompt{ |
2 | |
3 | /* macos 10.14 and lower do not require screen recording permission to get window titles */ |
4 | if(@available(macos 10.15, *)) { |
5 | /* |
6 | To minimize the intrusion just make a 1px image of the upper left corner |
7 | This way there is no real possibilty to access any private data |
8 | */ |
9 | CGImageRef c = CGWindowListCreateImage( |
10 | CGRectMake(0, 0, 1, 1), |
11 | kCGWindowListOptionOnScreenOnly, |
12 | kCGNullWindowID, |
13 | kCGWindowImageDefault); |
14 | |
15 | CFRelease(screenshot); |
16 | |
17 | } |
截取主屏幕全部的内容
1 | CGRect mainRect = CGDisplayBounds(CGMainDisplayID()); |
2 | CGImageRef desktopImage = CGWindowListCreateImage(mainRect, kCGWindowListOptionOnScreenOnly, kCGNullWindowID, kCGWindowImageBestResolution | kCGWindowImageShouldBeOpaque); |
3 | NSImage* image = [[NSImage alloc]initWithCGImage:desktopImage size:_screenAsBtn.frame.size]; |
4 | CGImageRelease(desktopImage); |
截取某个子程序的图片
1 | [_windowList removeAllObjects]; |
2 | CFArrayRef windowListArray = CGWindowListCreate(kCGWindowListOptionOnScreenOnly, kCGNullWindowID); |
3 | NSArray *windows = CFBridgingRelease(CGWindowListCreateDescriptionFromArray(windowListArray)); |
4 | for(NSMutableDictionary* dic in windows){ |
5 | NSString* layerStr = [dic objectForKey:(__bridge id)kCGWindowLayer]; |
6 | CGRect bounds; |
7 | CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[dic objectForKey:@”kCGWindowBounds”], &bounds); |
8 | NSRectFromCGRect(bounds); |
9 | if ([layerStr intValue] == 0 &&(bounds.size.width>10 && bounds.size.height>10)) { |
10 | [_windowList addObject:dic]; |
11 | } |
12 | } |
13 | CFRelease(windowListArray); |
14 | //下面是for循环中内容,取每张图片 |
15 | NSMutableDictionary* entry = [_windowList objectAtIndex:i]; |
16 | int ownerPID = [[entry objectForKey:(__bridge id)kCGWindowNumber] intValue]; |
17 | NSString* name =[entry objectForKey:(__bridge id)kCGWindowName]; |
18 | |
19 | NSString* owerName = [entry objectForKey:(__bridge id)kCGWindowOwnerName]; |
20 | CGImageRef imageRef = CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, ownerPID, kCGWindowImageShouldBeOpaque); |
21 | NSImage* image = [[NSImage alloc]initWithCGImage:imageRef size:NSZeroSize]; |
22 | CGImageRelease(imageRef); |
隐私页面跳转
1 | – (void)openSetting{ |
2 | NSString *urlString = @”x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture”; |
3 | [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:urlString]]; |
4 | } |
清除某个App的权限记录
使用tccutil reset All com.xxx.xxx来清除,com.xxx.xxx为bundle id
清除某个隐私权限的全部内容
重置摄像头访问: tccutil reset Camera
重置麦克风访问: tccutil reset Microphone
重置屏幕录制:tccutil reset ScreenCapture
遇到的问题
遇到权限一直要获取,获取后提示关闭该程序,进入程序后,又需要获取的死循环。
这里我重启mac就好了,不知道是10.15系统原因否。