安装 Docker Desktop
首先去 Docker 官网下载 macOS 版本的 Docker Desktop 版本(目前(2023/01/06)的最新版本是 4.15.0 (93002)),并安装。
安装 MySQL
通过 Docker Desktop 安装MySQL ,整个过程参考如下:
首先去 Docker 官网下载 macOS 版本的 Docker Desktop 版本(目前(2023/01/06)的最新版本是 4.15.0 (93002)),并安装。
通过 Docker Desktop 安装MySQL ,整个过程参考如下:
首先去 Docker 官网下载 macOS 版本的 Docker Desktop 版本(目前(2023/01/06)的最新版本是 4.15.0 (93002)),并安装。
|
1 2 3 4 5 6 7 8 9 10 |
$ brew install mysql # 设置管理员密码 $ mysqladmin -u root password # 手工创建数据库 $ mysql -u root -p -e "create database sonic default character set utf8 collate utf8_general_ci;" # 配置域名重定向 $ echo '127.0.0.1 host.docker.internal' | sudo tee -a /etc/hosts |
Whistle 是基于 Node 实现的跨平台抓包调试工具,其主要特点:
Android Studio 要求: 3.0以上版本 运行的真机或模拟器要求:最好8.0以上系统,低版本的手机获取不到数据。
|
1 |
$ sudo mkdir /home/data/.timemachine |
netatalk 服务和 avahi-daemon 服务。|
1 |
$ sudo apt install netatalk avahi-daemon |
netatalk 的配置文件:|
1 |
$ sudo nano /etc/netatalk/afp.conf |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[TimeCapsule] path = /home/data/.timemachine time machine = yes ; 关闭spotlight索引,这个在Centos6上是不能开的,缺依赖,7上面可以开,但是不建议,吃资源 spotlight = no ; 指定某用户有读写权限 rwlist = senra ; 强制指定用户 force user = senra ; 限制TM存储容量,单位为MB vol size limit = 100000 |
|
1 |
$ sudo service netatalk restart |
现在,你在 TimeMachine 上应该可以看到这个备份服务了,选择该备份服务就可以开始你的第一次备份了。
注意: Debian 12.5 系统上不能安装 netatalk ,原因是这个项目已经长时间没人维护了,后续建议直接使用 SMB 建立 TimeMachine 的备份服务器,参考 ubuntu 24.04使用SMB给macOS做无线Time Machine备份。
这篇文章主要讨论的是Fluter中CustomPainter中使用repaint属性实现自动paint的原理。
首先使用CustomPaint创建一个StatefulWidget,demo中根据点击位置,对蓝色的圆进行位置变换。
代码如下
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
import 'package:flutter/material.dart'; void main() => runApp(MyPaint()); class MyPaint extends StatefulWidget { const MyPaint({Key? key}) : super(key: key); @override _MyPaintState createState() => _MyPaintState(); } class _MyPaintState extends State<MyPaint> { ValueNotifier<double> _vn = ValueNotifier<double>(0); @override Widget build(BuildContext context) { return GestureDetector( onPanUpdate: parse, child: CustomPaint( painter: BoxPainter(vn: _vn), ), ); } dynamic parse(DragUpdateDetails details) { _vn.value = details.globalPosition.dy; } } class BoxPainter extends CustomPainter { ValueNotifier<double> vn; BoxPainter({@required this.vn}) : super(repaint: vn); @override void paint(Canvas canvas, Size size) { canvas.translate(size.width / 2, 0); canvas.drawCircle(Offset(0, vn.value), 66, Paint()..color = Colors.blue); } @override bool shouldRepaint(BoxPainter oldDelegate) => false; @override bool shouldRebuildSemantics(BoxPainter oldDelegate) => false; } |
flutter 升级到 3.3.9 后,代码编译报错,如下:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
$ flutter run Launching lib/main.dart on iPhone in debug mode... Automatically signing iOS for device deployment using specified development team in Xcode project: 4XS4BW9489 Running Xcode build... └─Compiling, linking and signing... 7.6s Xcode build done. 35.3s (lldb) dyld[627]: Library not loaded: @rpath/libswiftCore.dylib Referenced from: <8B0D72DF-EF41-3748-B8B5-8EF789672FF7> /private/var/containers/Bundle/Application/89C785E1-48B5-4139-8D0B-F392A3865D0B/Runner.app/Runner Reason: tried: '/private/var/containers/Bundle/Application/89C785E1-48B5-4139-8D0B-F392A3865D0B/Runner.app/Frameworks/libswiftCore.dylib' (errno=2), '/private/var/containers/Bundle/Application/89C785E1-48B5-4139-8D0B-F392A3865D0B/Runner.app/Frameworks/libswiftCore.dylib' (errno=2), '/private/preboot/Cryptexes/OS@rpath/libswiftCore.dylib' (errno=2), '/private/var/containers/Bundle/Application/89C785E1-48B5-4139-8D0B-F392A3865D0B/Runner.app/Frameworks/libswiftCore.dylib' (errno=2), '/private/var/containers/Bundle/Application/89C785E1-48B5-4139-8D0B-F392A3865D0B/Runner.app/Frameworks/libswiftCore.dylib' (errno=2), '/usr/local/lib/libswiftCore.dylib' (errno=2), '/usr/lib/libswiftCore.dylib' (errno=2, not in dyld cache) * thread #1, stop reason = signal SIGABRT frame #0: 0x00000001e6efeebc -> 0x1e6efeebc: b.lo 0x1e6efeedc 0x1e6efeec0: pacibsp 0x1e6efeec4: stp x29, x30, [sp, #-0x10]! 0x1e6efeec8: mov x29, sp Target 0: (Runner) stopped. Installing and launching... 26.6s Error launching application on iPhone. |
解决方法就是在工程的 "Build Settings->Linking->Runpath Search Paths" 加上 "/usr/lib/swift" 。
如下图:
继续阅读flutter升级到3.3.9后报错“Library not loaded: @rpath/libswiftCore.dylib”
Intel E3-1230 v3 可以成功安装, AMD Ryzen 5900 CPU 在 Linux 系统上,需要配置 CPU 模仿 Intel CPU 的特性。并且 CPU 部分,不要启用 嵌套VT-x/AMD-V 。
在 macOS (实验使用的系统是 macOS Big Sur (11.7.1))系统上,执行如下命令,生成系统安装镜像
|
1 2 3 4 5 6 7 8 9 10 11 |
$ hdiutil create -o /tmp/Monterey.cdr -size 15000m -layout SPUD -fs HFS+J $ hdiutil attach /tmp/Monterey.cdr.dmg -noverify -mountpoint /Volumes/install_build $ sudo ~/Install\ macOS\ Monterey.app/Contents/Resources/createinstallmedia --volume /Volumes/install_build $ hdiutil detach /Volumes/Install\ macOS\ Monterey $ mv /tmp/Monterey.cdr.dmg ~/Desktop/InstallSystem.dmg $ hdiutil convert ~/Desktop/InstallSystem.dmg -format UDTO -o ~/Desktop/Monterey.iso |
在今天晚上 ubuntu 22.04 执行如下升级命令之后
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ sudo apt-get dist-upgrade 正在读取软件包列表... 完成 正在分析软件包的依赖关系树... 完成 正在读取状态信息... 完成 正在计算更新... 完成 下列【新】软件包将被安装: cpp-12 gcc-12 libasan8 libgcc-12-dev libtsan2 下列软件包将被升级: apport apport-gtk dkms firmware-sof-signed libexpat1 libexpat1:i386 libexpat1-dev libflac8 libfreerdp-client2-2 libfreerdp-server2-2 libfreerdp2-2 libwinpr2-2 python3-apport python3-problem-report rsync xserver-common xserver-xephyr xserver-xorg-core xserver-xorg-legacy xwayland 升级了 20 个软件包,新安装了 5 个软件包,要卸载 0 个软件包,有 0 个软件包未被升级。 |
再次执行 flutter 的构建命令,报错。
操作过程如下:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
$ flutter run Launching lib/main.dart on Linux in debug mode... Building Linux application... /usr/include/glib-2.0/glib/glib-typeof.h:39:10: fatal error: 'type_traits' file not found /usr/include/glib-2.0/glib/glib-typeof.h:39:10: fatal error: 'type_traits' file not found Exception: Build process failed $ flutter --version Flutter 3.3.9 • channel stable • https://github.com/flutter/flutter.git Framework • revision b8f7f1f986 (2 天前) • 2022-11-23 06:43:51 +0900 Engine • revision 8f2221fbef Tools • Dart 2.18.5 • DevTools 2.15.0 $ flutter clean $ flutter run Multiple devices found: Linux (desktop) • linux • linux-x64 • Ubuntu 22.04.1 LTS 5.15.0-53-generic Chrome (web) • chrome • web-javascript • Chromium 107.0.5304.110 [1]: Linux (linux) [2]: Chrome (chrome) Please choose one (To quit, press "q/Q"): 1 Running "flutter pub get" in xxxx... 6.2s Launching lib/main.dart on Linux in debug mode... CMake Error at /usr/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake:62 (message): The C++ compiler "/usr/bin/clang++" is not able to compile a simple test program. It fails with the following output: Change Dir: /home/xxxx/xxxx/xxxxx/build/linux/x64/debug/CMakeFiles/CMakeTmp Run Build Command(s):/usr/bin/ninja cmTC_8cfda && [1/2] Building CXX object CMakeFiles/cmTC_8cfda.dir/testCXXCompiler.cxx.o [2/2] Linking CXX executable cmTC_8cfda FAILED: cmTC_8cfda : && /usr/bin/clang++ CMakeFiles/cmTC_8cfda.dir/testCXXCompiler.cxx.o -o cmTC_8cfda && : /usr/bin/ld: 找不到 -lstdc++: 没有那个文件或目录 clang: error: linker command failed with exit code 1 (use -v to see invocation) ninja: build stopped: subcommand failed. CMake will not be able to correctly generate this project. Call Stack (most recent call first): CMakeLists.txt:3 (project) Building Linux application... Exception: Unable to generate build files |
解决方法是手工安装依赖:
|
1 |
$ sudo apt install lib32stdc++-12-dev |
之后再执行构建命令。
对于 Android R(11) 使用 ContentResolver 检索图片,音乐,视频文件,参考 Android R(11) ContentResolver报错java.lang.IllegalArgumentException: Invalid token limit 里面的代码即可实现。但是如果想上传 PDF,TXT等文件的时候,则会发现系统无任何数据返回。
下面探讨一下如何解决这个问题:
首先,我们需要对Android的储存有所了解
Android储存器可分为内部储存和外部储存,这里的内部储存和外部储存不是说有两个物理储存器而是系统在硬盘上划分了两个专用目录用作内部储存和外部储存。简单来说,我们通过系统文件管理器看到的目录都属于外部储存,外部储存又可分为三类目录,私有目录、公共目录、其它目录,而内部储存对于用户是隐藏的,如数据库、SharedPreferences等文件都放在内部储存中。
|
1 2 3 4 5 6 |
//内部储存的文件目录获取方法,打印路径:/data/user/0/{应用包名}/files // Context.getFilesDir() //内部储存的缓存目录获取方法,打印路径:/data/user/0/{应用包名}/cache Context.getCacheDir() |
内部储存对应的目录为/data/user/0/{应用包名},该目录下应用有权限进行文件操作,目录对外不可见,应用删除对应的目录也会被删除。
|
1 2 3 4 5 6 |
//私有目录的文件目录获取方法,打印路径:/storage/emulated/0/Android/data/{应用包名}/files //方法参数可选,例如传入Environment.DIRECTORY_PICTURES拿到的目录为/storage/emulated/0/Android/data/com.example.android11/files/Pictures Context.getExternalFilesDir(null) //私有目录的缓存目录获取方法,打印路径:/storage/emulated/0/Android/data/{应用包名}/cache Context.getExternalCacheDir() |
私有目录获取和内部储存获取方式类似,都有file和cache目录,且该目录下应用有权限进行文件操作,目录对外可见,应用删除对应的目录也会被删除。
从Android11开始,私有目录不能被外部访问,即使获取了“所有文件管理”权限也不行(当然也是有其它方式可以实现Data目录的访问,不过目前看来并不完美)
Downloads、Documents、Pictures 、DCIM、Movies、Music、Ringtones等目录都是公共目录,Android11前可以通过文件路径直接访问,Android11后需要通过MediaStore来进行访问。
外部储存中除了私有目录和公共目录外都是其它目录,Android11后不能直接对其它目录进行访问。
Android10中已经加入了分区储存机制,不过是非强制的,适配Android10只需在AndroidManifest.xml中添加 android:requestLegacyExternalStorage="true"即可。而在Android11已经强制应用使用分区储存。
|
1 2 3 |
<!-- manifest中注册 --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" /> |
开启授权页面
|
1 2 3 4 5 |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !Environment.isExternalStorageEmulated()) { val intent = Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) startActivity(intent) } |
获取“所有文件管理”的权限可以读写除私有目录外的所有文件,但是这种权限一般为文件管理类的软件才需要申请。一般APP申请此类权限若上架Google,华为等应用市场大概率被拒。
应用如果有做文件选择上传类的功能可以使用此方式,通过启动一个系统的文件浏览页面,选择需要的文件后返回一个uri,之后将uri转成流上传或者将通过uri复制文件到私有目录再操作复制后的文件进行上传,这里切记不能直接将uri转成File去进行操作。
|
1 2 3 4 5 |
//启动SAF文件选择 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType(MimeTypeMap.getSingleton().getMimeTypeFromExtension("pdf"));//这里以打开PDF选择为例 startActivityForResult(intent, 10086); |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == 10086 && resultCode == getActivity().RESULT_OK) { if (data.getData() != null) { uriToFileApiQ(this, data.getData()) } } } //将uri对应的文件复制一份到私有目录,之后就可以操作复制后的File了 @RequiresApi(Build.VERSION_CODES.Q) public File uriToFileApiQ(Context context, Uri uri) { File file = null; if (uri == null) return file; //android10以上转换 if (uri.getScheme().equals(ContentResolver.SCHEME_FILE)) { file = new File(uri.getPath()); } else if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) { //把文件复制到沙盒目录 ContentResolver contentResolver = context.getContentResolver(); String displayName = "uritofile" + "." + MimeTypeMap.getSingleton().getExtensionFromMimeType(contentResolver.getType(uri)); InputStream is = null; try { is = contentResolver.openInputStream(uri); File cache = new File(context.getCacheDir().getAbsolutePath(), displayName); FileOutputStream fos = new FileOutputStream(cache); byte[] b = new byte[1024]; while ((is.read(b)) != -1) { fos.write(b);// 写入数据 } file = cache; fos.close(); is.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } return file; } |