本来是使用uniapp进行开发,然后打包成安卓软件的,因为是用了地图模块(基于天地图),因为uniapp框架的限制,只能使用webview组件引入地图文件,然后出现一个问题,发现地图在浏览器中打开很流畅,打包成app之后非常卡顿,试了很多种办法,包括把地图放在vue文件中来渲染,发现依然卡,然后想到能不能直接把打包成H5,然后整个文件丢在安卓中,用安卓的webview去打开它,尝试之后发现效果还挺好的,下面列出代码(自己需要啥功能需要自己去添加,可以自行添加腾讯的X5内核)

具体步骤
  1. HbuilderX把uniapp项目打包成H5手机版

  2. 新建一个安卓项目

  3. 新建一个assets目录(src目录单击右键选择,弹出的提示框选择finish就可以自动生成assets目录了)

  4. 把打包好的文件发到assets目录

  5. 编写程序

  6. 运行

uniapp打包注意点

将app打包成H5手机版注意别忘了把运行的基础路径改为./

开发工具

Android Studio版本 4.0.1

Java版本 Java1.8(使用到了lambda表达式,需要去设置为1.8,否者会报错)设置教程:https://blog.csdn.net/weixin_43373239/article/details/88741896

使用到的库

statusbar状态栏工具类(实现沉浸式状态栏/变色状态栏)

https://jaeger.itscoder.com/android/2016/03/27/statusbar-util.html

使用到的权限
<!--外部存储权限 这个目前没有使用到-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--获取wifi和网络信息-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--网络权限-->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!--定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
目录结构

软件运行流程

初次安装软件后,打开app,会弹出申请定位权限提示框,如果用户没有授权,则会弹出“请开启定位权限”提示框,用户点击确定后会自动关闭软件,如果用户授权之后,会弹出申请获取手机信息权限(因为在华为手机上如果没有获取此项权限可能无法使用定位功能),如果用户没有授权会提示“请开启获取手机信息权限”,用户点击确定按钮后会自动关闭软件,当用户开启所有权限后,会进入到登录页面,因为网页是存放在安卓本地,所以不会存在用户断网之后出现404页面的情况。

#mermaid-svg-iyQ7IbbteaJvJa0d .label {font-family: 'trebuchet ms', verdana, arial;font-family: var(--mermaid-font-family);fill: #333;color: #333; }#mermaid-svg-iyQ7IbbteaJvJa0d .label text {fill: #333; }#mermaid-svg-iyQ7IbbteaJvJa0d .node rect, #mermaid-svg-iyQ7IbbteaJvJa0d .node circle, #mermaid-svg-iyQ7IbbteaJvJa0d .node ellipse, #mermaid-svg-iyQ7IbbteaJvJa0d .node polygon, #mermaid-svg-iyQ7IbbteaJvJa0d .node path {fill: #ECECFF;stroke: #9370DB;stroke-width: 1px; }#mermaid-svg-iyQ7IbbteaJvJa0d .node .label {text-align: center;fill: #333; }#mermaid-svg-iyQ7IbbteaJvJa0d .node.clickable {cursor: pointer; }#mermaid-svg-iyQ7IbbteaJvJa0d .arrowheadPath {fill: #333333; }#mermaid-svg-iyQ7IbbteaJvJa0d .edgePath .path {stroke: #333333;stroke-width: 1.5px; }#mermaid-svg-iyQ7IbbteaJvJa0d .flowchart-link {stroke: #333333;fill: none; }#mermaid-svg-iyQ7IbbteaJvJa0d .edgeLabel {background-color: #e8e8e8;text-align: center; } #mermaid-svg-iyQ7IbbteaJvJa0d .edgeLabel rect {opacity: 0.9; } #mermaid-svg-iyQ7IbbteaJvJa0d .edgeLabel span {color: #333; }#mermaid-svg-iyQ7IbbteaJvJa0d .cluster rect {fill: #ffffde;stroke: #aaaa33;stroke-width: 1px; }#mermaid-svg-iyQ7IbbteaJvJa0d .cluster text {fill: #333; }#mermaid-svg-iyQ7IbbteaJvJa0d div.mermaidTooltip {position: absolute;text-align: center;max-width: 200px;padding: 2px;font-family: 'trebuchet ms', verdana, arial;font-family: var(--mermaid-font-family);font-size: 12px;background: #ffffde;border: 1px solid #aaaa33;border-radius: 2px;pointer-events: none;z-index: 100; }#mermaid-svg-iyQ7IbbteaJvJa0d .actor {stroke: #CCCCFF;fill: #ECECFF; }#mermaid-svg-iyQ7IbbteaJvJa0d text.actor > tspan {fill: black;stroke: none; }#mermaid-svg-iyQ7IbbteaJvJa0d .actor-line {stroke: grey; }#mermaid-svg-iyQ7IbbteaJvJa0d .messageLine0 {stroke-width: 1.5;stroke-dasharray: none;stroke: #333; }#mermaid-svg-iyQ7IbbteaJvJa0d .messageLine1 {stroke-width: 1.5;stroke-dasharray: 2, 2;stroke: #333; }#mermaid-svg-iyQ7IbbteaJvJa0d #arrowhead path {fill: #333;stroke: #333; }#mermaid-svg-iyQ7IbbteaJvJa0d .sequenceNumber {fill: white; }#mermaid-svg-iyQ7IbbteaJvJa0d #sequencenumber {fill: #333; }#mermaid-svg-iyQ7IbbteaJvJa0d #crosshead path {fill: #333;stroke: #333; }#mermaid-svg-iyQ7IbbteaJvJa0d .messageText {fill: #333;stroke: #333; }#mermaid-svg-iyQ7IbbteaJvJa0d .labelBox {stroke: #CCCCFF;fill: #ECECFF; }#mermaid-svg-iyQ7IbbteaJvJa0d .labelText,#mermaid-svg-iyQ7IbbteaJvJa0d .labelText > tspan {fill: black;stroke: none; }#mermaid-svg-iyQ7IbbteaJvJa0d .loopText,#mermaid-svg-iyQ7IbbteaJvJa0d .loopText > tspan {fill: black;stroke: none; }#mermaid-svg-iyQ7IbbteaJvJa0d .loopLine {stroke-width: 2px;stroke-dasharray: 2, 2;stroke: #CCCCFF;fill: #CCCCFF; }#mermaid-svg-iyQ7IbbteaJvJa0d .note {stroke: #aaaa33;fill: #fff5ad; }#mermaid-svg-iyQ7IbbteaJvJa0d .noteText,#mermaid-svg-iyQ7IbbteaJvJa0d .noteText > tspan {fill: black;stroke: none; }#mermaid-svg-iyQ7IbbteaJvJa0d .activation0 {fill: #f4f4f4;stroke: #666; }#mermaid-svg-iyQ7IbbteaJvJa0d .activation1 {fill: #f4f4f4;stroke: #666; }#mermaid-svg-iyQ7IbbteaJvJa0d .activation2 {fill: #f4f4f4;stroke: #666; }#mermaid-svg-iyQ7IbbteaJvJa0d .mermaid-main-font {font-family: "trebuchet ms", verdana, arial;font-family: var(--mermaid-font-family); }#mermaid-svg-iyQ7IbbteaJvJa0d .section {stroke: none;opacity: 0.2; }#mermaid-svg-iyQ7IbbteaJvJa0d .section0 {fill: rgba(102, 102, 255, 0.49); }#mermaid-svg-iyQ7IbbteaJvJa0d .section2 {fill: #fff400; }#mermaid-svg-iyQ7IbbteaJvJa0d .section1, #mermaid-svg-iyQ7IbbteaJvJa0d .section3 {fill: white;opacity: 0.2; }#mermaid-svg-iyQ7IbbteaJvJa0d .sectionTitle0 {fill: #333; }#mermaid-svg-iyQ7IbbteaJvJa0d .sectionTitle1 {fill: #333; }#mermaid-svg-iyQ7IbbteaJvJa0d .sectionTitle2 {fill: #333; }#mermaid-svg-iyQ7IbbteaJvJa0d .sectionTitle3 {fill: #333; }#mermaid-svg-iyQ7IbbteaJvJa0d .sectionTitle {text-anchor: start;font-size: 11px;text-height: 14px;font-family: 'trebuchet ms', verdana, arial;font-family: var(--mermaid-font-family); }#mermaid-svg-iyQ7IbbteaJvJa0d .grid .tick {stroke: lightgrey;opacity: 0.8;shape-rendering: crispEdges; } #mermaid-svg-iyQ7IbbteaJvJa0d .grid .tick text {font-family: 'trebuchet ms', verdana, arial;font-family: var(--mermaid-font-family); }#mermaid-svg-iyQ7IbbteaJvJa0d .grid path {stroke-width: 0; }#mermaid-svg-iyQ7IbbteaJvJa0d .today {fill: none;stroke: red;stroke-width: 2px; }#mermaid-svg-iyQ7IbbteaJvJa0d .task {stroke-width: 2; }#mermaid-svg-iyQ7IbbteaJvJa0d .taskText {text-anchor: middle;font-family: 'trebuchet ms', verdana, arial;font-family: var(--mermaid-font-family); }#mermaid-svg-iyQ7IbbteaJvJa0d .taskText:not([font-size]) {font-size: 11px; }#mermaid-svg-iyQ7IbbteaJvJa0d .taskTextOutsideRight {fill: black;text-anchor: start;font-size: 11px;font-family: 'trebuchet ms', verdana, arial;font-family: var(--mermaid-font-family); }#mermaid-svg-iyQ7IbbteaJvJa0d .taskTextOutsideLeft {fill: black;text-anchor: end;font-size: 11px; }#mermaid-svg-iyQ7IbbteaJvJa0d .task.clickable {cursor: pointer; }#mermaid-svg-iyQ7IbbteaJvJa0d .taskText.clickable {cursor: pointer;fill: #003163 !important;font-weight: bold; }#mermaid-svg-iyQ7IbbteaJvJa0d .taskTextOutsideLeft.clickable {cursor: pointer;fill: #003163 !important;font-weight: bold; }#mermaid-svg-iyQ7IbbteaJvJa0d .taskTextOutsideRight.clickable {cursor: pointer;fill: #003163 !important;font-weight: bold; }#mermaid-svg-iyQ7IbbteaJvJa0d .taskText0, #mermaid-svg-iyQ7IbbteaJvJa0d .taskText1, #mermaid-svg-iyQ7IbbteaJvJa0d .taskText2, #mermaid-svg-iyQ7IbbteaJvJa0d .taskText3 {fill: white; }#mermaid-svg-iyQ7IbbteaJvJa0d .task0, #mermaid-svg-iyQ7IbbteaJvJa0d .task1, #mermaid-svg-iyQ7IbbteaJvJa0d .task2, #mermaid-svg-iyQ7IbbteaJvJa0d .task3 {fill: #8a90dd;stroke: #534fbc; }#mermaid-svg-iyQ7IbbteaJvJa0d .taskTextOutside0, #mermaid-svg-iyQ7IbbteaJvJa0d .taskTextOutside2 {fill: black; }#mermaid-svg-iyQ7IbbteaJvJa0d .taskTextOutside1, #mermaid-svg-iyQ7IbbteaJvJa0d .taskTextOutside3 {fill: black; }#mermaid-svg-iyQ7IbbteaJvJa0d .active0, #mermaid-svg-iyQ7IbbteaJvJa0d .active1, #mermaid-svg-iyQ7IbbteaJvJa0d .active2, #mermaid-svg-iyQ7IbbteaJvJa0d .active3 {fill: #bfc7ff;stroke: #534fbc; }#mermaid-svg-iyQ7IbbteaJvJa0d .activeText0, #mermaid-svg-iyQ7IbbteaJvJa0d .activeText1, #mermaid-svg-iyQ7IbbteaJvJa0d .activeText2, #mermaid-svg-iyQ7IbbteaJvJa0d .activeText3 {fill: black !important; }#mermaid-svg-iyQ7IbbteaJvJa0d .done0, #mermaid-svg-iyQ7IbbteaJvJa0d .done1, #mermaid-svg-iyQ7IbbteaJvJa0d .done2, #mermaid-svg-iyQ7IbbteaJvJa0d .done3 {stroke: grey;fill: lightgrey;stroke-width: 2; }#mermaid-svg-iyQ7IbbteaJvJa0d .doneText0, #mermaid-svg-iyQ7IbbteaJvJa0d .doneText1, #mermaid-svg-iyQ7IbbteaJvJa0d .doneText2, #mermaid-svg-iyQ7IbbteaJvJa0d .doneText3 {fill: black !important; }#mermaid-svg-iyQ7IbbteaJvJa0d .crit0, #mermaid-svg-iyQ7IbbteaJvJa0d .crit1, #mermaid-svg-iyQ7IbbteaJvJa0d .crit2, #mermaid-svg-iyQ7IbbteaJvJa0d .crit3 {stroke: #ff8888;fill: red;stroke-width: 2; }#mermaid-svg-iyQ7IbbteaJvJa0d .activeCrit0, #mermaid-svg-iyQ7IbbteaJvJa0d .activeCrit1, #mermaid-svg-iyQ7IbbteaJvJa0d .activeCrit2, #mermaid-svg-iyQ7IbbteaJvJa0d .activeCrit3 {stroke: #ff8888;fill: #bfc7ff;stroke-width: 2; }#mermaid-svg-iyQ7IbbteaJvJa0d .doneCrit0, #mermaid-svg-iyQ7IbbteaJvJa0d .doneCrit1, #mermaid-svg-iyQ7IbbteaJvJa0d .doneCrit2, #mermaid-svg-iyQ7IbbteaJvJa0d .doneCrit3 {stroke: #ff8888;fill: lightgrey;stroke-width: 2;cursor: pointer;shape-rendering: crispEdges; }#mermaid-svg-iyQ7IbbteaJvJa0d .milestone {transform: rotate(45deg) scale(0.8, 0.8); }#mermaid-svg-iyQ7IbbteaJvJa0d .milestoneText {font-style: italic; }#mermaid-svg-iyQ7IbbteaJvJa0d .doneCritText0, #mermaid-svg-iyQ7IbbteaJvJa0d .doneCritText1, #mermaid-svg-iyQ7IbbteaJvJa0d .doneCritText2, #mermaid-svg-iyQ7IbbteaJvJa0d .doneCritText3 {fill: black !important; }#mermaid-svg-iyQ7IbbteaJvJa0d .activeCritText0, #mermaid-svg-iyQ7IbbteaJvJa0d .activeCritText1, #mermaid-svg-iyQ7IbbteaJvJa0d .activeCritText2, #mermaid-svg-iyQ7IbbteaJvJa0d .activeCritText3 {fill: black !important; }#mermaid-svg-iyQ7IbbteaJvJa0d .titleText {text-anchor: middle;font-size: 18px;fill: black;font-family: 'trebuchet ms', verdana, arial;font-family: var(--mermaid-font-family); }#mermaid-svg-iyQ7IbbteaJvJa0d g.classGroup text {fill: #9370DB;stroke: none;font-family: 'trebuchet ms', verdana, arial;font-family: var(--mermaid-font-family);font-size: 10px; } #mermaid-svg-iyQ7IbbteaJvJa0d g.classGroup text .title {font-weight: bolder; }#mermaid-svg-iyQ7IbbteaJvJa0d g.clickable {cursor: pointer; }#mermaid-svg-iyQ7IbbteaJvJa0d g.classGroup rect {fill: #ECECFF;stroke: #9370DB; }#mermaid-svg-iyQ7IbbteaJvJa0d g.classGroup line {stroke: #9370DB;stroke-width: 1; }#mermaid-svg-iyQ7IbbteaJvJa0d .classLabel .box {stroke: none;stroke-width: 0;fill: #ECECFF;opacity: 0.5; }#mermaid-svg-iyQ7IbbteaJvJa0d .classLabel .label {fill: #9370DB;font-size: 10px; }#mermaid-svg-iyQ7IbbteaJvJa0d .relation {stroke: #9370DB;stroke-width: 1;fill: none; }#mermaid-svg-iyQ7IbbteaJvJa0d .dashed-line {stroke-dasharray: 3; }#mermaid-svg-iyQ7IbbteaJvJa0d #compositionStart {fill: #9370DB;stroke: #9370DB;stroke-width: 1; }#mermaid-svg-iyQ7IbbteaJvJa0d #compositionEnd {fill: #9370DB;stroke: #9370DB;stroke-width: 1; }#mermaid-svg-iyQ7IbbteaJvJa0d #aggregationStart {fill: #ECECFF;stroke: #9370DB;stroke-width: 1; }#mermaid-svg-iyQ7IbbteaJvJa0d #aggregationEnd {fill: #ECECFF;stroke: #9370DB;stroke-width: 1; }#mermaid-svg-iyQ7IbbteaJvJa0d #dependencyStart {fill: #9370DB;stroke: #9370DB;stroke-width: 1; }#mermaid-svg-iyQ7IbbteaJvJa0d #dependencyEnd {fill: #9370DB;stroke: #9370DB;stroke-width: 1; }#mermaid-svg-iyQ7IbbteaJvJa0d #extensionStart {fill: #9370DB;stroke: #9370DB;stroke-width: 1; }#mermaid-svg-iyQ7IbbteaJvJa0d #extensionEnd {fill: #9370DB;stroke: #9370DB;stroke-width: 1; }#mermaid-svg-iyQ7IbbteaJvJa0d .commit-id, #mermaid-svg-iyQ7IbbteaJvJa0d .commit-msg, #mermaid-svg-iyQ7IbbteaJvJa0d .branch-label {fill: lightgrey;color: lightgrey;font-family: 'trebuchet ms', verdana, arial;font-family: var(--mermaid-font-family); }#mermaid-svg-iyQ7IbbteaJvJa0d .pieTitleText {text-anchor: middle;font-size: 25px;fill: black;font-family: 'trebuchet ms', verdana, arial;font-family: var(--mermaid-font-family); }#mermaid-svg-iyQ7IbbteaJvJa0d .slice {font-family: 'trebuchet ms', verdana, arial;font-family: var(--mermaid-font-family); }#mermaid-svg-iyQ7IbbteaJvJa0d g.stateGroup text {fill: #9370DB;stroke: none;font-size: 10px;font-family: 'trebuchet ms', verdana, arial;font-family: var(--mermaid-font-family); }#mermaid-svg-iyQ7IbbteaJvJa0d g.stateGroup text {fill: #9370DB;fill: #333;stroke: none;font-size: 10px; }#mermaid-svg-iyQ7IbbteaJvJa0d g.statediagram-cluster .cluster-label text {fill: #333; }#mermaid-svg-iyQ7IbbteaJvJa0d g.stateGroup .state-title {font-weight: bolder;fill: black; }#mermaid-svg-iyQ7IbbteaJvJa0d g.stateGroup rect {fill: #ECECFF;stroke: #9370DB; }#mermaid-svg-iyQ7IbbteaJvJa0d g.stateGroup line {stroke: #9370DB;stroke-width: 1; }#mermaid-svg-iyQ7IbbteaJvJa0d .transition {stroke: #9370DB;stroke-width: 1;fill: none; }#mermaid-svg-iyQ7IbbteaJvJa0d .stateGroup .composit {fill: white;border-bottom: 1px; }#mermaid-svg-iyQ7IbbteaJvJa0d .stateGroup .alt-composit {fill: #e0e0e0;border-bottom: 1px; }#mermaid-svg-iyQ7IbbteaJvJa0d .state-note {stroke: #aaaa33;fill: #fff5ad; } #mermaid-svg-iyQ7IbbteaJvJa0d .state-note text {fill: black;stroke: none;font-size: 10px; }#mermaid-svg-iyQ7IbbteaJvJa0d .stateLabel .box {stroke: none;stroke-width: 0;fill: #ECECFF;opacity: 0.7; }#mermaid-svg-iyQ7IbbteaJvJa0d .edgeLabel text {fill: #333; }#mermaid-svg-iyQ7IbbteaJvJa0d .stateLabel text {fill: black;font-size: 10px;font-weight: bold;font-family: 'trebuchet ms', verdana, arial;font-family: var(--mermaid-font-family); }#mermaid-svg-iyQ7IbbteaJvJa0d .node circle.state-start {fill: black;stroke: black; }#mermaid-svg-iyQ7IbbteaJvJa0d .node circle.state-end {fill: black;stroke: white;stroke-width: 1.5; }#mermaid-svg-iyQ7IbbteaJvJa0d #statediagram-barbEnd {fill: #9370DB; }#mermaid-svg-iyQ7IbbteaJvJa0d .statediagram-cluster rect {fill: #ECECFF;stroke: #9370DB;stroke-width: 1px; }#mermaid-svg-iyQ7IbbteaJvJa0d .statediagram-cluster rect.outer {rx: 5px;ry: 5px; }#mermaid-svg-iyQ7IbbteaJvJa0d .statediagram-state .divider {stroke: #9370DB; }#mermaid-svg-iyQ7IbbteaJvJa0d .statediagram-state .title-state {rx: 5px;ry: 5px; }#mermaid-svg-iyQ7IbbteaJvJa0d .statediagram-cluster.statediagram-cluster .inner {fill: white; }#mermaid-svg-iyQ7IbbteaJvJa0d .statediagram-cluster.statediagram-cluster-alt .inner {fill: #e0e0e0; }#mermaid-svg-iyQ7IbbteaJvJa0d .statediagram-cluster .inner {rx: 0;ry: 0; }#mermaid-svg-iyQ7IbbteaJvJa0d .statediagram-state rect.basic {rx: 5px;ry: 5px; }#mermaid-svg-iyQ7IbbteaJvJa0d .statediagram-state rect.divider {stroke-dasharray: 10,10;fill: #efefef; }#mermaid-svg-iyQ7IbbteaJvJa0d .note-edge {stroke-dasharray: 5; }#mermaid-svg-iyQ7IbbteaJvJa0d .statediagram-note rect {fill: #fff5ad;stroke: #aaaa33;stroke-width: 1px;rx: 0;ry: 0; }:root {--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive; }#mermaid-svg-iyQ7IbbteaJvJa0d .error-icon {fill: #552222; }#mermaid-svg-iyQ7IbbteaJvJa0d .error-text {fill: #552222;stroke: #552222; }#mermaid-svg-iyQ7IbbteaJvJa0d .edge-thickness-normal {stroke-width: 2px; }#mermaid-svg-iyQ7IbbteaJvJa0d .edge-thickness-thick {stroke-width: 3.5px; }#mermaid-svg-iyQ7IbbteaJvJa0d .edge-pattern-solid {stroke-dasharray: 0; }#mermaid-svg-iyQ7IbbteaJvJa0d .edge-pattern-dashed {stroke-dasharray: 3; }#mermaid-svg-iyQ7IbbteaJvJa0d .edge-pattern-dotted {stroke-dasharray: 2; }#mermaid-svg-iyQ7IbbteaJvJa0d .marker {fill: #333333; }#mermaid-svg-iyQ7IbbteaJvJa0d .marker.cross {stroke: #333333; }:root { --mermaid-font-family: "trebuchet ms", verdana, arial;} #mermaid-svg-iyQ7IbbteaJvJa0d {color: rgba(0, 0, 0, 0.75);font: ;}

授予权限
拒绝授权
授予权限
拒绝授权
进入湿地监测软件
申请定位权限
申请获取手机信息权限
弹出信息提示框`提示开启权限`
进入到登录页面
退出程序
布局文件(activity_mian.xml)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><WebViewandroid:id="@+id/webView"android:layout_width="match_parent"android:layout_height="match_parent"android:scrollbars="none" />
</androidx.constraintlayout.widget.ConstraintLayout>

android:scrollbars="none"不显示滚动条

主要Activity(MainActivity)
package com.example.opeak;import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Bundle;
import android.view.KeyEvent;
import android.webkit.GeolocationPermissions;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;import com.jaeger.library.StatusBarUtil;public class MainActivity extends Activity {private WebView webView;private static final int LOCATION_CODE = 1;private static final int READ_PHONE_CODE = 2;private boolean isWebLocation = false;private ValueCallback<Uri[]> valueCallback;private boolean uploadImage = true;/*** 顶部背景色 蓝 灰*/private String[] topColors = {"#FFFFFF", "#52A8F9", "#F8F8F8"};private String indexPageUrl = "file:///android_asset/h5/index.html#/pages/index/index";private String loginPageUrl = "file:///android_asset/h5/index.html#/";@SuppressLint("SetJavaScriptEnabled")@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);getGPSPermission();String url = "file:///android_asset/h5/index.html";webView = findViewById(R.id.webView);WebSettings webSettings = webView.getSettings();//开启JavaScriptwebSettings.setJavaScriptEnabled(true);webSettings.setDomStorageEnabled(true);//设置可以访问文件webSettings.setAllowFileAccess(true);webSettings.setLoadsImagesAutomatically(true);webView.setVerticalScrollBarEnabled(false);webView.setHorizontalScrollBarEnabled(false);webSettings.setAppCacheEnabled(true);webSettings.setDatabaseEnabled(true);String dir = getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();webSettings.setGeolocationDatabasePath(dir);webSettings.supportMultipleWindows();webSettings.setAllowContentAccess(true);webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);//允许地理位置可用webSettings.setGeolocationEnabled(true);webSettings.setJavaScriptCanOpenWindowsAutomatically(true);//加载urlwebView.loadUrl(url);//不可复制 就是拦截长按事件(如果要改成可以复制  把下面的代码注释掉就可以了)webView.setOnLongClickListener(v -> true);webView.setWebChromeClient(new WebChromeClient() {//网页申请定位后回调@Overridepublic void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {//判断是否有权限、是否开启了定位功能locationPermission();//invoke(申请定位网站的网址,是否同意定位,是否缓存授权)callback.invoke(origin, isWebLocation, false);}//选择文件@Overridepublic boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> valueCallback, FileChooserParams fileChooserParams) {showToast("请选择头像!");MainActivity.this.valueCallback = valueCallback;showFileChooser();//如果filePathCallback被调用;返回false,如果忽略处理return uploadImage;}//js弹框  下面的几个分别对应js中的alert弹框、confirm弹框等等@Overridepublic boolean onJsAlert(WebView webView, String url, String message, JsResult jsResult) {jsResult.confirm();showToast(message);return true;}@Overridepublic boolean onJsConfirm(WebView webview, String url, String message, JsResult result) {//可以弹框或进行其它处理,但一定要回调result.confirm或者cancelshowMeDialog(message, (dialogInterface, i) -> {result.confirm();},(dialogInterface, i) -> {result.cancel();});return true;}@Overridepublic boolean onJsBeforeUnload(WebView webview, String url, String message, JsResult result) {//可以弹框或进行其它处理,但一定要回调result.confirm或者cancelreturn true;}@Overridepublic boolean onJsPrompt(WebView webview, String url, String message, String defaultValue, JsPromptResult result) {//可以弹框或进行其它处理,但一定要回调result.confirm或者cancel,confirm可以将用户输入作为参数return true;}});webView.setWebViewClient(new WebViewClient() {/*** 顶部任务栏颜色变化* @param webView* @param s* @param b*/@Overridepublic void doUpdateVisitedHistory(WebView webView, String s, boolean b) {if (s.equals(indexPageUrl)) {StatusBarUtil.setColor(MainActivity.this, Color.parseColor(topColors[1]));} else if (s.equals(loginPageUrl)) {StatusBarUtil.setColor(MainActivity.this, Color.parseColor(topColors[0]));} else {StatusBarUtil.setColor(MainActivity.this, Color.parseColor(topColors[2]));}}});}/*** 判断是否拥有定位权限* PERMISSION_GRANTED:有权限*/public void locationPermission() {LocationManager lm = (LocationManager) MainActivity.this.getSystemService(LOCATION_SERVICE);boolean ok = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);if (ok) {getGPSPermission();} else {isWebLocation = false;showToast("未开启GPS定位服务,定位功能将受限!");}}/*** 申请定位权限*/public void getGPSPermission() {//没有权限if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION)!= PackageManager.PERMISSION_GRANTED) {// 没有权限,申请权限。ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_CODE);} else {isWebLocation = true;phoneInformationPermission();}}/*** 判断是否有获取手机信息权限(没有此权限,华为手机不能定位)*/public void phoneInformationPermission() {//如果没有权限if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {// 没有权限,申请权限。ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_PHONE_STATE}, READ_PHONE_CODE);}}/*** 申请权限后会回调** @param requestCode* @param permissions* @param grantResults*/@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {if (requestCode == LOCATION_CODE) {if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {isWebLocation = true;phoneInformationPermission();} else {isWebLocation = false;showMeDialog("请开启手机定位权限!",(dialogInterface, i) -> {closeApp();},null);}} else if (requestCode == READ_PHONE_CODE) {if (grantResults.length <= 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {showMeDialog("请开启获取手机信息权限!",(dialogInterface, i) -> {closeApp();},null);}}}/*** 关闭app*/private void closeApp() {finish();System.exit(0);}/*** 显示文件选择器*/private void showFileChooser() {Intent intent = new Intent(Intent.ACTION_GET_CONTENT);intent.setType("image/*");//设置类型,我这里是任意类型,任意后缀的可以这样写。intent.addCategory(Intent.CATEGORY_OPENABLE);startActivityForResult(intent, 1);}/*** 上传图片后回调** @param requestCode* @param resultCode* @param data*/@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if (resultCode == Activity.RESULT_OK) {//是否选择,没选择就不会继续Uri uri = data.getData();Uri[] uris = new Uri[]{uri};valueCallback.onReceiveValue(uris);uploadImage = false;showToast("正在上传头像,请稍后!");} else {uploadImage = true;valueCallback.onReceiveValue(null);showToast("没有选择头像文件!");}}/*** 编写后退事件** @param keyCode* @param event* @return*/@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK) {//时候可以后退boolean goBack = webView.canGoBack();if (goBack) {//后退webView.goBack();} else {showCoverDialog();}return true;}//继续执行父类的其他点击事件return false;}/*** 显示退出弹框*/private void showCoverDialog() {showMeDialog("是否退出本程序", (dialogInterface, i) -> {closeApp();},(dialogInterface, i) -> {});}/*** 显示弹框** @param message 内容* @param ok      点击确定的事件* @param cancel  点击取消的事件*/private void showMeDialog(String message, DialogInterface.OnClickListener ok, DialogInterface.OnClickListener cancel) {AlertDialog.Builder builder = new AlertDialog.Builder(this);builder.setTitle("提示");builder.setMessage(message);builder.setPositiveButton("是", ok);if (cancel != null) {builder.setNegativeButton("否", cancel);}builder.show();}@Overrideprotected void onDestroy() {//删除地理位置授权,也可以删除某个域名的授权(参考接口类)GeolocationPermissions.getInstance().clearAll();webView.destroy();super.onDestroy();}/*** 显示提示(去除小米手机自带应用名)** @param message 消息*/private void showToast(String message) {Toast toast = Toast.makeText(this, null, Toast.LENGTH_SHORT);toast.setText(message);toast.show();}}
AndroidManifest.xml文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"package="com.example.opeak"><!--外部存储权限--><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><!--获取wifi和网络信息--><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><!--网络权限--><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><!--定位--><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><applicationandroid:name=".MeApplication"android:allowBackup="false"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:supportsRtl="true"android:theme="@style/AppTheme"android:usesCleartextTraffic="true"tools:targetApi="m"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>

android:usesCleartextTraffic=true别忘了加(如果你的网页都是https的请求那就可以不用加了)。

摘取网络上的一段解释:

android:usesCleartextTraffic 指示应用程序是否打算使用明文网络流量,例如明文HTTP。目标API级别为27或更低的应用程序的默认值为“ true”。面向API级别28或更高级别的应用默认为“ false”。

当属性设置为“ false”时,平台组件(例如,HTTP和FTP堆栈,DownloadManager和MediaPlayer)将拒绝应用程序使用明文流量的请求。强烈建议第三方库也采用此设置。避免明文通信的主要原因是缺乏机密性,真实性和防篡改保护;网络攻击者可以窃听所传输的数据,并且还可以对其进行修改而不会被检测到。

build.gradle文件
apply plugin: 'com.android.application'android {compileSdkVersion 29buildToolsVersion "30.0.1"defaultConfig {applicationId "com.example.opeak"minSdkVersion defaultMinSdkVersiontargetSdkVersion 29versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}
}dependencies {implementation fileTree(dir: "libs", include: ["*.jar"])implementation 'androidx.appcompat:appcompat:1.2.0'implementation 'androidx.constraintlayout:constraintlayout:1.1.3'testImplementation 'junit:junit:4.12'androidTestImplementation 'androidx.test.ext:junit:1.1.1'androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'implementation 'com.jaeger.statusbarutil:library:1.4.0'
}

com.jaeger.statusbarutil:library:1.4.0就是前面说的statusbar

打包教程

https://blog.csdn.net/weixin_43373239/article/details/107833035

注意事项
  1. 正式打包生成apk的时候,如果使用的不是同一个签名证书,更新app的时候会出现签名不同,无法安装,只要把原app卸载即可。

将uniapp打包成h5放在安卓webview中(解决uniapp引入第三方地图卡顿问题)相关推荐

  1. 将uni-app打包的H5放在 Android程序中在 webview 显示的两种方法

    将uni-app打包的H5放在 Android程序中在 webview 显示的两种方法 前言 Hash History 完事 前言 之前有个项目要同时做小程序和APP,本着节省时间的想法,研究了下un ...

  2. uniapp打包成h5页面

    1.manifest.json中修改h5配置,运行的基础路径设置为 ./ 表示相对路径 2.hbuilderx上方按钮,点击发行,选择"网站-pc web 或手机h5",按流程操作 ...

  3. uniapp 打包成H5

    1.在hbuilder中工具栏中找到发行->网站pc web或手机h5 一栏 2.点击进去进入h5发行 3.发行后控制台进行编译 生h5包 , 4.发送给后台,让后台部署上服务器(也可以自己部署 ...

  4. uniapp-怎么把项目打包成H5

    如果没有项目的话就自己创建项目uni-app 创建完项目我们会得到一个uniapp框架,可以往里面添加属于自己的功能和需求 但我们把需求和功能都写好,就是发布的时候,通过uniapp 我们可以发布成  ...

  5. h5 android 字体设置,解决因为手机设置字体大小导致h5页面在webview中变形的BUG

    解决因为手机设置字体大小导致h5页面在webview中变形的BUG 首先,我们做了一个H5页面,在各种手机浏览器中打开都没问题.我们采用了rem单位进行布局,通过JS来动态计算网页的视窗宽度,动态设置 ...

  6. Python打包成exe,文件太大问题解决办法

    Python打包成exe,文件太大问题解决办法 原因 解决办法 具体步骤 情况一:初次打包 情况二:再次打包 原因 由于使用pyinstaller打包.py文件时,会把很多已安装的无关库同时打包进去, ...

  7. uniapp 打包成安卓app

    一.window打包前生成安卓的.keystore 证书文件 引用蒋德富的博客 https://www.jiangdefu.com/archives/91 二.在编辑器里面如何打包app 在Hbuil ...

  8. 记录uniapp打包成App

    使用HBuilderX创建一个uniapp项目 打开manifest.json文件,配置一下AppId(登录了HBuilderX能自动获取) 打包成App 使用App云打包打包项目(顶部发行  →  ...

  9. python 编译成exe黑屏_python''外星人入侵''打包成exe遇到的问题和解决办法,闪退,黑屏。...

    利用python写完"外星人入侵之后",尝试打包成exe给自己玩得方便点.然后我在网上查找各种方法.下面按顺序列出. 一:我首先安装好了pyinstaller:在cmd中输入:pi ...

最新文章

  1. linux dd 截文件,Linux使用dd命令快速生成大文件(转)
  2. Selenium3.X 与 Javascript (Nodejs)
  3. 网络营销外包专员浅析从用户角度出发如何完善网络营销外包?
  4. PaaS服务之路漫谈(三):MSA分析
  5. mysql 优化方法_Mysql的优化方法介绍
  6. 照猫画虎,分分钟学会的Matplotlib技巧:反转轴、绘制双轴和定制刻度
  7. vim比vi做的一些改进
  8. Eclipse 设置自动导包
  9. linux 怎么添加path环境变量,Linux下怎么添加和查看PATH环境变量
  10. 鼠标控制视角wasd移动_绝地求生:为什么控制方向键是WASD?网友:就不能是其他键位吗?...
  11. 如何在 ES5 环境下实现一个const ?
  12. IntellijIDEA中maven模块中POM文件不生效
  13. shell编程cp强制覆盖拷贝时仍需确认问题的处理方法
  14. ConnectionString 最简便写法 for MSSQL 2005 EXPRESS
  15. Android CheckBoxPreference设置默认值会触发持久化以及其内部实现逻辑
  16. 使用网关实现把modbus数据存入sql数据库的方案
  17. setlocale 与 mbstowcs 的问题
  18. 香农-范诺算法(Shannon-Fano coding)算法
  19. 2019年IT行业的十大热门岗位
  20. 网络篇 - netty实现高并发安全聊天客户端

热门文章

  1. eclipse如何在包下新建一个包
  2. STAR: A Structure and Texture Aware Retinex Model论文理解
  3. 【转】电脑/服务器各大硬件部件介绍
  4. Linux terminator终端使用方式,个人认为目前最好的终端工具
  5. AlipaySignature.rsaCheckV1返回false,支付宝接口回调失败
  6. dijkstra 算法_数据结构与算法—单源最短路径dijkstra算法
  7. spark入门介绍(菜鸟必看)
  8. 计算机云桌面功能实时监控,云桌面技术在高校计算机实验室中的应用原稿(手机版)...
  9. 快速理解宽带调频中的贝塞尔函数
  10. python 性能并不慢_关于性能:Python多处理队列比pool.map慢