发布日期:2022-9-8 更新日期: 2022-9-8文章字数 0阅读时长:0分钟

类型
Post
状态
Published
日期
Sep 8, 2022
文章链接
build-an-android-shell-using-webview-from-scratch
概览
折腾项目的时候,难免会玩到安卓,虽然我是web端的前端开发,而且多少会一点安卓原生,但是折腾起来太过麻烦,花费的精力和收益不成正比,于是还是决定自己手撸一个安卓外壳,内嵌webview,通过开发h5的方式达到开发安卓app的目的。
标签
Android
App
分类
技术分享
图标
密码
创建时间
Sep 8, 2022 06:17 PM
最近更新时间
Sep 8, 2022 06:27 PM
折腾项目的时候,难免会玩到安卓,虽然我是web端的前端开发,而且多少会一点安卓原生,但是折腾起来太过麻烦,花费的精力和收益不成正比,于是还是决定自己手撸一个安卓外壳,内嵌webview,通过开发h5的方式达到开发安卓app的目的。

安装安卓开发环境

下载并安装 android studio
notion image
新建项目
notion image
选择默认即可
notion image
设置新项目的必要配置
  • Name:应用名
  • Package Name:包名
  • Save Location:项目保存路径
  • Language:项目使用的编程语言
  • Minimum SDK:最低兼容 SDK 版本
notion image

开发安卓程序

新建一个MWebView控件

新建文件 controls/MWebView.java
package com.jsmiao.webapp.controls; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.os.Build; import android.util.AttributeSet; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; public class MWebView extends WebView { private Activity mActivity; public MWebView(Context context) { super(context); init(); } public MWebView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public MWebView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } /** * 设置要选择图片的activity * * @param activity */ public void setActivity(Activity activity) { this.mActivity = activity; } @SuppressLint("SetJavaScriptEnabled") private void init() { WebSettings webSettings = getSettings(); // 设置 // 开启JavaScript支持 webSettings.setJavaScriptEnabled(true); // 让Webivew支持<meta>标签的viewport属性 webSettings.setUseWideViewPort(true); // 是否启动概述模式浏览界面,当页面宽度超过WebView显示宽度时,缩小页面适应WebView。默认false webSettings.setLoadWithOverviewMode(true); /** * 基于WebView导航的类型使用缓存:正常页面加载会加载缓存并按需判断内容是否需要重新验证。 * 如果是页面返回,页面内容不会重新加载,直接从缓存中恢复。setCacheMode允许客户端根据指定的模式来 * 使用缓存。 * LOAD_DEFAULT 默认加载方式 * LOAD_CACHE_ELSE_NETWORK 按网络情况使用缓存 * LOAD_NO_CACHE 不使用缓存 * LOAD_CACHE_ONLY 只使用缓存 */ webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); // 是否存储页面DOM结构,默认false。 webSettings.setDomStorageEnabled(true); // 是否允许访问WebView内部文件,默认true webSettings.setAllowFileAccess(true); // 是否允许获取WebView的内容URL ,可以让WebView访问ContentPrivider存储的内容。 默认true webSettings.setAllowContentAccess(true); // 设置页面的编码格式,默认UTF-8 webSettings.setDefaultTextEncodingName("utf-8"); // 是否允许运行在一个URL环境中的JavaScript访问来自其他URL环境的内容 webSettings.setAllowFileAccessFromFileURLs(false); // 是否允许运行在一个file schema URL环境下的JavaScript访问来自其他任何来源的内容,包括其他file schema URLs webSettings.setAllowUniversalAccessFromFileURLs(false); /** * Webview在安卓5.0之前默认允许其加载混合网络协议内容 * 在安卓5.0之后,默认不允许加载http与https混合内容,需要设置webview允许其加载混合网络协议内容 */ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); //测试打开 WebView.setWebContentsDebuggingEnabled(true); } setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { //判断url是否以http或https开头,是则不消费事件 if (url.startsWith("http:") || url.startsWith("https:")) { return false; } return true; } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); } }); setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); } @Override public void onReceivedTitle(WebView view, String title) { super.onReceivedTitle(view, title); } }); } }
notion image

设置Layout布局

layout目录主要用于存放定义用户界面布局的 XML 文件。有些类似于web端的html,不过更为复杂。
修改 app/res/layout/activity_main.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"> <com.jsmiao.webapp.controls.MWebView android:id="@+id/mWebView" android:layout_width="match_parent" android:layout_height="match_parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
看不到代码的,需要调整到Code
notion image

修改MainActivity文件

Activity 类是 Android 应用的关键组件,而 Activity 的启动和组合方式则是该平台应用模型的基本组成部分。
package com.jsmiao.webapp; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import com.jsmiao.webapp.controls.MWebView; public class MainActivity extends AppCompatActivity { private MWebView mWebView; // webView 控件 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 获取控件 mWebView = (MWebView) findViewById(R.id.mWebView); mWebView.setActivity(this); String url; // 设置url地址 url = "https://blog.jsmiao.com"; // 加载url mWebView.loadUrl(url); } }
notion image

添加联网权限

选择 app/minifests/AndroidMinifest.xml文件,在 application标签前添加一个 uses-permission标签来声明应用的网络访问权限,最后保存。
<!-- 访问网络的权限 --> <uses-permission android:name="android.permission.INTERNET" />
notion image

运行调试

连接手机,选择打开调试(也可以安装虚拟机)
notion image
不出意外的话,结果如下:
notion image

打包

选择打包
notion image
选择APK
notion image
新建一个
notion image
选择文件夹
notion image
配置密钥文件
notion image
然后输入这个jks和别名的一些相关信息,上方的商店密码和别名密码可以设置为一样的,这样便于记忆,只不过安全系数就降低了。
notion image
记住密码
notion image
选择release 点击finish 等待打包
notion image
打包好之后,将会在文件夹中看到你打包的app了
notion image
以上,我们想要的基本功能就已经完成了,以下功能可以根据需要进行拓展。

隐藏标题栏

themes.xml 中增加代码:
<style name="Theme.Webapp.NoActionBar"> <item name="windowActionBar">false</item> <item name="windowNoTitle">true</item> </style>
notion image
AndroidManifest.xml 文件中使用该主题
notion image
重启即可
notion image

设置状态栏

修改状态栏颜色

themes.xml 中增加代码:
<style name="Theme.Webapp.NoActionBar"> ... <item name="android:statusBarColor">自己想要的颜色</item> </style>
notion image
notion image

隐藏状态栏

MainActivityonCreate 方法内增加代码:
// 设置为全屏(隐藏状态栏) getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
需要加在 setContentView 方法执行的前面
notion image
重新运行,状态栏就没有了,页面为全屏状态(刘海屏还是会有个黑条)
notion image

接管返回键

MainActivityonCreate 方法内修改代码:
private WebView webView = null; // 创建 WebView 实例时保存到 this.webView 中 /* * 重写onBackPressed函数 接管返回键 */ @Override public void onBackPressed() { if (this.webView.canGoBack()) { this.webView.goBack(); } else { super.onBackPressed(); } }

设置可http明文传输

从Android 9.0(API级别28)开始,默认情况下限制了明文流量的网络请求,对未加密流量不再信任,直接放弃请求,因此http的url均无法在webview中加载,https 不受影响。
AndroidManifest.xml 文件的 application 标签内,加入属性:
android:usesCleartextTraffic="true"
notion image

设计一个程序,模拟红绿灯切换 设计一个程序,模拟红绿灯切换

抖音《渡一Web前端学习频道》袁老师讲的一个题目,虽然东西不多,但是受益匪浅,很多东西都是我没想到的,所以打算记录一下,方便自己积累使用。


分享几个 Notion 免费获取 Icons 的网站 分享几个 Notion 免费获取 Icons 的网站

图标在notion中总是显得很活泼,这里分享几个能免费获取到图标的网站,几乎你所想要的icon都能满足