uniapp离线打包指南

uniapp本地打包官方文档,可以根据官方文档中的sdk文件夹UniPlugin-Hello-AS为基础进行改造,刚开始摸索时,也是一点点看文档、看demo进行搭建的,毕竟一点安卓开发的基础也没有,又因为业务需求必须要开发一个推送功能module,所以就先把本地测试环境搭建好,方便开发module。
首先创建一个新的空项目(android studio默认已经安装好,以下称作“ad”),File=>New=>New Project=>Empty Activity

Empty_Activity.png

接下来进行一些项目最基础的配置
image.png

然后Finish,ad会自动下载配置依赖,慢慢等待......
文件目录如下,各个文件的具体功能,可以自行百度(主要是不专业,怕说错喽) ↓↓↓↓

│  .gitignore
│  build.gradle 
│  gradle.properties
│  gradlew
│  gradlew.bat
│  local.properties
│  settings.gradle
├─app
│  │  .gitignore
│  │  build.gradle
│  │  proguard-rules.pro
│  │
│  ├─libs
│  └─src
│      ├─androidTest
│      │
│      ├─main
│      │  │  AndroidManifest.xml
│      │  │
│      │  ├─java
│      │  │  └─com
│      │  │      └─fq
│      │  │          └─test
│      │  │                  MainActivity.java
│      │  │
│      │  └─res
│      │
│      └─test
│
└─gradle
    └─wrapper
            gradle-wrapper.jar
            gradle-wrapper.properties

以下是自己的个人理解:

settings.gradle文件

settings.gradle文件是用于写项目之间的依懒关系,里面有项目的总名称,包含了哪些模块等,

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        jcenter() // Warning: this repository is going to shut down soon
    }
}
rootProject.name = "MyTest"
include ':app'

我不晓得里面的dependencyResolutionManagement有什么用,所以根据uniapp给的demo,把这个删除了,只留下了:

rootProject.name = "MyTest"
include ':app'  // 用于增加子模块,如果这个时候想加一个新的module  可以再加一个 include ":<module名>"

gradle.properties文件是配置gradle的,uniapp 本地开发需要这三个配置

org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
android.useAndroidX=true
android.enableJetifier=true

build.gradle文件

build.gradle文件是配置gradle依赖下载源,gradle构建工具的版本,我这里改成了阿里的源

buildscript {
    repositories {
        maven {
            url 'https://maven.aliyun.com/repository/google'
        }
        maven {
            url 'https://maven.aliyun.com/repository/public'
        }
        maven {
            url 'https://maven.aliyun.com/repository/jcenter'
        }
    }
    dependencies {
        classpath "com.android.tools.build:gradle:4.2.2"
    }
}
allprojects {
    repositories {
        maven {
            url 'https://maven.aliyun.com/repository/google'
        }
        maven {
            url 'https://maven.aliyun.com/repository/public'
        }
        maven {
            url 'https://maven.aliyun.com/repository/jcenter'
        }
    }
}
task clean(type: Delete) {
    delete rootProject.buildDir
}

最外围的改动就这些了,其他的操作都在app这个主项目文件夹下

注意以下的操作都在app文件夹内

删除掉了src下所有文件夹,新建了libssrc文件夹,

lib目录内容

其中libs下是需要引入的依赖

以下为运行必备的依赖
android-gif-drawable-release@1.2.23.aar
lib.5plus.base-release.aar
oaid_sdk_1.0.25.aar
uniapp-v8-release.aar

其他的依赖可以按照自己的实际需要放入,具体的增加哪些可以根据下载的sdk文件夹Feature-Android.xls查看
Feature-Android文件位置
这些是我用到的

build.gradle内的内容

// 声明是Android程序,
// com.android.application 表示这是一个应用程序模块,可直接运行
// com.android.library 标识这是一个库模块,是依附别的应用程序运行
apply plugin: 'com.android.application'
android {
    compileSdkVersion 30
    buildToolsVersion "30.0.3"
    defaultConfig {
        applicationId "app包名"  //注意确定自己的包名,不要有"test"之类的字眼,不然提交到应用商城会过不去
        minSdkVersion 21
        targetSdkVersion 26
        versionCode 79 // 对应hbuilder的 -> 应用版本号
        versionName "1.1.9.0"  // 对应hbuilder的 -> 应用版本名称
//        multiDexEnabled true
        ndk {
            abiFilters 'x86', 'armeabi-v7a', 'arm64-v8a', "x86_64" // 允许在哪些设备中运行你的app
        }
        archivesBaseName = "fqApp-$versionName" // 构建的apk名字
    }

    signingConfigs {
        config {  // 配置证书签名,如何生成证书 https://ask.dcloud.net.cn/article/35777
            storeFile file('./lalala.keystore')  // file中是你app证书的位置
            storePassword '123456'
            keyAlias 'lalala'
            keyPassword '123456'
            v1SigningEnabled true
            v2SigningEnabled true
        }
    }
    /**
     * 代码混淆
     */
    buildTypes {
        release {
            signingConfig signingConfigs.config // 签名配置
//            zipAlignEnabled true // 是否支持zip
//            shrinkResources true // 移除无用的resource文件
            debuggable true
            minifyEnabled true // 代码混淆
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
        debug {
//            zipAlignEnabled true
            debuggable true
            signingConfig signingConfigs.config
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    //使用uniapp时,需复制下面代码
    /*代码开始*/
    aaptOptions {
        additionalParameters '--auto-add-overlay'
        ignoreAssetsPattern "!.svn:!.git:.*:!CVS:!thumbs.db:!picasa.ini:!*.scc:*~"
    }
    /*代码结束*/
    /**
     * 编译配置
     */
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    lintOptions {
        abortOnError false
    }
}
dependencies {
    implementation fileTree(include: ['*.jar','*.aar'], dir: 'libs')

    implementation 'androidx.appcompat:appcompat:1.0.0'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'

    /*uniapp所需库-----------------------开始*/
    implementation 'androidx.recyclerview:recyclerview:1.0.0'
    implementation 'com.facebook.fresco:fresco:2.5.0'
    implementation "com.facebook.fresco:animated-gif:2.5.0"
    /*uniapp所需库-----------------------结束*/

    // 基座需要,必须添加
    implementation 'com.github.bumptech.glide:glide:4.9.0'
    implementation 'com.alibaba:fastjson:1.1.46.android'


    // 添加uni-app插件
    // implementation project(":fqPush")
}

src目录

src目录

目录截图,以下是其中各个文件内容,可以对照此图,查看各个文件的位置

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="你的包名">
    <supports-screens
        android:anyDensity="true"
        android:largeScreens="true"
        android:normalScreens="true"
        android:resizeable="true"
        android:smallScreens="true" />

    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />
<!-- app权限 根据实际情况增减  -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.FLASHLIGHT" />
    <uses-permission android:name="android.permission.GET_TASKS" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.INSTALL_PACKAGES" />
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <uses-permission android:name="android.permission.READ_LOGS" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
    <uses-permission android:name="android.permission.BROADCAST_PACKAGE_ADDED" />
    <uses-permission android:name="android.permission.BROADCAST_PACKAGE_CHANGED" />
    <uses-permission android:name="android.permission.BROADCAST_PACKAGE_INSTALL" />
    <uses-permission android:name="android.permission.BROADCAST_PACKAGE_REPLACED" />
    <uses-permission android:name="android.permission.RESTART_PACKAGES" />

    <application
        android:name="io.dcloud.application.DCloudApplication"
        android:allowClearUserData="true"
        android:icon="@drawable/icon"
        android:label="@string/app_name"
        android:supportsRtl="true"
        >
        <activity
            android:name="io.dcloud.PandoraEntry"
            android:configChanges="orientation|keyboardHidden|keyboard|navigation"
            android:label="@string/app_name"
            android:launchMode="singleTask"
            android:hardwareAccelerated="true"
            android:theme="@style/TranslucentTheme"
            android:screenOrientation="user"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="io.dcloud.PandoraEntryActivity"
            android:configChanges="orientation|keyboardHidden|screenSize|mcc|mnc|fontScale|keyboard|smallestScreenSize|screenLayout|screenSize"
            android:hardwareAccelerated="true"
            android:launchMode="singleTask"
            android:permission="com.miui.securitycenter.permission.AppPermissionsEditor"
            android:screenOrientation="user"
            android:theme="@style/DCloudTheme"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <action android:name="android.intent.action.VIEW" />
                <data android:scheme="h56131bcf" />
            </intent-filter>
        </activity>
        <!--provider节点必须添加-->
        <provider
            android:name="io.dcloud.common.util.DCloud_FileProvider"
            android:authorities="你的包名.dc.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/dcloud_file_provider" />
        </provider>
        //这里我用了高德地图 所以需要加这个 不用可以不加,具体加哪些还是看上面提到的excel文件
<!-- 高德 开始 -->
        <meta-data
            android:name="com.amap.api.v2.apikey"
            android:value="地图的key"
            >
        </meta-data>
        <service
            android:name="com.amap.api.location.APSService"
            >
        </service>
<!-- 高德 结束 -->
        // 离线打包的key, 没它可启动不了哦~
        <meta-data
            android:name="dcloud_appkey"
            android:value="你的离线打包key" />
    </application>

</manifest>

离线打包的key 从dcloud开发者中心获取


离线打包key

string.xml

<resources>
    <string name="app_name">你的应用名称</string>
</resources>

proguard-rules.pro

-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose

#-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-dontoptimize

-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class * extends io.dcloud.common.DHInterface.IPlugin
-keep public class * extends io.dcloud.common.DHInterface.IFeature
-keep public class * extends io.dcloud.common.DHInterface.IBoot
-keep public class * extends io.dcloud.common.DHInterface.IReflectAble

-keep class io.dcloud.feature.speech.** {*;}
-keep class io.dcloud.net.** {*;}
-keep class io.dcloud.common.constant.** {*;}
-keep class io.dcloud.common.sonic.** {*;}
-keep class io.dcloud.common.DHInterface.** {*;}
-keep class io.dcloud.common.util.** {*;}
-keep class io.dcloud.common.adapter.** {*;}
-keep class io.dcloud.feature.internal.reflect.** {*;}
-keep class io.dcloud.feature.internal.sdk.** {*;}
-keep class io.dcloud.feature.payment.** {*;}
-keep class io.dcloud.sdk.** {*;}
-keep class com.** {*;}
-keep class io.dcloud.nineoldandroids.** {*;}
-keep class vi.com.gdi.** {*;}
-keep class androidx.** {*;}
-dontwarn pl.droidsonroids.gif.**

-keepclasseswithmembers class * extends io.dcloud.js.geolocation.GeoManagerBase {
    <methods>;
}

-keep class io.dcloud.share.AbsWebviewClient
-keepclasseswithmembers class io.dcloud.share.AbsWebviewClient {
    <methods>;
}

-keep class io.dcloud.share.ShareAuthorizeView
-keepclasseswithmembers class io.dcloud.share.ShareAuthorizeView {
    <methods>;
}
-keep class io.dcloud.share.IFShareApi
-keep public class * extends io.dcloud.share.IFShareApi
-keepclasseswithmembers class io.dcloud.share.IFShareApi {
    <methods>;
}




-keepattributes Exceptions,InnerClasses,Signature,Deprecated, SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
-keep class io.dcloud.appstream.StreamAppManager
-keepclasseswithmembers class io.dcloud.appstream.StreamAppManager {
    public protected <methods>;
}

-keep class io.dcloud.common.DHInterface.IReflectAble
-keep public class * extends io.dcloud.common.DHInterface.IReflectAble{
  public protected <methods>;
  public protected *;
}
-keep class **.R
-keep class **.R$* {
    public static <fields>;
}
-keep public class * extends io.dcloud.common.DHInterface.IJsInterface{
  public protected <methods>;
  public protected *;
}

-keepclasseswithmembers class io.dcloud.EntryProxy {
    <methods>;
}

-keep class * implements android.os.IInterface {
  <methods>;
}

-keepclasseswithmembers class *{
  public static java.lang.String getJsContent();
}
-keepclasseswithmembers class io.dcloud.appstream.StreamAppScriptEntry {
    <methods>;
}
-keepclasseswithmembers class *{
    public static void onReceiver1(android.content.Intent, android.content.Context);
}

-keepclasseswithmembers class *{
  public static io.dcloud.share.AbsWebviewClient getWebviewClient(io.dcloud.share.ShareAuthorizeView);
}
-keepclasseswithmembers class *{
    public java.lang.String exec(java.lang.String,java.lang.String,java.lang.String[]);
}
-keepattributes Exceptions,InnerClasses,Signature,Deprecated, SourceFile,LineNumberTable,*Annotation*,EnclosingMethod

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

-keep public class * extends android.app.Application{
  public static <methods>;
  public *;
}

-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
   public static <methods>;
}

-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}

-keepattributes Signature
-keep class io.dcloud.encryption.K {*;}
-dontwarn com.igexin.**
-keep class org.json.** { *; }
-dontwarn com.amap.**
-dontwarn org.apache.commons.**
-dontwarn com.sina.weibo.sdk.**

-keep class tv.danmaku.ijk.media.player.** {*;}

-keep class uni.** {*;}
-keep class pl.** {*;}
-keep class io.** {*;}
-keep class org.mozilla.**{*;}

-keep class androidtranscoder.**{*;}
-keep class XI.**{*;}

drawable-xxhdpi

该文件夹下的是应用的基础图片,其实还有各种分辨率的,但是没有的话,安卓会使用当前存在的进行放大缩小,因为当时的目的仅仅是为了搭建一个本地环境,所以只设置了drawable-xxhdpi文件夹。

icon.png // 应用显示在手机桌面上的图标
push.png // 应用推送时的图标
splash.9.png  // 应用刚刚打开时的图片

apps

apps下是使用hbuilderx生成的文件夹

生成到前端项目dist->resources

假如生成的是__UNI__E34234,直接把__UNI__E34234文件夹放到apps下

dcloud_uniplugins.json

该文件夹是添加module的,目前文件内不需要加内容

data

dcloud_control.xml
dcloud_error.html
dcloud_properties.xml

以上三个直接从UniPlugin-Hello-AS\app\src\main\assets\data文件夹内复制粘贴
其中dcloud_control.xml内容(__UNI__E34234是随便写的,它应该跟你的uniapp应用标识一致)

<hbuilder>
<apps>
    <app appid="__UNI__E34234" appver=""/>
</apps>
</hbuilder>

进行完以上操作后,基本可以happy了
把手机连接电脑,调试模式,或者使用ad的AVD


运行

打包的话,点击后,下一步,填入证书就ok啦~


打包

参考

因为之前百度找了好多,不知道借鉴了哪些文章,所以就不列出来了
over~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容