天天看點

android和Vue互動

最近開發一個項目,原本是用的RN開發,後來打算三端統一,後來決定用VUE開發,是以涉及到一些Vue和原生互動的地方,做一下筆記~~

先直接上Vue代碼

<template>
  <div class="page-box">
    <div class="page-content">
        <div class="page-bg">
          <div class="page-login-head">
            <img class="head-img" src="./images/head.png"/>
            <div class="head-text" @click="goLogin">
              {{userMsg}}
            </div>
          </div>
        </div>
        <!-- 我的賬單 -->
        <div class="mine-item mine-item-head" @click="gotoBill">
          <div class="mine-item-content mine-item-content-bottom">
            <div class="left">
              <img class="item-img-size" src="./images/bill.png"/>
              <span class="item-text">我的賬單</span>
            </div>
            <span class="icon-right"></span>
          </div>
        </div>
        <!-- 我的銀行卡 -->
        <div class="mine-item">
          <div class="mine-item-content">
            <div class="left">
              <img src="./images/bankcard.png" style="width:5vw; height:4.1vw"/>
              <span class="item-text">我的銀行卡</span>
            </div>
            <span class="icon-right"></span>
          </div>
        </div>
        <!-- 更改交易密碼 -->
        <div class="mine-item mine-item-head">
          <div class="mine-item-content mine-item-content-bottom">
            <div class="left">
              <img class="item-img-size" src="./images/change_psw.png"/>
              <span class="item-text">更改交易密碼</span>
            </div>
            <span class="icon-right"></span>
          </div>
        </div>
        <!-- 意見與回報 -->
        <div class="mine-item" @click="gotoFeedback">
          <div class="mine-item-content mine-item-content-bottom">
            <div class="left">
              <img style="width:4.8vw; height:5vw" src="./images/opinion.png"/>
              <span class="item-text">意見與回報</span>
            </div>
            <span class="icon-right"></span>
          </div>
        </div>
        <!-- 幫助中心 -->
        <div class="mine-item" @click="gotoHelpCenter">
          <div class="mine-item-content mine-item-content-bottom">
            <div class="left">
              <img style="width:5vw; height:5vw" src="./images/help.png"/>
              <span class="item-text">幫助中心</span>
            </div>
            <span class="icon-right"></span>
          </div>
        </div>
        <!-- 免責聲明 -->
        <div class="mine-item" @click="ocrtest">
          <div class="mine-item-content">
            <div class="left">
              <img style="width:5vw; height:5vw" src="./images/exemption.png"/>
              <span class="item-text">免責聲明</span>
            </div>
            <span class="icon-right"></span>
          </div>
        </div>
        <!-- 關于我們 -->
        <div class="mine-item mine-item-head" @click="gotoAboutUs">
          <div class="mine-item-content">
            <div class="left">
              <img style="width:5vw; height:5vw" src="./images/about.png"/>
              <span class="item-text">關于我們</span>
            </div>
            <span class="icon-right"></span>
          </div>
        </div>
      </div>
      <TabBar></TabBar>
  </div>
</template>

<script>
import TabBar from '@/components/tabBar/TabBar'
import { mapGetters } from 'vuex'
export default {
  components: { TabBar },
  data () {
    return {
      userMsg: '登陸/注冊'
    }
  },
  mounted () {
    this.initView()
  },
  methods: {
    initView () {
      if (this.ifLogin) {
        this.userMsg = this.userInfo.cellphone
      } else {
        this.userMsg = '登陸/注冊'
      }
    },
    goLogin () {
      if (!this.ifLogin) {
        this.$bridge.push({ name: 'login' })
      }
    },
    gotoAboutUs () {
      let params = {
        jumpUrl: 'http://192.168.1.38:8080/aboutus',
        title: '關于我們'
      }
      window.android.callAndroid(JSON.stringify(params))
    },
    gotoFeedback () {
      this.$bridge.push({ name: 'feedback' })
    },
    gotoHelpCenter () {
      this.$bridge.push({ name: 'helpcenter' })
    },
    gotoBill () {
      this.$bridge.push({ name: 'bill' })
    },
    ocrtest () {
      let params = {
        jumpUrl: 'http://192.168.1.38:8080/userinfo',
        title: 'ORC調試'
      }
      window.android.callAndroid(JSON.stringify(params))
    }
  },
  computed: {
    ...mapGetters(['userInfo', 'ifLogin'])
  }
}
</script>

<style  scoped>
  .page-box { position: relative; min-height: 100%; background: #F5F5F5}
  .page-content {
    position: relative;
    z-index: 0;
    padding-bottom :190px;
  }
  .page-bg {
    width: 100%; height: 380px;
    background: linear-gradient(32deg,rgba(46,42,50,1) 0%,rgba(78,65,80,1) 100%);
    display :flex;
    justify-content :center;
    align-items :center;
  }
  .page-box .page-bg .page-login-head {
    display :flex;
    flex-direction :column;
    align-items :center;
  }
  .page-box .page-bg .page-login-head .head-img {
    width: 124px; height: 124px;
  }
  .page-box .page-bg .page-login-head .head-text{
    margin-top :15px;
    font-size :28px;
    color :#FFFFFF;
  }
  .mine-item-head {
    margin-top :20px;
  }
  .mine-item {
    background-color :#FFFFFF;
    height :100px;
    width :100%
    padding-left :39px;
  }
  .mine-item .mine-item-content-bottom {
    border-bottom-width :1px;
    border-style :solid;
    border-bottom-color :#DDDDDD;
  }
  .mine-item .mine-item-content {
    display :flex;
    height :100px;
    width :100%
    align-items :center;
    justify-content :space-between;
  }
  .mine-item .left{
    display :flex;
  }
  .item-text {
    font-size :28px;
    color :#333333;
    margin-left :20px;
    align-self :center;
  }
  .item-img-size {
    width :31px;
    height :38px;
  }

  .icon-right {
    width: 36px; height: 36px;
    background: url('./images/arrow_grey_right.png') no-repeat center center;
    background-size: 19px 34px;
    margin-right :30px;
  }
</style>
           

這是一個個人中心完整VUE界面的代碼,包括樣式,點選事件,重點看這裡就行

android和Vue互動

vue和原生互動的原理和Html裡面js和原生互動一樣,都是通過js代碼來實作,都需要把原生方法挂載到window上面

是以這裡,這裡的params是需要傳遞給原生的資料,JSON.stringify(params)的作用是,必須把資料轉為json格式,原生才能收到,否則接收不到,其中callAndroid()是原生的方法,window後面的android是原生代碼裡面申明的一個标志

原生代碼如下

public class JsBridgeForMain {
    private static final String TAG = "JsBridgeForMain";
    private Handler deliver = new Handler(Looper.getMainLooper());
    private AgentWeb agent;
    private Context context;

    private OnNativeDataGetInterface mOnNativeDataGetInterface;

    public JsBridgeForMain(AgentWeb agent, Context context) {
        this.agent = agent;
        this.context = context;
    }

    public JsBridgeForMain(AgentWeb agent, Context context, OnNativeDataGetInterface onNativeDataGetInterface) {
        this.agent = agent;
        this.context = context;
        mOnNativeDataGetInterface = onNativeDataGetInterface;
    }

    @JavascriptInterface
    public void showMsg(final String obj) {
        Log.e(TAG, "showMsg: " + obj);
    }

    @JavascriptInterface
    public void jumpAndroid(final String obj) {
        Log.e(TAG, "jumpAndroid: " + obj);
        final Map<String, Object> params = AppUtils.getMap(obj);
        assert params != null;
        context.startActivity(new Intent(context, OcrCallbackActivity.class)
                .putExtra(PrefKeys.EXTRA_URL, params.get("href").toString()));
    }

    @JavascriptInterface
    public void callAndroid(final String obj) {
        deliver.post(new Runnable() {
            @Override
            public void run() {
                final Map<String, Object> params = AppUtils.getMap(obj);
                assert params != null;
                Log.e(TAG, "name: " + params);
                if ("OCR".equals(params.get("name"))) {
                    Gson gson = new Gson();
                    String jsonString = gson.toJson(params.get("data")).replace("\\", "");
                    jsonString = jsonString.substring(1, jsonString.length() - 1);
                    OcrEntity ocrEntity = gson.fromJson(jsonString, OcrEntity.class);
                    OcrCallbackActivity.msgId = params.get("msgId").toString();
                    if (mOnNativeDataGetInterface != null)
                        mOnNativeDataGetInterface.onDataGot(ocrEntity);
                    Log.e(TAG, "ocrEntity: " + params);
                }
                if ("phoneContact".equals(params.get("name"))) {
                    OcrCallbackActivity.msgId = params.get("msgId").toString();
                    mOnNativeDataGetInterface.onAddressCalled();
                }
                if ("GPS".equals(params.get("name"))){
                    OcrCallbackActivity.msgId = params.get("msgId").toString();
                    mOnNativeDataGetInterface.onGpsCalled();
                }
                if ("GPSStatus".equals(params.get("name"))){
                    OcrCallbackActivity.msgId = params.get("msgId").toString();
                    mOnNativeDataGetInterface.onGpsStatus();
                }
            }
        });
    }
}
           

其中原生調用JS方法代碼如下

Map<String, String> contactMap = new HashMap<>();
                contactMap.clear();
                contactMap.put("phone", phoneNum);
                contactMap.put("msgId", msgId);
                contactMap.put("name", contactName);
                Gson gson = new Gson();
                String contactPersonData = gson.toJson(contactMap);
                agentWeb.getJsAccessEntrace().quickCallJs("webViewBridge.callback_('" + contactPersonData + "')");
           

我使用的一個webview的中間件名字叫做AgentWeb,具體使用方法可以看github,

這裡的

webViewBridge.callback_('" + contactPersonData + "')" 為js中的方法,contactPersonData 為原生的json資料
      

webViewBridge.callback_是我們自己封裝的一個vue的連接配接橋可以忽略也可以吧這部分直接改成js裡具體的方法比如前面vue代碼中method裡面的任意一個方法