用Flutter写了个博客园APP
最近在摸鱼时看到了一些博客园API文章,就想着摸鱼时写个APP练练手。
现阶段实现了以下功能模块:
- 博客浏览、评论
- 新闻浏览
- 闪存浏览、发布、评论
- 博问浏览
- 用户登录
博问暂时只支持浏览,不支持回答提问等操作。
支持iOS、Android平台。
截图
浅色模式:
深色模式:
API
开发前需要先到https://api.cnblogs.com/申请API KEY,申请通过才能使用博客园的API。
输入一下个人信息跟应用信息,提交后等待博客园的审核。通过审核后会收到一封包含ClientId和ClientSecret的邮件。
博客园API文档上的API不全,有些API需要到Github中查询。
开发
API申请完成就可以愉快的进行开发了。
Flutter版本这次选择了最新的3.3,基于GetX框架+Dio来开发,不得不说GetX一把梭的感觉是真的爽。
目录结构跟GetX框架差不多,按我自己的习惯进行了一些改动:
app
一些通用的类及样式services
提供数据存储等服务requests
请求的封装generated
生成的国际化文件,使用get generate locales
生成modules
模块,每个会有两个文件,view及controllerwidgets
自定义的小组件routes
路由定义models
实体类
个人练手项目就加上了一些以前没用过包跟特性体验一下(如lottie、getx国际化)。
这个项目比较简单,技术上没什么好说的,主要说下博文的展示:
博文展示
博文由于是HTML富文本且有一些复杂样式,把文章内容转为Flutter Widget显示的体验挺差,所以还是使用WebView来展示。
在这里我选择了flutter_inappwebview
包,这个包会比官方的webview_flutter
功能更加丰富,更新也更频繁。
HTML加载流程如下:
- 在assets中添加HTML,预留内容、js、css槽位
- 在assets中添加两个css样式,分别对应浅色模式及深色模式;css内容可以从任意文章的Web页面抓取
- 在assets中添加JS,编写WebView与APP的交互
- 在assets中添加highlight.js,实现代码的高亮
- 将js、css填充至HTML,css需要根据APP主题选择
- 通过API读取博文内容,并填充到HTML中
- 通过
webViewController.loadData(data: html)
在APP中显示博文
具体实现可以看源代码。实现效果:
由于项目依赖WebView(文章、登录),所以只支持iOS、Android平台。要支持其他平台也不难,只需要把文章内容转为Flutter Widget显示再更改下登录逻辑即可。
自动打包
使用Github Actions可以很简单的自动完成打包发布的步骤。
关于Github Actions的介绍,可以看下官方文档。
在项目创建根目录创建一个.github/workflows,然后创建一个xxxx.yml,写入以下代码。
name: app-build-action
#推送Tag时触发
on:
push:
tags:
- "*"
jobs:
build-ios-android:
# 使用macOS镜像,如果不需要打包iOS,可以替换成Ubuntu
runs-on: macos-latest
permissions:
contents: write
steps:
#签出代码
- uses: actions/checkout@v2
with:
ref: master
#写出ENV文件
- name: Create .env
run: |
echo "CLIENT_ID=${{ secrets.CLIENT_ID }}" > .env
echo "CLIENT_SECRET=${{ secrets.CLIENT_SECRET }}" >> .env
#APK签名设置
- name: Download Android keystore
id: android_keystore
uses: timheuer/base64-to-file@v1.2
with:
fileName: keystore.jks
encodedString: ${{ secrets.KEYSTORE_BASE64 }}
- name: Create key.properties
run: |
echo "storeFile=${{ steps.android_keystore.outputs.filePath }}" > android/key.properties
echo "storePassword=${{ secrets.STORE_PASSWORD }}" >> android/key.properties
echo "keyPassword=${{ secrets.KEY_PASSWORD }}" >> android/key.properties
echo "keyAlias=${{ secrets.KEY_ALIAS }}" >> android/key.properties
#设置JAVA环境
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: "12.x"
cache: 'gradle'
#设置Flutter
- name: Flutter action
uses: subosito/flutter-action@v2
with:
flutter-version: '3.3.9'
cache: true
- name: Restore packages
run: flutter pub get
#打包APK
- name: Build APK
run: flutter build apk --release
#上传APK至Artifacts
- name: Upload APK to Artifacts
uses: actions/upload-artifact@v3
with:
name: app-release.apk
path: |
build/app/outputs/flutter-apk/app-release.apk
#打包iOS
- name: Build IPA
run: flutter build ios --release --no-codesign
#创建未签名ipa
- name: Create IPA
run: |
mkdir build/ios/iphoneos/Payload
cp -R build/ios/iphoneos/Runner.app build/ios/iphoneos/Payload/Runner.app
cd build/ios/iphoneos/
zip -q -r ios_no_sign.ipa Payload
cd ../../..
#上传IPA至Artifacts
- name: Upload IPA to Artifacts
uses: actions/upload-artifact@v3
with:
name: ios_no_sign.ipa
path: |
build/ios/iphoneos/ios_no_sign.ipa
#从document/new_version.json读取版本信息
- name: Read version
id: version
uses: juliangruber/read-file-action@v1
with:
path: document/new_version.json
- name: Echo version
run: echo "${{ fromJson(steps.version.outputs.content).version }}"
- name: Echo version content
run: echo "${{ fromJson(steps.version.outputs.content).version_desc }}"
#发布至Github Release
- name: Upload Release
uses: ncipollo/release-action@v1
with:
allowUpdates: true
artifactErrorsFailBuild: true
artifacts: "build/app/outputs/flutter-apk/app-release.apk,build/ios/iphoneos/ios_no_sign.ipa"
name: "${{ fromJson(steps.version.outputs.content).version }}"
body: "${{ fromJson(steps.version.outputs.content).version_desc }}"
token: ${{ secrets.TOKEN }}
#完成
- run: echo "🍏 This job's status is ${{ job.status }}."
运行脚本前,需要先到Github项目设置-Secrets-Actions中添加以下字段
CLIENT_ID
博客园API ClientId
CLIENT_SECRET
博客园API ClientSecret
KEYSTORE_BASE64
APK签名文件,转为BASE64
KEY_ALIAS
APK签名keyAlias
KEY_PASSWORD
APK签名keyPassword
STORE_PASSWORD
APK签名storePassword
TOKEN
Github Token
Github Token点这里添加,注意需要权限的设置。
设置完成后,当想要打包一个新版本时,只需要提交代码并打上Tag推送至Github,即可自动打包。
总结
这个项目没啥难度且博客园API文档还是比较全面,基本对着API做个UI就行了。
天冷变懒了,有些功能还没有写完,过段时间再慢慢完善了。
项目开源地址:https://github.com/xiaoyaocz/flutter_cnblogs,有兴趣可以到Release中下载安装包体验一下。