Flutter (2.10.1~3.3.9)/Xcode 13.2.1/macOS Big Sur 11.6.4在iPad Pro iOS 15.3.1/iPhone SE 3 iOS 16.1.1真机免费调试

系统与开发环境 Flutter (2.10.1~3.3.9)/Xcode 13.2.1(13C100)/macOS Big Sur 11.6.4/iPad Pro(Model A1673) iOS 15.3.1/iPhone SE 3 iOS 16.1.1

操作步骤

1. 苹果开发网站注册或关联开发者账号,如果暂时不需要发布应用到 Mac App Store,只是在设备上调试应用,则不需要注册收费用户,只需要注册或者关联账号即可。具体可以查看官方介绍 选择会员资格

2. 在 iPad Promacbook Pro 登陆同一个注册的开发者的账号。

3. 通过 USB 数据线把 iPad Promacbook Pro 设备连接起来,如下图:

继续阅读Flutter (2.10.1~3.3.9)/Xcode 13.2.1/macOS Big Sur 11.6.4在iPad Pro iOS 15.3.1/iPhone SE 3 iOS 16.1.1真机免费调试

macOS Big Sur(11.6.2) Android Studio (version 2020.3) 执行 flutter doctor 报错

$ flutter doctor

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 1.22.5, on macOS 11.6.2 20G314 darwin-x64, locale zh-Hans-CN)
[!] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
 
[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
[!] Android Studio (version 2020.3)
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
    ✗ Unable to find bundled Java version.
[!] IntelliJ IDEA Ultimate Edition (version 2018.3.6)
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
[✓] VS Code (version 1.63.2)
[✓] Connected device (1 available)

! Doctor found issues in 3 categories.

在执行 flutter doctor --android-licenses 的时候报错:

$ flutter doctor --android-licenses

Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema
        at com.android.repository.api.SchemaModule$SchemaModuleVersion.<init>(SchemaModule.java:156)
        at com.android.repository.api.SchemaModule.<init>(SchemaModule.java:75)
        at com.android.sdklib.repository.AndroidSdkHandler.<clinit>(AndroidSdkHandler.java:81)
        at com.android.sdklib.tool.sdkmanager.SdkManagerCli.main(SdkManagerCli.java:73)
        at com.android.sdklib.tool.sdkmanager.SdkManagerCli.main(SdkManagerCli.java:48)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.annotation.XmlSchema
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
        ... 5 more                       

原因为 Java 版本太高,Flutter 1.22.5 只能使用 Java 1.8版本:

$ export JAVA_HOME=/Users/xxxx/Library/Java/JavaVirtualMachines/corretto-1.8.0_312/Contents/Home

$ flutter doctor --android-licenses

对于错误

[!] Android Studio (version 2020.3)
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
    ✗ Unable to find bundled Java version.

原因:

Plugin folder has changed in 4.1 version;
From : ~/Library/Application\ Support/AndroidStudio4.1
To: ~/Library/Application\ Support/Google/AndroidStudio4.1/plugins

Android Studio(4.1)后,安装插件的位置发生了变化,但是flutter doctor还是去原先的位置找,导致的安装过插件还报错。

解决方法:

$ ln -s ~/Library/Application\ Support/Google/AndroidStudio2020.3/plugins ~/Library/Application\ Support/AndroidStudio2020.3

更简单的方式是执行

$ flutter upgrade

升级到 flutter 2.8.1 以及之后的版本即可。

参考链接


macOS Monterey (12.0.1)解决App Store无法下载APP的问题

最近,公司的一台电脑升级到 macOS Monterey (12.0.1),之后从进行软件更新,以及 XCode 的下载安装。由于网速的限制,临时把 XCode 的下载进行了暂停操作,之后忘记恢复就进行了重启。

结果第二天在App的安装界面上就看不到被暂停的任务了。然后在 App Store 中尝试继续进行下载,发现无法进行下载任务,下载按钮点击之后,状态一闪而过,又回到待下载状态。

更换账号/重启应用/重启系统之后,无法解决问题。

应该是 App Store 内部状态混乱了,导致无法进行下载任务,需要对 App Store 进行重置操作。

网上搜索很久,才找到解决方案,执行如下命令:

$ sudo find /private/var/folders/ -iname 'com.apple.appstore' 2>/dev/null | while IFS='' read -r line; do rm -fr "$line"; done; rm -fr ~/Library/Caches/*store*; ps aux | egrep -i 'app.?store' | awk '{ print $2 }' | while IFS='' read -r line; do kill -9 "$line"; done

之后重启系统,重新点击下载应用,即可解决问题。

参考链接


OS X EI Capitan(10.11.6)报错'os/availability.h' file not found

==> Installing gradle dependency: openjdk
==> ./configure --disable-warnings-as-errors --with-boot-jdk-jvmargs=-Duser.home
==> make images
Last 15 lines from /Users/xxx/Library/Logs/Homebrew/openjdk/02.make:
In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CFBase.h:18:
/Library/Developer/CommandLineTools/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CFAvailability.h:21:10: fatal error: 'os/availability.h' file not found
#include <os/availability.h>
         ^
1 error generated.

* All command lines available in /private/tmp/openjdk-20210919-6132-1pm1i4r/jdk16u-jdk-16.0.1-ga/build/macosx-x86_64-server-release/make-support/failure-logs.
=== End of repeated output ===

No indication of failed target found.
Hint: Try searching the build log for '] Error'.
Hint: See doc/building.html#troubleshooting for assistance.

解决方案:

$ export CPATH=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/:$CPATH

$ sudo rm -rf /Library/Developer/CommandLineTools

$ xcode-select --install

参考链接


macOS Big Sur(11.4)安装指定版本Node

# 安装配置 Node Version Manager,用来管理安装使用特定版本
$ git clone https://github.com/nvm-sh/nvm.git

$ cd nvm 

$ bash install.sh

# 刷新环境变量,使得设置生效
$ source ~/.bashrc

$ nvm install 12.16.2

$ nvm use 12.16.2

参考链接


NSURLProtocol -- DNS劫持和Web资源本地化

什么是DNS劫持

DNS劫持就是通过劫持了DNS服务器,通过某些手段取得某域名的解析记录控制权,进而修改此域名的解析结果,导致对该域名的访问由原IP地址转入到修改后的指定IP,其结果就是对特定的网址不能访问或访问的是假网址,从而实现窃取资料或者破坏原有正常服务的目的。
 常见的DNS劫持现象网络运营商向网页中注入了Javascript代码,甚至直接将我们的网页请求转发到他们自己的广告页面或者通过自己的DNS服务器将用户请求的域名指向到非法地址

如何解决DNS被劫持

全站使用HTTPS协议,或者采用HttpDNS,通过HTTP向自建的DNS服务器或者安全的DNS服务器发送域名解析请求,然后根据解析结果设置客户端的Host指向,从而绕过网络运营商的DNS解析服务。

本文的解决方案

客户端对WebView的html请求进行DNS解析。优先使用阿里、腾讯、114等公共安全的DNS服务器解析客户端的所有指定域名的http请求。相对来讲我们自己的服务域名变化较少,对此我们做了一个白名单,把凡是访问包含我们公司域名的请求都必须通过白名单的解析和DNS验证。从而杜绝被劫持的情况出现,这时候NSURLProtocol就派上用场了。

NSURLProtocol

这是一个抽象类,所以在oc中只能通过继承来重写父类的方法。

@interface XRKURLProtocol : NSURLProtocol
@end

然后在AppDelegate的 application:didFinishLaunchingWithOptions: 方法或者程序首次请求网络数据之前去注册这个NSURLProtocol的子类

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
     [NSURLProtocol registerClass:[XRKURLProtocol class]];
}

注册了自定义的urlProtocol子类后,之后每一个http请求都会先经过该类过滤并且通过+canInitWithRequest:这个方法返回一个布尔值告诉系统该请求是否需要处理,返回Yes才能进行后续处理。

+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
    if ([NSURLProtocol propertyForKey:URLProtocolHandledKey inRequest:request]) {
        return NO;
    }

    //http和https都会出现dns劫持情况,都需要处理
    NSString *scheme = [[request URL] scheme];
    if (([scheme caseInsensitiveCompare:@"http"] == NSOrderedSame)) {
        // 判断请求是否为白名单
        NSArray *whiteLists = [XRKConfigManager sharedManager].whiteList;
        if (whiteLists && [whiteLists isKindOfClass:[NSArray class]]) {
            for (NSString *url in whiteLists) {
                if (request.URL.host && [request.URL.host hasSuffix:url]) {
                    return YES;
                }
            }
        }
    }

    return NO;
}

+canonicalRequestForRequest:这个父类的抽象方法子类必须实现。

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
    return request;
}

以下是官方对这个方法的解释。当我们想对某个请求添加请求头或者返回新的请求时,可以在这个方法里自定义然后返回,一般情况下直接返回参数里的NSURLRequest实例即可。

It is up to each concrete protocol implementation to define what “canonical” means. A protocol should guarantee that the same input request always yields the same canonical form.

+requestIsCacheEquivalent:toRquest:这个方法能够判断当拦截URL相同时是否使用缓存数据,以下例子是直接返回父类实现。

+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b {
    return [super requestIsCacheEquivalent:a toRequest:b];
}

-startLoading-stopLoading两个方法分别告诉NSURLProtocol实现开始和取消请求的处理。

- (void)startLoading {
    NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];

    //打标签,防止无限循环
    [NSURLProtocol setProperty:@YES forKey:URLProtocolHandledKey inRequest:mutableReqeust];
    // dns解析
    NSMutableURLRequest *request = [self.class replaceHostInRequset:mutableReqeust];
    self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
}

+ (NSMutableURLRequest *)replaceHostInRequset:(NSMutableURLRequest *)request {
    if ([request.URL host].length == 0) {
        return request;
    }

    NSString *originUrlString = [request.URL absoluteString];
    NSString *originHostString = [request.URL host];
    NSRange hostRange = [originUrlString rangeOfString:originHostString];
    if (hostRange.location == NSNotFound) {
        return request;
    }

    //用HappyDNS 替换host
    NSMutableArray *array = [NSMutableArray array];
    /// 第一dns解析为114,第二解析才是系统dns
    [array addObject:[[QNResolver alloc] initWithAddress:@"114.114.115.115"]];
    [array addObject:[QNResolver systemResolver]];
    QNDnsManager *dnsManager = [[QNDnsManager alloc] init:array networkInfo:[QNNetworkInfo normal]];
    NSArray *queryArray = [dnsManager query:originHostString];
    if (queryArray && queryArray.count > 0) {
        NSString *ip = queryArray[0];
        if (ip && ip.length) {
            // 替换host
            NSString *urlString = [originUrlString stringByReplacingCharactersInRange:hostRange withString:ip];
            NSURL *url = [NSURL URLWithString:urlString];
            request.URL = url;

            [request setValue:originHostString forHTTPHeaderField:@"Host"];
        }
    }

    return request;
}
- (void)stopLoading {
    [self.connection cancel];
}

由于我们在-startLoading中新建了一个NSURLConnection实例,因此要实现NSURLConnectionDelegate的委托方法。

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [self.client URLProtocol:self didLoadData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    [self.client URLProtocolDidFinishLoading:self];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    [self.client URLProtocol:self didFailWithError:error];
}

至此,通过NSURLProtocol和QNDnsManager(七牛DNS解析开源库)可以解决DNS劫持问题。但是NSURLProtocol还有更多的用途,以下是本文第二个内容:webView上web请求的资源本地化。

Web资源本地化

这里只举一个简单的示例,同样是在上述NSURLProtocol的子类的-startLoading方法里

- (void)startLoading {
    NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];
    // 处理MIME type
    NSString *mimeType = nil;
    mutableReqeust = [self.class replaceLocalSource:mutableReqeust];
    NSString *pathComponent = mutableReqeust.URL.absoluteString.lastPathComponent;
    if ([pathComponent hasSuffix:@"js"]) {
        mimeType = @"text/javascript";
    } else if ([pathComponent hasSuffix:@"css"]) {
        mimeType = @"text/css";
    }
    
    if (mimeType) {
        NSData *data = [NSData dataWithContentsOfFile:mutableReqeust.URL.absoluteString];
        
        NSURLResponse *response = [[NSURLResponse alloc] initWithURL:[[self request] URL]
                                                            MIMEType:mimeType
                                               expectedContentLength:[data length]
                                                    textEncodingName:@"UTF8"];
        [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
        [[self client] URLProtocol:self didLoadData:data];
        [[self client] URLProtocolDidFinishLoading:self];
    }
}
#pragma mark - 判断是否是本地资源
+ (BOOL)canReplaceLocalSource:(NSURLRequest *)request {
    NSString *absoluteString = request.URL.absoluteString;
    for (NSString *localSourceurl in [self localSourceArray]) {
        if ([absoluteString isEqualToString:localSourceurl]) {
            return YES;
        }
    }
    return NO;
}

继续阅读NSURLProtocol -- DNS劫持和Web资源本地化

OS X EI Capitan curl: (22) The requested URL returned error: 403 [[[!!! BREAKING CHANGE !!!]]] Support for clients that do not support Server Name Indication is temporarily disabled and will be permanently deprecated soon.

最近在OS X EI Capitan系统上执行升级工作的时候,发生错误,内容如下:

$  brew upgrade cmake
==> Upgrading 1 outdated package:
cmake 3.17.3 -> 3.20.3
==> Upgrading cmake 3.17.3 -> 3.20.3 
==> Downloading https://www.bytereef.org/contrib/decimal.diff
Already downloaded: /Users/longsky/Library/Caches/Homebrew/downloads/f60b5004541eb3c87cce87ef3bf94933a2684ab267346afdc45ae1622ffa923a--decimal.diff
==> Downloading https://files.pythonhosted.org/packages/f6/e9/19af16328705915233299f6f1f02db95899fb00c75ac9da4757aa1e5d1de/setuptools-56.0.0.t

curl: (22) The requested URL returned error: 403 [[[!!! BREAKING CHANGE !!!]]] Support for clients that do not support Server Name Indication is temporarily disabled and will be permanently deprecated soon. See https://status.python.org/incidents/hzmjhqsdjqgb and ht
Error: Failed to download resource "python@3.9--setuptools"
Download failed: https://files.pythonhosted.org/packages/f6/e9/19af16328705915233299f6f1f02db95899fb00c75ac9da4757aa1e5d1de/setuptools-56.0.0.tar.gz

排查了很久,发现是以前为了修复 解决macOS系统curl报告https证书不正确(curl: (60) SSL certificate problem: Invalid certificate chain)问题而配置了curl忽略安全配置信息导致的,如下:

$ cat .curlrc 
--insecure

移除这个配置项目即可解决问题。

参考链接


禁止macOS系统产生.DS_Store文件的方法

Mac经常会产生 .DS_Store 的隐藏文件,虽然在 Mac 上看不到,但是有时用了人家的 U 盘或把 U 盘拿到 Windows 系统上用,就会看到。

.DS_StoreMac OS 保存文件夹的自定义属性的隐藏文件,如文件的图标位置或背景色,相当于Windowsdesktop.ini

  • 禁止 .DS_Store 生成:
    打开 “终端” ,复制黏贴下面的命令,回车执行,重启Mac即可生效。

    $ defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool TRUE
  • 恢复 .DS_Store 生成:
    $ defaults delete com.apple.desktopservices DSDontWriteNetworkStores

参考链接


解决GitHub的raw.githubusercontent.com无法连接问题

https://site.ip138.com/raw.Githubusercontent.com/

输入raw.githubusercontent.com

查询IP地址

修改hosts Ubuntu,CentOS及macOS直接在终端输入

$ sudo vi /etc/hosts

添加以下内容保存即可 (IP地址查询后相应修改,可以ping不同IP的延时 选择最佳IP地址

# GitHub Start
52.74.223.119 github.com
192.30.253.119 gist.github.com
54.169.195.247 api.github.com
185.199.111.153 assets-cdn.github.com
199.232.96.133 raw.githubusercontent.com
#151.101.76.133 raw.githubusercontent.com
151.101.108.133 user-images.githubusercontent.com
151.101.76.133 gist.githubusercontent.com
151.101.76.133 cloud.githubusercontent.com
151.101.76.133 camo.githubusercontent.com
151.101.76.133 avatars0.githubusercontent.com
151.101.76.133 avatars1.githubusercontent.com
151.101.76.133 avatars2.githubusercontent.com
151.101.76.133 avatars3.githubusercontent.com
151.101.76.133 avatars4.githubusercontent.com
151.101.76.133 avatars5.githubusercontent.com
151.101.76.133 avatars6.githubusercontent.com
151.101.76.133 avatars7.githubusercontent.com
151.101.76.133 avatars8.githubusercontent.com
# GitHub End

参考链接


Error: Your CLT does not support macOS 11.0.

最近系统升级到macOS Big Sur(11.0.1)之后,系统报告如下错误:

$ brew upgrade

...........................................

==> Upgrading 5 outdated packages:
tomcat 9.0.39 -> 9.0.40
gradle 6.7 -> 6.7.1
opencv 4.5.0_3 -> 4.5.0_4
vtk 9.0.1_1 -> 9.0.1_2
imagemagick 7.0.10-38 -> 7.0.10-39
==> Upgrading tomcat 9.0.39 -> 9.0.40 
==> Downloading https://www.apache.org/dyn/closer.lua?path=tomcat/tomcat-9/v9.0.
==> Downloading from https://mirror.bit.edu.cn/apache/tomcat/tomcat-9/v9.0.40/bi
######################################################################## 100.0%
Error: Your CLT does not support macOS 11.0.
It is either outdated or was modified.
Please update your CLT or delete it if no updates are available.
Error: An exception occurred within a child process:
  SystemExit: exit

解决方案如下:

$ sudo rm -rf /Library/Developer/CommandLineTools

$ sudo xcode-select --install

参考链接