安卓webApp模板

安卓webApp开发模板

最近团队需要做一个安卓app,使用原生的android开发的话,开发周期会比较长,考虑到时间因素团队成员考虑采用webapp的形式来开发,这样门槛会相对来说也会低一些。

开发工具:

  • Android Studio

具体思路如下:

同时这里采用了快捷菜单来设置请求的URL,预计效果如下(安卓系统得在7.1以上才支持):

总的来说这样的开发门槛很低,对于零基础的安卓开发人员也很容易上手,具体的代码也不难,主要是安卓的布局是xml格式的,对于习惯了html的朋友来说,初始会感到不习惯。

接下来我们聊一下具体的代码实现细节:

整体项目层次结构如下:

 

配置文件:AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.mywebviewapp" android:versionCode="1"
    android:versionName="1.0">
​
    <uses-permission android:name="android.permission.INTERNET" />
​
    <application
        android:allowBackup="true"
        android:networkSecurityConfig="@xml/network_security_config"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
​
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <!--add static shortcut注意把这个都加到主页面上,至于下面这个类 我们在xml/static_shortcut下面已经配置了/-->
            <meta-data android:name="android.app.shortcuts"
                android:resource="@xml/static_shortcut" />
        </activity>
        <!--  注意这里有结果active就得注册几个,不注册的话 如果要跳转到该active则会出现闪退现象 -->
    <activity android:name=".WebSettingActivity">
    </activity>
    </application>
​
</manifest>

请注意:

使用webview一定要给联网权限

<uses-permission android:name="android.permission.INTERNET" />

配置静态快捷菜单

<!--add static shortcut注意把这个都加到主页面上,至于下面这个类 我们在xml/static_shortcut下面已经配置了/-->
<meta-data android:name="android.app.shortcuts"
    android:resource="@xml/static_shortcut" />

静态快捷键菜单配置文件xml/static_shortcut.xml

<?xml version="1.0" encoding="utf-8"?>
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
    <!--设置UrL-->
    <shortcut
        android:enabled="true"
        android:icon="@drawable/ic_shortcut_search"
        android:shortcutDisabledMessage="@string/lable_shortcut_static_search_disable"
        android:shortcutId="shortcut_id_search"
        android:shortcutLongLabel="@string/lable_shortcut_static_search_long"
        android:shortcutShortLabel="@string/lable_shortcut_static_search_short">
        <intent
            android:action="android.intent.action.VIEW"
            android:targetClass="com.example.mywebviewapp.WebSettingActivity"
            android:targetPackage="com.example.mywebviewapp" />
        <!--当前只有这个分类-->
        <categories android:name="android.shortcut.conversation" />
    </shortcut>
</shortcuts>

主布局页:activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
​
​
​
    <WebView
        android:id="@+id/webView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentTop="false"
        android:layout_centerHorizontal="true"
        android:layout_marginHorizontal="8dp" />
​
</LinearLayout>

设置请求URL:activity_web_setting.xml

<RelativeLayout 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"
    android:paddingBottom="16dp"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:paddingTop="16dp"
    tools:context=".WebSettingActivity" >
​
    <Button
        android:id="@+id/btnCancel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:onClick="myClickBtnBack"
        android:text="返回" />
​
    <Button
        android:id="@+id/btnSave"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/btnCancel"
        android:layout_alignBottom="@+id/btnCancel"
        android:layout_alignParentRight="true"
        android:onClick="myClickBtnSave"
        android:text="保存" />
​
    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/btnCancel"
        android:layout_below="@+id/btnCancel"
        android:layout_marginTop="29dp"
        android:text="Url:"
        android:textAppearance="?android:attr/textAppearanceMedium" />
​
    <EditText
        android:id="@+id/txtUrl"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/textView1"
        android:layout_alignBottom="@+id/textView1"
        android:layout_alignRight="@+id/btnSave"
        android:layout_toRightOf="@+id/textView1"
        android:ems="10" >
​
        <requestFocus />
    </EditText>
</RelativeLayout>

主入口类:MainActivity.class:

package com.example.mywebviewapp;
​
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.KeyEvent;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
​
import java.util.concurrent.ExecutionException;
​
public class MainActivity extends Activity {
​
    private WebView webView;
    private ProgressDialog progressBar;
​
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
​
​
        //获取webview
        webView = (WebView) findViewById(R.id.webView1);
​
        // 获取触摸焦点
        webView.requestFocus();
        //设置webview禁止缓存  方便调试
        webView.getSettings().setCacheMode(webView.getSettings().LOAD_NO_CACHE);
        // 取消滚动条
        webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
        // 构建缩放控制
        webView.getSettings().setBuiltInZoomControls(false);
        // 设置支持缩放
        webView.getSettings().setSupportZoom(false);
​
        //设置webview支持JS
        webView.getSettings().setJavaScriptEnabled(true);
        /*
         * 用webview打开指定网页
         * 网址取保存在SharedPreferences的参数
         */
        progressBar = new ProgressDialog(this);
        progressBar.setMessage("正在加载中......");
        progressBar.setCancelable(true);
​
        webView.setWebViewClient(
                new WebViewClient() {
                    public boolean shouldOverrideUrlLoading(WebView view, String url) {
                        view.loadUrl(url);
                        return true;
                    }
​
                    //等待进度条
                    public void onPageStarted(WebView view, String url, Bitmap favicon) {
                        //Log.i(TAG, "Started loading URL: " +url);
                        //progressBar = ProgressDialog.show(MainActivity.this, "title", "message",true);
                        progressBar.show();
                    }
​
                    public void onPageFinished(WebView view, String url) {
                        //Log.i(TAG, "Finished loading URL: " +url);
                        if (progressBar.isShowing()) {
                            progressBar.dismiss();
                        }
                    }
                });
​
​
        SharedPreferences userInfo = getSharedPreferences("user_info", 0);
        if (userInfo.getString("url", "").toString().equals("")) {
            //页面跳转至WebSettingActivity
            Intent intent = new Intent(MainActivity.this, WebSettingActivity.class);
            startActivity(intent);
            return;
        }
        try {
            if (!new Connection().execute(userInfo.getString("url", "").toString()).get()) {
                linkWebSettingActive();
                return;
            }
        } catch (ExecutionException e) {
            linkWebSettingActive();
            e.printStackTrace();
        } catch (InterruptedException e) {
            linkWebSettingActive();
            e.printStackTrace();
        }
​
        //布局中设置的方向是horizontal,设置成LayoutParams(0,heignt,weight) 即width需要设置权重就在width处为0
        //布局中设置的方向是vertical,设置成LayoutParams(width,0,weight) 即heignt需要设置权重就在heignt处为0
        //webView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        try {
            webView.loadUrl(userInfo.getString("url", "").toString());
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
​
​
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        return false;
    }
​
    private void linkWebSettingActive() {
        //构建一个Toast,相当于网页的alert。  makeText(Context 上下文对象,String字符串,显示延迟的时间);
        Intent intent = new Intent(MainActivity.this, WebSettingActivity.class);
        startActivity(intent);
        Toast ts = Toast.makeText(MainActivity.this, "当前请求链接不可达,请重新输入新的请求链接!", Toast.LENGTH_LONG);
        ts.show();
    }
}

由于安卓默认在主线程内不允许发生其他请求(会提示NetworkOnMainThreadException),所以要想检查URL是否可用,我们需要异步非阻塞的方式来进行,这样我们的安卓app响应也会更快。

增加一个connection.class:

package com.example.mywebviewapp;
​
import android.os.AsyncTask;
​
import java.net.HttpURLConnection;
import java.net.URL;
​
import javax.net.ssl.HttpsURLConnection;
​
public class Connection extends AsyncTask<String, Boolean, Boolean> {
​
    private boolean checkUrlIsAvailable(String urlStr) {
        try {
            HttpsURLConnection httpsCon=null;
            HttpURLConnection httpCon=null;
            URL url = new URL(urlStr);
            if(urlStr.contains("https"))
            {
                httpsCon = (HttpsURLConnection) url.openConnection();
                int code = httpsCon.getResponseCode();
                if (code != 200) {
                    httpsCon.disconnect();
                    return false;
                }
                httpsCon.disconnect();
            }
            else
            {
                httpCon = (HttpURLConnection) url.openConnection();
                int code = httpCon.getResponseCode();
                if (code != 200) {
                    httpCon.disconnect();
                    return false;
                }
                httpCon.disconnect();
            }
​
​
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
​
​
    @Override
    protected Boolean doInBackground(String... urls) {
        return checkUrlIsAvailable(urls[0]);
    }
}

设置动态链接:WebSettingActivity.class

package com.example.mywebviewapp;
​
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.view.View;
import android.widget.EditText;
​
public class WebSettingActivity extends Activity {
​
    private EditText txtUrl = null;
​
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_web_setting);
​
        txtUrl = (EditText) findViewById(R.id.txtUrl);
        SharedPreferences userInfo = getSharedPreferences("user_info", 0);
        txtUrl.setText(userInfo.getString("url", ""));
    }
​
    /*
     * 保存按钮事件
     */
    public void myClickBtnSave(View v) {
        /*
         * 将表单结果保存到SharedPreferences中
         */
        SharedPreferences userInfo = getSharedPreferences("user_info", 0);
        userInfo.edit().putString("url", txtUrl.getText().toString()).commit();
​
        Intent intent = new Intent(WebSettingActivity.this, MainActivity.class);
        startActivity(intent);
    }
​
    /*
     * 返回按钮事件
     */
    public void myClickBtnBack(View v) {
        finish();     //只是推向后台
    }
}

解决http链接默认不能访问的问题network_security_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <!--Set application-wide security config using base-config tag.-->
    <base-config cleartextTrafficPermitted="true"/>
</network-security-config>

这里我用的安卓模拟器是:夜神模拟器,为什么使用它呢,主要是觉得android studio中的模拟器太重(当然这是个人拙见),另外如果可以的话,我们可以直接在真机上来debug我们的webapp,这需要开启设备的【USB调试】,不同设备的开启方式不同。

具体调试方式可以参考:谷歌远程调试的文档(可能需要翻墙)

参考文章:

安卓的快捷菜单

App Shortcuts的官方文档: App Shortcuts

Exploring Android Nougat 7.1 App Shortcuts

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值