欢迎来到十九分快乐的博客

生死看淡,不服就干。

10. 社交模块 - 好友邀请,推广应用

社交模块

邀请好友 - 推广应用

主要就是为了实现推广流程。

业务逻辑流程图

客户端提供邀请好友的展示页面

  1. 用户个人中心user.html, 实现点击"邀请好友"打开邀请好友invite.html页面,代码:
<!DOCTYPE html>
<html>
<head>
	<title>用户中心</title>
	<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
	<meta charset="utf-8">
	<link rel="stylesheet" href="../static/css/main.css">
	<script src="../static/js/vue.js"></script>
	<script src="../static/js/axios.js"></script>
	<script src="../static/js/uuid.js"></script>
	<script src="../static/js/v-avatar-2.0.3.min.js"></script>
  <script src="../static/js/main.js"></script>
</head>
<body>
	<div class="app user" id="app">
		<div class="bg">
      <img src="../static/images/bg0.jpg">
    </div>
		<img class="back" @click="back" src="../static/images/user_back.png" alt="">
		<img class="setting" @click="goto_settings" src="../static/images/setting.png" alt="">
		<div class="header">
			<div class="info">
				<div class="avatar">
					<img class="avatar_bf" src="../static/images/avatar_bf.png" alt="">
					<!-- <img class="user_avatar" :src="user_data.avatar" alt=""> -->
					<div class="user_avatar">
						<v-avatar v-if="user_data.avatar" :src="user_data.avatar" :size="56" :rounded="true"></v-avatar>
						<v-avatar v-else-if="user_data.nickname" :username="user_data.nickname" :size="56" :rounded="true"></v-avatar>
						<v-avatar v-else :username="user_data.id" :size="56" :rounded="true"></v-avatar>
					</div>
					<img class="avatar_border" src="../static/images/avatar_border.png" alt="">
				</div>
				<p class="user_name">{{user_data.nickname}}</p>
			</div>
			<div class="wallet">
				<div class="balance">
					<p class="title"><img src="../static/images/money.png" alt="">钱包</p>
					<p class="num">{{game.money_format(user_data.money)}}</p>
				</div>
				<div class="balance">
					<p class="title"><img src="../static/images/integral.png" alt="">果子</p>
					<p class="num">{{game.money_format(user_data.credit)}}</p>
          <!-- <p class="num">99,999.00</p> -->
          <!-- <p class="num">1,999,999.00</p> -->
				</div>
			</div>
			<div class="invite" @click="open_invite_page">
				<img class="invite_btn" src="../static/images/invite.png" alt="">
			</div>
		</div>
		<div class="menu">
				<div class="item">
					<span class="title">我的主页</span>
					<span class="value">查看</span>
				</div>
				<div class="item" @click="open_friend_list">
					<span class="title">好友列表</span>
					<span class="value">查看</span>
				</div>
				<div class="item">
					<span class="title">收益明细</span>
					<span class="value">查看</span>
				</div>
				<div class="item">
					<span class="title">实名认证</span>
					<span class="value">未认证</span>
				</div>
				<div class="item">
					<span class="title">问题反馈</span>
					<span class="value">去反馈</span>
				</div>
			</ul>
		</div>
	</div>
	<script>
	apiready = function(){
    var game = new Game("../static/mp3/bg1.mp3");
    Vue.prototype.game = game;
		new Vue({
			el:"#app",
			data(){
				return {
					user_data: {},
				}
			},
			created(){
				  let token = this.game.getfs("access_token") || this.game.getdata("access_token");
          this.user_data = this.game.get_user_by_token(token);
					this.game.print(this.user_data);
					this.listen();
			},
			methods:{
					listen(){
	          // 监听头像发生变化的通知
	          this.listen_update_avatar();
						// 监听昵称发生变化的通知
						this.listen_update_nickname();
	        },
	        listen_update_avatar(){
	          // 监听头像更新的通知
	          api.addEventListener({
	              name: 'update_avatar_success',
	          }, (ret, err)=>{
	              this.get_user_data();
	          });
	        },
					listen_update_nickname(){
						//监听昵称更新的通知
						api.addEventListener({
								name: 'update_nickname_success'
						}, (ret, err)=>{
								this.get_user_data();
						});
					},
					get_user_data(){
	          let token = this.game.getfs("access_token") || this.game.getdata("access_token");
	          this.user_data = this.game.get_user_by_token(token);
	          this.game.print(this.user_data);
	        },
				  back(){
            // 返回首页
            this.game.closeWin();
          },
					goto_settings(){
						// 打开配置页面
						this.game.openFrame("settings","settings.html");
					},
					open_friend_list(){
						// 打开好友列表
						this.game.openFrame("friends","friends.html");
						this.game.openFrame("friend_list","friend_list.html",null,{
							x: 0,             // 左上角x轴坐标
							y: 194,           // 左上角y轴坐标
							w: 'auto',        // 当前帧页面的宽度, auto表示满屏
							h: 'auto'         // 当前帧页面的高度, auto表示满屏
						});
					},
					open_invite_page(){
						// 邀请好友页面
						this.game.openFrame("invite","invite.html",null,null,{
	            type: "push", //动画类型(详见动画类型常量)
	            subType: "from_top", //动画子类型(详见动画子类型常量)
	            duration: 300 //动画过渡时间,默认300毫秒
	          });
					}
			}
		});
	}
	</script>
</body>
</html>
  1. 邀请好友页面html/invite.html,代码:
<!DOCTYPE html>
<html>
<head>
	<title>邀请好友</title>
	<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
	<meta charset="utf-8">
	<link rel="stylesheet" href="../static/css/main.css">
	<script src="../static/js/vue.js"></script>
	<script src="../static/js/axios.js"></script>
  <script src="../static/js/uuid.js"></script>
	<script src="../static/js/main.js"></script>
</head>
<body>
	<div class="app frame avatar" id="app">
    <div class="box">
      <p class="title">邀请好友</p>
      <img class="close" @click="back" src="../static/images/close_btn1.png" alt="">
      <div class="content">
				<img class="invite_code" src="../static/images/code.jpg" alt="">
			</div>
			<p class="invite_tips">长按保存图片到相册</p>
    </div>
	</div>
	<script>
	apiready = function(){
    var game = new Game("../static/mp3/bg1.mp3");
    // 在 #app 标签下渲染一个按钮组件
    Vue.prototype.game = game;
		new Vue({
			el:"#app",
			data(){
				return {

				}
			},
			methods:{
        back(){
          this.game.closeFrame();
        },
			}
		});
	}
	</script>
</body>
</html>

  1. 添加代码样式: static/css/main.css,代码:
.invite_code{
  width: 14rem;
  height: 14rem;
  position: absolute;
  left: 7rem;
  top: 11rem;
}
.invite_tips{
  position: absolute;
  left: 7rem;
  top: 26.4rem;
  text-align: center;
  color: #fff;
  font-size: 1.5rem;
}

代码逻辑编写

服务端提供基于二维码生成邀请码的接口

flask-qrcode, 文档: https://marcoagner.github.io/Flask-QRcode/

  1. 安装二维码生成模块
pip install flask-qrcode
  1. 项目入口文件初始化模块 ,application/__init__.py,代码:
import os

from flask import Flask
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy
from flask_redis import FlaskRedis
from flask_session import Session
from flask_jsonrpc import JSONRPC
from faker import Faker
from celery import Celery
from flask_jwt_extended import JWTManager
from flask_admin import Admin
from flask_babelex import Babel
from xpinyin import Pinyin
from flask_qrcode import QRcode

from application.utils.config import init_config
from application.utils.logger import Log
from application.utils.commands import load_commands
from application.utils.bluerprint import register_blueprint, path, include, api_rpc
from application.utils import message, code
from application.utils.unittest import BasicTestCase
from application.utils.OssStore import OssStore

# 终端脚本工具初始化
manager = Manager()

# SQLAlchemy初始化
db = SQLAlchemy()

# redis数据库初始化
# - 1.默认缓存数据库对象,配置前缀为REDIS
redis_cache = FlaskRedis(config_prefix='REDIS')
# - 2.验证相关数据库对象,配置前缀为CHECK
redis_check = FlaskRedis(config_prefix='CHECK')
# - 3.验证相关数据库对象,配置前缀为SESSION
redis_session = FlaskRedis(config_prefix='SESSION')

# session储存配置初始化
session_store = Session()

# 自定义日志初始化
logger = Log()

# 初始化jsonrpc模块
jsonrpc = JSONRPC()

# 初始化随机生成数据模块faker
faker = Faker(locale='zh-CN') # 指定中文

# 初始化异步celery
celery = Celery()

# jwt认证模块初始化
jwt = JWTManager()

# 阿里云对象存储oss初始化
oss = OssStore()

# admin后台站点初始化
admin = Admin()

# 国际化和本地化的初始化
babel = Babel()

# 文字转拼音初始化
pinyin = Pinyin()

# 二维码生成模块初始化
qrcode = QRcode()

# 全局初始化
def init_app(config_path):
    """全局初始化 - 需要传入加载开发或生产环境配置路径"""
    # 创建app应用对象
    app = Flask(__name__)

    # 当前项目根目录
    app.BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

    # 开发或生产环境加载配置
    init_config(app, config_path)

    # SQLAlchemy加载配置
    db.init_app(app)

    # redis加载配置
    redis_cache.init_app(app)
    redis_check.init_app(app)
    redis_session.init_app(app)

    """一定先加载默认配置,再传入APP加载session对象"""
    # session保存数据到redis时启用的链接对象
    app.config["SESSION_REDIS"] = redis_session
    # session存储对象加载配置
    session_store.init_app(app)

    # 为日志对象加载配置
    log = logger.init_app(app)
    app.log = log

    # json-rpc加载配置
    jsonrpc.init_app(app)
    # rpc访问路径入口(只有唯一一个访问路径入口),默认/api
    jsonrpc.service_url = app.config.get('JSON_SERVER_URL', '/api')
    jsonrpc.enable_web_browsable_api = app.config.get("ENABLE_WEB_BROWSABLE_API",False)
    app.jsonrpc = jsonrpc

    # 自动注册蓝图
    register_blueprint(app)

    # 加载celery配置
    celery.main = app.name
    celery.app = app
    # 更新配置
    celery.conf.update(app.config)
    # 自动注册任务
    celery.autodiscover_tasks(app.config.get('INSTALL_BLUEPRINT'))

    # jwt认证加载配置
    jwt.init_app(app)

    # faker作为app成员属性
    app.faker = faker

    # 注册模型,创建表
    with app.app_context():
        db.create_all()

    # 阿里云存储对象加载配置
    oss.init_app(app)

    # admin后台站点加载配置
    admin.name = app.config.get('FLASK_ADMIN_NAME') # 站点名称
    admin.template_mode = app.config.get('FLASK_TEMPLATE_MODE') # 使用的模板
    admin.init_app(app)

    # 国际化和本地化加载配置
    babel.init_app(app)

    # 二维码模块加载配置
    qrcode.init_app(app)

    # 终端脚本工具加载配置
    manager.app = app

    # 自动注册自定义命令
    load_commands(manager)

    return manager
  1. 视图提供生成二维码图片 : users/views.py,代码:
from flask_jwt_extended import jwt_required
from flask import make_response, current_app, request

from application import qrcode
# 引入装饰器
from application.utils import decorator

# 基于二维码模块生成邀请码
@jwt_required()
@decorator.get_user_object
def invite_code(user):
    '''
    基于二维码模块生成邀请码
    :param user: 装饰器通过token获取的用户模型对象
    :return:
    '''
    # 获取用户头像,如果没有设置头像,则默认为项目配置中的默认头像
    if user.avatar:
        avatar = user.avatar
    else:
        avatar = current_app.config.get('DEFAULT_INVITE_LOGO')

    # 服务端访问地址,从配置文件中提取
    # 判断是否为开发环境
    if current_app.config.get('DEBUG'):
        SERVER_URL = 'DEV_SERVER_URL'
    else:
        SERVER_URL = 'SERVER_URL'
    # 获取服务端访问地址,如果没有就用请求地址
    # print(request.host_url[:-1]) # http://0.0.0.0:5000
    server_url = current_app.config.get(SERVER_URL, request.host_url[:-1])

    # 编写邀请码中携带的地址
    invite_url = server_url + '/users/invite?type=invite&uid=%s'%user.id

    # 生成二维码图片数据
    # qrcode基于mode=raw生成的图片数据格式是 BytesIO, flask返回图片需要bytes类型数据
    # 所以需要把BytesIO通过getvalue方法转成bytes
    image = qrcode.qrcode(invite_url, mode='raw', box_size=16, icon_img=avatar)
    image = image.getvalue()

    response = make_response(image)
    # 设置响应头类型
    response.headers['Content-Type'] = 'image/png'

    return response
  1. 开发环境配置文件 application/settings/dev.py,配置代码:
"""邀请二维码"""
# 默认LOGO
DEFAULT_INVITE_LOGO = "https://mofang32.oss-cn-beijing.aliyuncs.com/680cda4f-2868-4abf-95b0-6eb5240bfd39.jpeg"
# 服务端的访问地址
SERVER_URL = "http://www.mofang.com:5000"
DEV_SERVER_URL = "http://192.168.19.46:5000" # 开发环境使用主机IP地址
  1. 路由: user/urls.py,代码:
from application import path, api_rpc
# 引入当前蓝图应用视图 , 引入rpc视图
from . import views, api

# 蓝图路径与函数映射列表
urlpatterns = [
    path('invite.png', views.invite_code), # 生成邀请码,推广应用
]

# rpc方法与函数映射列表[rpc接口列表]
apipatterns = [
    api_rpc('check_mobile', api.check_mobile),
    api_rpc('register', api.register),
    api_rpc('login', api.login),
    api_rpc('refresh', api.refresh_token), # 刷新access_token值
    api_rpc('update_avatar', api.update_avatar), # 更新头像
    api_rpc('update_nickname', api.update_nickname), # 更新昵称
    api_rpc('update_mobile', api.update_mobile), # 更新手机号
    api_rpc('update_password', api.update_password), # 更新登录密码
    api_rpc('update_pay_password', api.update_pay_password), # 更新交易密码
    api_rpc('get_apply_friend_history', api.get_apply_friend_history), # 获取好友申请列表
    api_rpc('search_user_info', api.search_user_info), # 搜索用户信息
    api_rpc('apply_friend', api.apply_friend), # 添加用户好友申请记录
    api_rpc('add_friend', api.add_friend), # 添加用户好友关系记录
    api_rpc('cancel_apply_friend', api.cancel_apply_friend), # 用户取消自己申请的好友记录
    api_rpc('get_friend_list', api.get_friend_list), # 获取好友列表
]

  1. 获取好友邀请码访问地址:
http://0.0.0.0:5000/users/invite.png?jwt=(access_token值)

客户端获取好友邀请码

  1. 获取好友邀请码, 并且长按保存图片到相册中 ,html/invite.html,代码:
<!DOCTYPE html>
<html>
    <head>
        <title>邀请好友</title>
        <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
        <meta charset="utf-8">
        <link rel="stylesheet" href="../static/css/main.css">
        <script src="../static/js/vue.js"></script>
        <script src="../static/js/axios.js"></script>
        <script src="../static/js/uuid.js"></script>
        <script src="../static/js/main.js"></script>
    </head>
    <body>
        <div class="app frame avatar" id="app">
            <div class="box">
                <p class="title">邀请好友</p>
                <img class="close" @click="back" src="../static/images/close_btn1.png" alt="">
                <div class="content">
                    <img class="invite_code" :src="invite_code" alt="">
                </div>
                <p class="invite_tips">长按保存图片到相册</p>
            </div>
        </div>
        <script>
            apiready = function(){
                var game = new Game("../static/mp3/bg1.mp3");
                // 在 #app 标签下渲染一个按钮组件
                Vue.prototype.game = game;
                new Vue({
                    el:"#app",
                    data(){
                        return {
                            invite_code: '', // 好友邀请码图片地址
                        }
                    },
                    created(){
                        this.get_invite_code(); // 获取好友邀请码地址
                        this.listen(); // 监听事件
                    },
                    methods:{
                        // 监听事件
                        listen(){
                            // 监听长按事件
                            this.listen_long_press();
                        },

                        // 监听长按邀请码事件
                        listen_long_press(){
                            api.addEventListener({
                                name: 'longpress' // 监听系统长按页面事件
                            }, (ret, err)=>{
                                // 保存图片或视频到本地相册
                                api.saveMediaToAlbum({
                                    path: this.invite_code
                                }, (ret, err)=>{
                                    if (ret && ret.status) {
                                        this.game.tips('保存二维码成功!')
                                    } else {
                                        this.game.tips('保存二维码失败!')
                                    }
                                });
                            });  
                        },


                        back(){
                            this.game.closeFrame();
                        },
                        // 获取好友邀请码地址
                        get_invite_code(){
                            let self = this
                            self.game.check_user_login(self, () => {
                                let token = self.game.getdata('access_token') || self.game.getfs('access_token')
                                // 拼接好友邀请码地址
                                self.invite_code = self.game.config.HTTP_SERVER + 'users/invite.png?jwt=' + token
                            })
                        },


                    }
                });
            }
        </script>
    </body>
</html>


  1. static/js/main.js中新增HTTP_SERVER(网关地址)配置项,代码:
   // 初始化配置
	init_config(){
		// 客户端项目的全局配置
		this.config = {
			// 服务端API地址
			// API_SERVER:"http://192.168.189.138:5000/api",
			API_SERVER:"http://192.168.19.46:5000/api",
			// http服务端网关地址
			HTTP_SERVER: 'http://192.168.19.46:5000/',
			SMS_TIME_OUT: 60 , // 短信发送冷却时间/秒
			CAPTCHA_APP_ID: "2028945858", // 防水墙验证码应用ID
		}
	}

扫描识别邀请码,下载应用软件

服务端提供对应的接口允许访问

  1. 视图提供users/views.py
from flask import make_response, current_app, request, render_template

# 根据二维码识别进入的唤醒/下载APP视图
def invite():
    '''根据二维码识别进入的唤醒/下载APP视图'''
    # 提取二维码中隐藏链接的参数信息
    uid = request.args.get('uid') # 用户ID
    user_type = request.args.get('type') # 用途来源

    # 识别用户信息
    user = services.get_user_by_id(id = uid)
    # todo 用户邀请好友的奖励方法,将来方便进行奖励处理
    # services.apply_user(user)

    # 识别用户当前使用的访问代理(使用什么软件扫描的二维码)
    user_agent = request.headers.get('User-Agent').lower()
    if 'micromessenger' in user_agent:
        client_agent = 'weixin' # 使用微信扫描的
    elif 'alipayclient' in user_agent:
        client_agent = 'alipay' # 使用支付宝扫描的
    else:
        client_agent = 'others' # 使用其他软件扫描的

    # 判断用途来源
    if user_type == 'invite':
        '''邀请好友的'''
        data = {
            'uid': uid,
            'user_tpye': user_type,
            'client_agent': client_agent
        }
        # 返回模板界面
        return render_template('users/invite.html', **data)

    return 'hello world !'

  1. 模板目录下创建对应的html模板文件,application/templates/users/invite.html, 代码:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <meta >
    <title>Title</title>
    <style>
    body{
        background-color: #000;
    }
    img{
        width: 100%;
    }
    a{
        color: #fff;
    }
    </style>
</head>
<body>
    {% if client_agent == "weixin" %}
        <img src="/static/openbrowser.png" alt="">
    {% else %}
        <div id="content"></div>
        <script>
        // 尝试通过打开客户端已经安装的魔方APP
        var iframe = document.createElement("iframe");
        iframe.src = "mofang://?uid={{ uid }}&user_type={{user_type}}"; // app的私有协议,在用户已经安装了app以后,可以自动唤醒APP
        iframe.hidden=true; // iframe.style.display="none";
        document.body.appendChild(iframe);

        // 如果等待了3秒以后,还没有切换APP
        setTimeout(function() {
          if (!document.hidden) {
            // 在3秒内如果页面出去了。说明这个时候document.hidden是true,这段代码就不执行了。
            // 就算是再切回来也是不执行的。
            // 如果你进了这个函数,没离开。。那就会在3秒后跳进这里
            alert('你还没安装魔方APP,赶紧下载吧,你的好友朋友都在等哦~');

            // 自动下载
            var iframe = document.createElement("iframe");
            iframe.src = "/static/app/mofang.apk"; // app所在的下载地址
            iframe.hidden=true;
            document.body.appendChild(iframe);

            // 让用户自己手动点击下载链接
            u = navigator.userAgent;
            let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android终端
            let isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
            var content = document.querySelector("#content");
            if (isiOS) {
                // 去下载ios版本的魔方APP
                content.innerHTML = `<a href="/static/app/mofang.ipa">点击链接下载魔方APP</a>`;
            }
            if (isAndroid){
                // 去下载安卓版本的魔方APP
                content.innerHTML = `<a href="/static/app/mofang.apk">点击链接下载魔方APP</a>`;
            }
          }
        }, 3000);

        </script>
    {% endif %}
</body>
</html>

(1) 把素材中的openbrowser.png图片放到静态文件中application/static/image

(2) 把客户端编译过的APP下载包, 放置到静态文件 application/static/app 中, 方便视图调用下载

  1. 注册视图路由: ,users.urls,代码:
from application import path, api_rpc
# 引入当前蓝图应用视图 , 引入rpc视图
from . import views, api

# 蓝图路径与函数映射列表
urlpatterns = [
    path('invite.png', views.invite_code), # 生成邀请码,推广应用
    path('invite', views.invite), # 唤醒或下载APP软件
]

# rpc方法与函数映射列表[rpc接口列表]
apipatterns = [
    api_rpc('check_mobile', api.check_mobile),
    api_rpc('register', api.register),
    api_rpc('login', api.login),
    api_rpc('refresh', api.refresh_token), # 刷新access_token值
    api_rpc('update_avatar', api.update_avatar), # 更新头像
    api_rpc('update_nickname', api.update_nickname), # 更新昵称
    api_rpc('update_mobile', api.update_mobile), # 更新手机号
    api_rpc('update_password', api.update_password), # 更新登录密码
    api_rpc('update_pay_password', api.update_pay_password), # 更新交易密码
    api_rpc('get_apply_friend_history', api.get_apply_friend_history), # 获取好友申请列表
    api_rpc('search_user_info', api.search_user_info), # 搜索用户信息
    api_rpc('apply_friend', api.apply_friend), # 添加用户好友申请记录
    api_rpc('add_friend', api.add_friend), # 添加用户好友关系记录
    api_rpc('cancel_apply_friend', api.cancel_apply_friend), # 用户取消自己申请的好友记录
    api_rpc('get_friend_list', api.get_friend_list), # 获取好友列表
]



客户端

App配置私有协议, 允许第三方应用通过私有协议唤醒魔方APP

  1. config.xml 中配置添加 <preference name="urlScheme" value="mofang" />
 <widget id="A6177994729952"  version="0.0.1">

    <name>mofangapp</name>

    <description>

        Example For APICloud.

    </description>

    <author email="developer@apicloud.com" href="http://www.apicloud.com">

        Developer

    </author>

    <content src="html/index.html" />

    <access origin="*" />

    <preference name="pageBounce" value="false"/>

	<preference name="appBackground" value="rgba(0,0,0,0.0)"/>

	<preference name="windowBackground" value="rgba(0,0,0,0.0)"/>

	<preference name="frameBackgroundColor" value="rgba(0,0,0,0.0)"/>

	<preference name="hScrollBarEnabled" value="false"/>

	<preference name="vScrollBarEnabled" value="false"/>

	<preference name="autoLaunch" value="true"/>

	<preference name="fullScreen" value="false"/>

	<preference name="autoUpdate" value="true" />

	<preference name="smartUpdate" value="false" />

	<preference name="debug" value="true"/>

	<preference name="statusBarAppearance" value="true"/>
  <!-- 配置app私有协议, 可通过协议唤醒魔方APP软件 -->
  <preference name="urlScheme" value="mofang" />

	<permission name="readPhoneState" />

	<permission name="camera" />

	<permission name="record" />

	<permission name="location" />

	<permission name="fileSystem" />

	<permission name="internet" />

	<permission name="bootCompleted" />

	<permission name="hardware" />

</widget>


  1. APP默认首页index.html中监听是否来自第三方应用的唤醒.并接收唤醒时附带的参数信息.

html/index.html,代码:

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>首页</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
        <meta name="format-detection" content="telephone=no,email=no,date=no,address=no">
        <link rel="stylesheet" href="../static/css/main.css">
        <script src="../static/js/vue.js"></script>
        <script src="../static/js/axios.js"></script>
        <script src="../static/js/uuid.js"></script>
        <script src="../static/js/main.js"></script>
    </head>
    <body>
        <div class="app" id="app">
            <img class="music" :class="music_play?'music2':''" @click="music_play=!music_play" src="../static/images/player.png">
            <div class="bg">
                <img src="../static/images/bg0.jpg">
            </div>
            <ul>
                <li><img class="module1" src="../static/images/image1.png"></li>
                <li><img class="module2" src="../static/images/image2.png" @click='to_user'></li>
                <li><img class="module3" src="../static/images/image3.png"></li>
                <li><img class="module4" src="../static/images/image4.png" @click='to_login'></li>
            </ul>
        </div>
        <script>
            apiready = function(){
                var game = new Game("../static/mp3/bg1.mp3");
                Vue.prototype.game = game;
                new Vue({
                    el:"#app",
                    data(){
                        return {
                            music_play:true,  // 默认播放背景音乐
                            prev:{name:"",url:"",params:{}}, // 上一页状态
                            current:{name:"index",url:"index.html","params":{}}, // 下一页状态
                        }
                    },
                    watch:{
                        music_play(){
                            if(this.music_play){
                                this.game.play_music("../static/mp3/bg1.mp3");
                            }else{
                                this.game.stop_music();
                            }
                        }
                    },
                    created(){
                        this.listen(); // 监听事件
                    },
                    methods:{
                        // 监听事件
                        listen(){
                            // 监听外部访问,唤醒app
                            this.listen_invite();
                        },

                        // 监听外部访问,唤醒app
                        listen_invite(){
                            // 使用系统方法appintenr监听并使用appParam接收URLScheme的路由参数
                            // 收集操作保存起来,并跳转到登陆页面.
                            api.addEventListener({
                                name: 'appintent' // 系统方法
                            }, (ret, err)=>{
                                // 获取路由参数,保存到本地
                                let appParam = ret.appParam;
                                // this.game.print(appParam,1); //{"uid":xxx,"user_type":xxx};
                                this.game.setfs(appParam)

                                // 如果是其他用户邀请注册!
                                if(appParam.user_type == 'invite'){
                                    // 跳转到登陆页面
                                    this.game.openWin('login', 'login.html')
                                }
                            });
                        },

                        // 点击签到跳转登陆页面
                        to_login(){
                            this.game.openWin('login','login.html')
                        },
                        // 点击跳转到个人中心页面
                        to_user(){
                            // 判断用户是否登陆
                            this.game.check_user_login(this,() => {
                                this.game.openWin('user', 'user.html')
                            });
                        },

                    }
                })
            }
        </script>
    </body>
</html>


编译生成apk安装包

接下来的开发,我们不能再依赖官方提供的AppLoader进行功能测试了,所以我们使用由APICloud编辑器提供的本地编译, 编译自定义APPLoader来进行测试。

  1. 编译APP,则是生成一个独立的APP,无法进行终端调试,后续如果客户端代码更新,需要重新生成APP。
  2. 编译自定义APPLoader,则是生成一个新的调试加载器工具,可以进行终端调试,可以配置网络参数。

posted @ 2021-06-23 16:25  十九分快乐  阅读(723)  评论(0编辑  收藏  举报