中山本地网站建设推广企业,天天向上网站建设,网络推广计划,网站建设费交文化事业大家好#xff0c;我是 17。
为什么要写这篇文章呢#xff1f;对于一没有 android 开发经验#xff0c;从未有过打包经历的新人来说#xff0c;要想成功打包#xff0c;是很困难的。因为受到的阻碍太多#xff0c;是完全陌生的领域#xff0c;几乎是寸步难行。如果有老… 大家好我是 17。
为什么要写这篇文章呢对于一没有 android 开发经验从未有过打包经历的新人来说要想成功打包是很困难的。因为受到的阻碍太多是完全陌生的领域几乎是寸步难行。如果有老人带还行如果没有那就只能自己四处找人或搜索资料求指导了。可惜的是网上的文章不是过时了就是不全或是讲的不够明白要几经坎坷才能成功。但是只要成功打包一次回头再看其实也是满简单的嘛所缺少的只是一份完整的资料而已。
为了能让首次打包 android 的小伙伴不必再经历四处碰壁的磨难17 决定写这篇文章从此 android 打包不求人。虽然已经很详细但还是不可能面面俱到保证能发包。有的地方只是点到为止。
操作系统 Mac OS
Flutter 版本 3.7.5android SDK 33
在打包之前首先检查 pubspec.yaml 中的依赖删除没有用到的依赖减少包的大小。如果需要网络权限需要在 android/app/src/main/AndroidManifest.xml 中添加网络权限申请。 ...uses-permission android:nameandroid.permission.INTERNET /uses-permission android:nameandroid.permission.ACCESS_NETWORK_STATE /
/manifest权限 INTERNET 允许网络连接。
权限 ACCESS_NETWORK_STATE 允许程序获取网络信息状态。如果用不到这条权限可以不申请。
如果要用 http 但是需要在 AndroidManifest.xml 的 applictation 加如下配置 android:usesCleartextTraffictrue
下面详细说下打包的主要过程。
设置应用 ID 和包名
在建项目的时候可以直接设置应用 ID 和包名。
–org 指定 applicationId 的前缀默认为 com.example”我们指定为 com.iam17项目名为 app17。 flutter create --orgcom.iam17 app17创建成功后项目的应用 ID(applicationId 是 com.iam17.app17。包名package) 也是 com.iam17.app17
默认情况下项目的软件包名称与应用 ID 是一样的。
如果开始无法确定 org到发版的时候才确定怎么办。 对于新手来说与其做修改不如直接新建项目把 lib 下面的文件 copy 过来并对 android 下面的内容做相应修改这样肯定效率更高也不容易出错。
应用 ID 和包名的区别
你一定会很奇怪既然他们两个一样为什么不用一个
他们两个一个主外一个主内。
应用 ID 主外是 android app 的身份证全球唯一。一般是把域名倒过来加上你的 app 的名字。
包名主内包名是 app 代码需要的。 它将此名称用作应用生成的 R.java 类的命名空间。 示例对于上面创建的项目R 类将为 com.iam17.app17.R。 它会使用此名称解析清单文件中声明的任何相关类名。
一个应用使用一个包名但可以使用不同的应用 ID 发布为多个不同的应用在应用市场上可以共存这就是为什么要把应用 ID 和 包名分开的原因。
应用 ID 的位置
应用 ID 在gradle在 android/app/build.gradle 的 defaultConfig 中设置新版本的 flutter 在新建项目的时候已经自动设置好了。
android {defaultConfig {applicationId com.iam17.app17...如果没有设置 applicationId为了与以前的 SDK 工具兼容构建工具会将 AndroidManifest.xml 文件中的包名称用作应用 ID。在这种情况下重构您的软件包名称也会更改您的应用 ID。
包名的位置
AndroidManifest.xml 文件中的 package 属性就是包名。
?xml version1.0 encodingutf-8?
manifest xmlns:androidhttp://schemas.android.com/apk/res/androidpackagecom.iam17.app17...package 轻易不要修改修改起来比较麻烦。不是光修改这一个地方就完事了还要调整目录结构修改文件中的代码。 包名和应用 ID 的位置了解一下即可一般不需要我们手动去修改。 修改版本号
打开 pubspec.yaml 找到 version: 1.0.01。
可能有的小伙伴对版本号不知道为什么用 3 位我来解释一下。
一般来讲大部分的软件版本号 分 3 段比如 A.B.C
A 表示大版本号一般当软件整体重写或出现不向后兼容的改变时增加A。
一般来说第一版发布的时候是 1.0.0。
B 表示功能更新出现新功能时增加B。
比如原来没有点赞功能增加点赞功能的版本可以是 1.1.0。
有的时候软件还在快速迭代中很容易出现向前不能兼容的情况这个时候也可以直接用 B 来代替 A 的作用。比如发第一版的时候用 0.1.0。等稳定后再发 1.0.0 版本。一般来说 A 是不应该经常变动的。
C 表示小修改如修复bug只要有修改就增加C
C 的更新可以不经测试直接更新。如果功能要修改也必须要兼容以前的版本也就是说接口是不能修改的只能修改逻辑实现。
还有后面的 1 是怎么回事 号可以看做是分隔符。1 是累计版本从 1 开始只能增加不能减小并且每次发版必须增加。这个版本号是给内部用的。比如苹果商店android 平台都用这个版本号来判断软件的新旧。3 位版本号是给用户看的。3 位版本号包含软件更新的信息让人一看就知道是重大更新还是功能增加还是 bug 修复。
消除 build.gradle 中的错误提示
打开 android/app/build.gradle 后你可能会发现有一个错误提示unable to resolve class GradleException。 新建的项目可能也有这个问题虽然不影响编译但是有这个错误在总是心里不舒服。我们可以把 GradleException 换成 FileNotFoundException 错误提示就消失了。
设置 sdk 版本
在 android 下面有三个版本相关的配置 compileSdkVersionminSdkVersiontargetSdkVersion需要我们关注一下。
compileSdkVersion 告诉 gradle 用哪个 Android SDK 版本编译你的应用。compileSdkVersion 决定了你可以用哪个版本的 api。比如你的 compileSdkVersion 是 31如果你在代码中用了 33 的 api编译会报错。一般我们都把 compileSdkVersion 设置为最高版本。minSdkVersion 是应用可以运行的最低版本要求。也就是你要向下兼容哪些版本。根据 app 的用户特点尽量设得高一些否则很多插件不能用。targetSdkVersion 告诉 android 系统app 要在哪个版本运行。android 的 api 在不同版本之间虽然接口没有变化但内部的行为可能发生了变化。当你指定了 targetSdkVersion 后一定要在这个版本做完整的测试。新开项目 targetSdkVersion 应该和 compileSdkVersion 保持一致。支持新近的 API 级别有助于让您的应用利用平台的最新功能为用户提供愉悦的体验。
说了半天你可能最想知道到底写什么既然是新手第一次发包那项目应该是新的。推荐这样设置。
compileSdkVersion 33
minSdkVersion 23
targetSdkVersion 3333 是当前 Android SDK 最新版本如果你本机没有安装 SDK 33需要先安装。 具体要如何修改呢两个方案
修改 flutter安装目录/packages/flutter_tools/gradle/flutter.gradle
class FlutterExtension {static int compileSdkVersion 33static int minSdkVersion 16static int targetSdkVersion 33...默认的 minSdkVersion 竟然是 16一定得修改这个确实太低了。注意在这里修改会影响到所有项目。
修改项目中的 android/app/build.gradle 比如修改 minSdkVersion把变量换成常就行 defaultConfig {applicationId com.iam17.app17minSdkVersion flutter.minSdkVersion...修改为 defaultConfig {applicationId com.iam17.app17minSdkVersion 23...
另外两个已经是最新了就不用修改了。如果需要修改修改为 33 就行。虽然有两种方案但 17 推荐第 2 种直接在项目中修改。
添加 launcher icon
launcher icon 就是下面图中的这些小方块。 如果要手动设置 launcher icon 还是很麻烦的。幸运的是这个问题被一个叫 flutter_launcher_icons 的插件解决了。所以原来那个超级麻烦的问题现在就转变为学会使用这个插件就行了。
安装 flutter_launcher_icons 插件 flutter pub add dev:flutter_launcher_icons注意前面的 dev: 表示作为开发期间的依赖flutter_launcher_icons 会出现在 dev_dependencies 下面。出现在这里的好处是等发版的时候 flutter_launcher_icons 不会被包括里 apk 中。 准备一张 1024x1024 的图片。如果你手边没有合适的17 亲手画了一张可以 点击这里打开原图右键另存下载。在根目录下建一个文件夹 images把图片命名为 icon1024.png 放入 images 文件夹中。 添加配置信息打开 pubspec.yaml
flutter_icons:image_path: images/icon1024.pngandroid: true ios: true 执行创建命令
flutter pub run flutter_launcher_icons:main检查生成的图片
打开 android/app/src/main/res/drawable 文件夹查看已经生成好的图片发现所有图片都已经自动生成好了。
为 ios 生成的图片路径 在 ios/Runner/Assets.xcassets/AppIcon.appiconset
注意事项
Format: 32-bit PNGicon 大小必须是 1024x1024确保在 40px 大小时也能清晰可见这是 icon 最小的尺寸。icon 不能大于 1024KBicon 不能是透明的。必须是正方形不能有圆角。
icon 的边可能会被切掉因为 Icon 最后展示的可能不是正方形所以一般边上需要留白。
设置 App Name
App Name 就是 App 安装成功后在图标下面显示的名字。
打开 flutter根目录/android/app/src/main/AndroidManifest.xml
applicationandroid:labelApp Name //在这修改 Android App Name。设置 Splash Screen
虽然可以手动设置但对于新手来说用 flutter_native_splash 这个插件会更方便一些。 安装
flutter pub add flutter_native_splash在项目根目录下找到文件夹 images把 splash.png 放入其中。
在 pubspec.yaml 的末尾加上配置
flutter_native_splash:color: #42a5f5image: images/splash.png执行创建命令
flutter pub run flutter_native_splash:create运行第一时间就会看到启动画面了。splash.png 会居中显示。
说明
splash.png 要准备 4x 的。插件会自动为我们生成小分辨率的每次修改配置都得重新执行 flutter pub run flutter_native_splash:create不光是配置了 android 的启动页面iosweb 的也一起生成好了。
有一个小福利。默认情况下当 flutter 开始绘制的时候 Splash Screen 就自动消失了。但这个时候首屏的数据可能还没有准备好还无法显示画面我们可能还得准备一个 loading 的画面。现在你可以继续显示 Splash Screen直到首屏数据准备完毕。
代码很好写的。我们用 Timer 来模拟数据准备。
void main() {WidgetsBinding widgetsBinding WidgetsFlutterBinding.ensureInitialized();FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);runApp(const MyApp());Timer(Duration(seconds: 10), () {FlutterNativeSplash.remove();});
}如果你哪天想自己配置可以恢复到默认状态
flutter pub run flutter_native_splash:remove现在的启动页面只有一张图片但一般在启动页面的底部还会有一个 品牌 logo。你可以把 logo 合并在主图上但这样就无法保证 logo 出现在底部的位置。所以 logo 需要单独用一张图片。
在 pubspec.yaml 中增加 branding 的配置。
flutter_native_splash:color: #42a5f5image: images/splash.pngbranding: images/logo.png 重新执行 flutter pub run flutter_native_splash:create 就可以看到 logo 了。如果你觉得 logo 太靠下了可以把 logo 的图片下面留点空白。
签名
要想把 app 发布到商店必须要对 app 进行签名。签名有两种方式命令式和交互式。命令式对新手不大友好我用交互的方式来说明。
在 IDE 中运行或调试项目时AS 会自动使用 Android SDK 工具生成的调试证书为我们的应用签名路径为 $HOME/.android/debug.keystore但是应用商店可不接受使用调试证书发布的应用签名。为了给应用签名需要先创建密钥。
创建密钥
打开 Android Studio 找到 Build 菜单下面的 Generated Signed Bundle/APK 会弹出下面这个对话框 有两个选项
Android App Bundle 如果你要上传到 google 商店选这个。你暂可以理解为 这是 APK 优化方案可惜不是所有的商店都支持。APK 就是传统的打包为了兼容所有商痁我们选这个就好了。
接下来又会弹窗 Key store path 是你要将 key 保存在哪里可以先找个地方放后面可以 copy 到其它地方。应在位置路径末尾添加一个扩展名为 .jks 的文件名。点击 Create new 新建一个比如文件名可以叫 key17.jks。
key store passowrd 为您的密钥库创建并确认一个安全的密码。设置好了必须要记住。
Alias为您的密钥输入一个标识名。 比如可以叫 key17。Password为您的密钥创建并确认一个安全的密码。它应该与密钥库密码相同。具体原因就不用管了把它设成和 key store passowrd 一样就没问题了。密码要求至少 6 位。Validity (years) 以年为单位设置密钥的有效时长。密钥的有效期应至少为 25 年以便您可以在应用的整个生命期内使用同一密钥为应用更新签名。我直接写 100 年让它没有过期的可能。
Certificate 为证书输入一些关于您本人的信息。此信息不会显示在应用中但会作为 APK 的一部分包含在您的证书中。只有第一项是必须填的其它的空着就行。当然了如果写全了更好。 选中 release点下面的按钮 create。然后签名文件就生成好了。
使用密钥为应用自动签名
先把创建好的 key 文件 copy 到 android 目录下。
建立 keystore.properties 文件
在 android 文件夹下建立名为 keystore.properties 文件不叫这个名也可以但一般都这么叫没有特别的原因还是用这个名字为好。在文件里放如下内容
storePassword123456
keyPassword123456
keyAliaskey17
storeFile../key17.jks注意这里的 keyAlias 要和前面设置的 key alias 保持一致否则找不到 key。密码当然也要一样。 添加 gradle 配置
在 build.gradle 文件中按如下方式加载 keystore.properties 文件必须在 android 代码块前面
def keystorePropertiesFile rootProject.file(keystore.properties)
def keystoreProperties new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))android {...
}
输入存储在 keystoreProperties 对象中的签名信息
android {signingConfigs {release {keyAlias keystoreProperties[keyAlias]keyPassword keystoreProperties[keyPassword]storeFile file(keystoreProperties[storeFile])storePassword keystoreProperties[storePassword]}}buildTypes {release {signingConfig signingConfigs.release}}...
}
...多渠道统计
apk 会发到不同的商店你可能想知道哪个商店的下载量最大。这就需要渠道统计这个功能要用到 dart 参数。
--dart-define 来指定不同的 dart 参数比如
flutter build apk --dart-define channelhuawei在 dart 代码里可以通过 String.fromEnvironment 获取到对应的自定义配置参数。
const channel String.fromEnvironment(channel);dart 代码拿到 channel 后就可以发统计数据出来。
发布优化
启用缩减、混淆处理和优化功能
android {buildTypes {release {minifyEnabled trueshrinkResources trueproguardFiles getDefaultProguardFile(proguard-android.txt), proguard-rules.pro}}...
}发布和安装
现在执行发布命令 flutter build apk --release--release 可以省略是默认值。
不出意外的话build 成功可以看到类似如下信息 Built build/app/outputs/flutter-apk/app-release.apk (37.6MB)apk 已经生成了怎么装到手机上呢三种方法。
通过网络把 apk 发到手机上。比如有的包就是通过一个 http 链接发布的下载后可以直接安装。通过 adb 命令安装
adb install build/app/outputs/flutter-apk/app-release.apk通过 flutter install 命令安装
优化
虽然做为新手能打包成功就已经满心欢喜了但还可以做的更好。
apk 大小优化
不同的 Android 设备使用不同的 CPU而不同的 CPU 支持不同的指令集。CPU 与指令集的每种组合都有专属的应用二进制接口 (ABI)。ABI 目前有两大类 arm 和 x86。arm 是当前手机的主流x86 出现在模拟器上。flutter 默认支持 arm 和 x86 两种 ABI。我们用 android studio 查看一下。把刚才生成的 apk 直接拖到 android studio 上就行。查看 lib 文件夹发现 flutter 为我们生成了三种 ABI 的文件。 一种手机只用一种 ABI所以把它们分别打包会更好些体积会大大减小。只需要加一个参数就好 。
flutter build apk --split-per-abi再看输出目录原来的一个 apk 包现在分成三个了每个只有原来 apk 1/3 大小。 ABI 的更多信息见 这里 到此基本的打包流程就讲完了可以发布了。恭喜你完成了从 0 到 1 的跨越
如果你的产品只发布为一个版本下面的内容可以先跳过。虽然有开发环境测试环境也需要打不同的包因为差异不大可以用简单的办法解决。比如用 --dart-define 设置变量。
用 applicationIdSuffix 为开发版设置不同的 applicationId。
buildTypes{...debug {applicationIdSuffix .debugdebuggable true}
}多版本打包
可能你的产品还需要根据不同的用户出不同的版本比如免费版本收费版。
多版本要面临的问题主要有三个
如何让多版本共存。如何做个性化设置优化打包。你可以在所有版本中把所有的功能都加上简单的用开启关闭来控制。但这样会导致 apk 过大也不大安全。
如果都手动配置学习成本有点高对于新手来说可以我们可以用 flutter_flavorizr 这个插件帮我们处理好许多事情让我们有一个好的起点。
安装
flutter pub add dev:flutter_flavorizr如果你这样执行安装命令的是话会报错原因是和前面的插件 flutter_launcher_iconsflutter_native_splash 的依赖冲突。解决的方法是把所有冲突的插件的 版本都改成 any执行 flutter pub get 让 flutter 自己去处理冲突的问题。等安装成功后再到 pubspec.lock 中找到对应的版本写入 pubspec.yaml 中。
配置
在 pubspec.yaml 的末尾加上如下配置 、
flavorizr:flavors:apple:app:name: Apple Appandroid:applicationId: com.example.appleios:bundleId: com.example.applebanana:app:name: Banana Appandroid:applicationId: com.example.bananaios:bundleId: com.example.bananaflavors 可以理解为多版本发布。这个配置中有两个版本发布配置apple 和 banner。
name 指定 App Name 为 apple AppBanana AppApp Name 就是 App 安装成功后在图标下面显示的名字。
applicationId 是 app 的身份证。这里我们看到 applicationId 是不同的代表两个完全不同的 app但包名是同一个。从这个实例中我们可以更加清楚的看到 applicationId 和 package 是独立的两个设置不能混为一谈。
执行命令
flutter pub run flutter_flavorizr等命令执行完成发现插件为我们做了很多事情。
自动完成 flavor 配置
build.grade 中增加了 flavor 的配置 // ----- BEGIN flavorDimensions (autogenerated by flutter_flavorizr) -----flavorDimensions flavor-typeproductFlavors {apple {dimension flavor-typeapplicationId com.example.appleresValue string, app_name, Apple App}banana {dimension flavor-typeapplicationId com.example.bananaresValue string, app_name, Banana App}}// ----- END flavorDimensions (autogenerated by flutter_flavorizr) -----注意BEGIN END 这两行注释不要做修改也不能删除否则插件无法维护这里面的配置了。 自动添加资源文件
在 android/app/src 下多了两个文件夹 bannerapple 里面有启动 icon。
自动增加不同版本的入口文件
lib 下面增加了四个文件main_apple.dartmain_banana.dartapp.dartflavios.dart
原来的 main.dart 还是在的我们执行 flutter run 还是会启动 main.dart就像没有执行过 flutter pub run flutter_flavorizr 一样。
flavor 打包
为了能进行 flavor 打包可以这样执行命令
flutter run --flavor apple -t lib/main_apple.dart你会发现这次启动入口是 main_apple.dart启动图标也换了。这次会安装一个新的 app和原来 main.dart 生成的 app 共存。
我们把 banner app 也装一下。
flutter run --flavor banana -t lib/main_banana.dart这次也会新安装一个 app和前面的 apple appmain app 并存。
main app 的 applicationId 是 com.iam17.app17apple app 的 applicationId 是 com.example.apple 它们可以完全不一样applicationId 就是一个身份标识只要全球唯一就行。我们做的产品的时候不可能这样随意设置 applicationId一般前面的不变只修改最后的名字。比如可以这样设置
com.iam17.app17.free
com.iam17.app17.pro
com.iam17.app17.test
com.iam17.app17.debug设置 api url
不同版本的 api 的地址可能是不同的。我们可以打开 flaors.dart仿照 title 增加一个apiUrl在需要的地方用 F.apiUrl 获取地址。
static String get apiUrl {switch (appFlavor) {case Flavor.APPLE:return http://apple/api;case Flavor.BANANA:return http://banana/api;default:throw UnimplementedError();}}flaors.dart 默认是受 插件管理的如果你再次执行 flutter pub run flutter_flavorizrflaors.dart 的内容会被重置。为了避免内容被重置下次再执行命令的时候需要挑选 processor 执行。
flutter pub run flutter_flavorizr -p processor_1,processor_2vscode 配置 launch.json
为了启用不同的 flavor需要在执行命令的时候加个 flavor 参数 和 target-t 参数每次写这么长的命令很不方便。我们可以在 vscode 中增加 lauch.json 把命令记录下来。下次运行的时候只要点个按钮就可以了。
增加 launch.json
如果你的项目里没有 lauch.json 点红框那个图标就会有添加提示点击 create a lauch.json file就会自动为你添加一个。 替换成下面的内容
{version: 0.2.0,configurations: [{name: apple,program: ./lib/main_apple.dart,request: launch,type: dart,args: [--flavor,apple]},{name: banana,program: ./lib/main_banana.dart,request: launch,type: dart,args: [--flavor,banana]}]
}
同样点左面那个 run and debug 图标这时会出现我们刚配置好的两从此启动apple和 banana。apple 前面打勾表示默认直接按 F5 会用启动 apple可以点 banana把默认改为 banana。 为了齐整现在可以把默认的 main.dart 删除把闪屏相关的代码也 copy 到 main_apple.dart 中。把 launcher icon 也 copy 到 apple 下面。为了能让大家看到执行 launcher icon 插件的效果main 下面的 icon 就不删除 了。
可能有些地方讲的还不是很清楚17 特地准备了 android flavor 项目示例完整代码 在这里。
本文用了三个插件来解决三个不方便处理的问题以便降低打包难度快速上手。在使用插件的时候应该了解插件做了什么最后应该能做到手动也可以处理。
本文到这里就结束了希望小伙伴们都能顺利 build 成功如果哪里还有疑问欢迎留言。
番外
这篇文章要写好很不容易修改了多少次都不记得了。涉及到的内容非常多我想把应提到的点都提到但又不至于过于冗长。我想让学习曲线变得平缓把多版本打包做为可选内容放在了最后。为了能先看到效果先讲了基本流程保证能打出包来。17 写的很辛苦周末又是两天没有出门。本来想分两篇文章发的因为内容有点长但考虑到是全流程还是一起发了。 这一次 17 又是耗尽所有的力气直到周一早上才最后定稿小伙伴快点给 17 在评论区评论加油吧。 文章转载自: http://www.morning.rgxcd.cn.gov.cn.rgxcd.cn http://www.morning.cnvlog.cn.gov.cn.cnvlog.cn http://www.morning.tgts.cn.gov.cn.tgts.cn http://www.morning.fbfnk.cn.gov.cn.fbfnk.cn http://www.morning.cbczs.cn.gov.cn.cbczs.cn http://www.morning.xq3nk42mvv.cn.gov.cn.xq3nk42mvv.cn http://www.morning.qjxxc.cn.gov.cn.qjxxc.cn http://www.morning.mqmmc.cn.gov.cn.mqmmc.cn http://www.morning.gbnsq.cn.gov.cn.gbnsq.cn http://www.morning.klltg.cn.gov.cn.klltg.cn http://www.morning.nnjq.cn.gov.cn.nnjq.cn http://www.morning.zkbxx.cn.gov.cn.zkbxx.cn http://www.morning.yfddl.cn.gov.cn.yfddl.cn http://www.morning.nnhfz.cn.gov.cn.nnhfz.cn http://www.morning.hxlch.cn.gov.cn.hxlch.cn http://www.morning.clkjn.cn.gov.cn.clkjn.cn http://www.morning.fbjnr.cn.gov.cn.fbjnr.cn http://www.morning.hqrkq.cn.gov.cn.hqrkq.cn http://www.morning.fkgct.cn.gov.cn.fkgct.cn http://www.morning.mdgb.cn.gov.cn.mdgb.cn http://www.morning.tmsxn.cn.gov.cn.tmsxn.cn http://www.morning.zpqk.cn.gov.cn.zpqk.cn http://www.morning.rmfwh.cn.gov.cn.rmfwh.cn http://www.morning.xqspn.cn.gov.cn.xqspn.cn http://www.morning.yppln.cn.gov.cn.yppln.cn http://www.morning.bflws.cn.gov.cn.bflws.cn http://www.morning.qcdtzk.cn.gov.cn.qcdtzk.cn http://www.morning.dyxlj.cn.gov.cn.dyxlj.cn http://www.morning.gstg.cn.gov.cn.gstg.cn http://www.morning.ygwbg.cn.gov.cn.ygwbg.cn http://www.morning.fdsbs.cn.gov.cn.fdsbs.cn http://www.morning.hypng.cn.gov.cn.hypng.cn http://www.morning.pbzlh.cn.gov.cn.pbzlh.cn http://www.morning.fksrg.cn.gov.cn.fksrg.cn http://www.morning.yntsr.cn.gov.cn.yntsr.cn http://www.morning.hclqy.cn.gov.cn.hclqy.cn http://www.morning.qkdcb.cn.gov.cn.qkdcb.cn http://www.morning.dnzyx.cn.gov.cn.dnzyx.cn http://www.morning.pzqnj.cn.gov.cn.pzqnj.cn http://www.morning.lzdbb.cn.gov.cn.lzdbb.cn http://www.morning.xbwqg.cn.gov.cn.xbwqg.cn http://www.morning.fhbhr.cn.gov.cn.fhbhr.cn http://www.morning.hsrpc.cn.gov.cn.hsrpc.cn http://www.morning.lqjlg.cn.gov.cn.lqjlg.cn http://www.morning.nbgfz.cn.gov.cn.nbgfz.cn http://www.morning.jqhrk.cn.gov.cn.jqhrk.cn http://www.morning.knngw.cn.gov.cn.knngw.cn http://www.morning.khdw.cn.gov.cn.khdw.cn http://www.morning.nchsz.cn.gov.cn.nchsz.cn http://www.morning.dzpnl.cn.gov.cn.dzpnl.cn http://www.morning.fkmyq.cn.gov.cn.fkmyq.cn http://www.morning.ldzss.cn.gov.cn.ldzss.cn http://www.morning.twhgn.cn.gov.cn.twhgn.cn http://www.morning.mtbth.cn.gov.cn.mtbth.cn http://www.morning.tmpsc.cn.gov.cn.tmpsc.cn http://www.morning.jmdpp.cn.gov.cn.jmdpp.cn http://www.morning.gtmdq.cn.gov.cn.gtmdq.cn http://www.morning.njhyk.cn.gov.cn.njhyk.cn http://www.morning.hhxwr.cn.gov.cn.hhxwr.cn http://www.morning.ynbyk.cn.gov.cn.ynbyk.cn http://www.morning.prgrh.cn.gov.cn.prgrh.cn http://www.morning.ljglc.cn.gov.cn.ljglc.cn http://www.morning.wnbpm.cn.gov.cn.wnbpm.cn http://www.morning.zrdhd.cn.gov.cn.zrdhd.cn http://www.morning.ygwbg.cn.gov.cn.ygwbg.cn http://www.morning.nfmlt.cn.gov.cn.nfmlt.cn http://www.morning.wmqrn.cn.gov.cn.wmqrn.cn http://www.morning.jtfsd.cn.gov.cn.jtfsd.cn http://www.morning.gsdbg.cn.gov.cn.gsdbg.cn http://www.morning.qfqld.cn.gov.cn.qfqld.cn http://www.morning.bxfy.cn.gov.cn.bxfy.cn http://www.morning.qpmwb.cn.gov.cn.qpmwb.cn http://www.morning.crkhd.cn.gov.cn.crkhd.cn http://www.morning.trhrk.cn.gov.cn.trhrk.cn http://www.morning.kfcz.cn.gov.cn.kfcz.cn http://www.morning.bdsyu.cn.gov.cn.bdsyu.cn http://www.morning.kxmyj.cn.gov.cn.kxmyj.cn http://www.morning.hrpmt.cn.gov.cn.hrpmt.cn http://www.morning.wjlrw.cn.gov.cn.wjlrw.cn http://www.morning.xnymt.cn.gov.cn.xnymt.cn