当前位置: 首页 > 编程日记 > 正文

腾讯广告广点通API接入文档(Android)

官方文档地址

如果能够看懂文档的也没有必要再往下面看了。本篇文章就到此结束。

下面记录的是本人在上面锁踩过的坑,因为我发现Mac电脑上面的联系客服不是我想要的。

本来只是内部使用的文档,后来想想还是公开出来,希望能够帮助到人。

进入正式的接入流程吧!!!

Step 1: 注册成为开发者

Step 2: 创建应用

这两步建议可以直接看文档,坑不在这一块。但是创建应用的时候有几个点可以注意下

  • 应用介绍:这个不只是简单的介绍一下应用,还需要表明创建应用以后需要用到哪些接口,并且是干嘛使用的

    应用介绍说明(自己的应用介绍说明),主要使用到的接口有:1、https://developers.e.qq.com/oauth/authorize 通过这个接口获取到 authorization_code ;2、调用接口 https://api.e.qq.com/oauth/token 获取到 access_tokenrefresh_token ; 3、最后在调用 https://api.e.qq.com/v1.0/campaigns/add 发送请求

  • 回调地址:这个可以是你们公司的域名之类的,可以是不正确的,没有很大的关系。
  • 创建应用以后会向邮箱里面给你发送一些数据,我整个过程中没有使用这个数据,直接使用的是正式流程中的数据。主要还是看自己吧!

应用创建成功以后并且审核通过的话,就可以进行接下来的步骤了。

Step 3:授权认证

授权认证就是用浏览器去调用一个接口

https://developers.e.qq.com/oauth/authorize?client_id=123456&redirect_uri=https://www.example.com&state=&scope=

其中:

  • client_id:开发者创建的应用唯一标识id,必填,可通过 [应用程序管理页面] 查看;
  • redirect_uri:回调地址,由开发者自行提供和定义(地址主域需与开发者创建应用程序时登记的回调主域一致),用于跳转并接收回调信息,必填;
  • state:开发者自定义参数,可用于验证请求有效性或者传递其他自定义信息,回调的时候会原样带回,可选;
  • scope:授权的能力范围,可选,不传时表示授权范围为当前应用程序所拥有的所有能力;

OAuth 2.0 授权页面如下图所示:

同意授权以后,页面将会跳转到以下链接:

https://www.test.com/?authorization_code=1066a051ea8fbaf011b892c202ae1c93&state=

https://www.test.com 表示你所填写的回调地址。

authorization_code=1066a051ea8fbaf011b892c202ae1c93 这个参数将会在接下来的步骤中有这很大的作用。

点击进入你的腾讯社交平台->应用程序管理->应用test,进入应用test详情页面,会在页面的最底下绑定帐号管理栏里面多出刚刚授权的账号,

我这边有两个是因为我授权了两个账号。注意到图片上面有个广点通账号,这个将会对你有用的。

Step 4:使用 authorization_code 获得 access_token 和 refresh_token

腾讯文档关于获取这个还是说的很清楚的,具体可以查看文档。直接贴一个我这边请求的图:

这个接口的请求方式是GET

Step 5:上报用户行为数据

上报用户行为数据之前需要广点通人员在DMP后台新建App用户行为数据源,这一步骤将会取得 用户属性数据源 id ,接口会要用到的。

请求地址:

https://api.e.qq.com/v1.0/user_properties/add?access_token=<ACCESS_TOKEN>&timestamp=<TIMESTAMP>&nonce=<NONCE>'

对参数进行讲解一下

  • access_token:就是上一个接口获取到的数据
  • timestamp : 时间戳 (秒级别)
  • nonce : 32位随机码

请求方式:POST

请求参数:

名称类型描述
account_id(必填)integer推广帐号 id,有操作权限的帐号id,包括代理商和广告主帐号 id
user_action_set_id(必填)integer用户行为源 id,通过 [user_action_sets 接口] 创建用户行为源时分配的唯一 id
actions(必填)struct[]返回数组列表,不能大于 50KB 数组最小长度 1,最大长度 50
action_time(必填)integer行为发生时,客户端的时间点。 UNIX时间,单位为秒,如果不填将使用服务端时间填写 最小值 0,最大值 2147483647
user_id(必填)struct用户标识
hash_imei(必填)stringIMEI 设备号保持小写,进行 md5 编码 字段长度最小 32 字节,长度最大 32 字节
action_type(必填)enum标准行为类型,当值为 'CUSTOM' 时表示自定义行为类型,[枚举详情] 枚举列表:{ CUSTOM, REGISTER, VIEW_CONTENT, CONSULT, ADD_TO_CART, PURCHASE, ACTIVATE_APP, SEARCH, ADD_TO_WISHLIST, INITIATE_CHECKOUT, COMPLETE_ORDER, START_APP, RATE, PAGE_VIEW, RESERVATION, SHARE, APPLY, CLAIM_OFFER, NAVIGATE, PRODUCT_RECOMMEND, VISIT_STORE, TRY_OUT, DELIVER, SIGN_IN }

上面只是对参数进行讲解

还是给个json示例吧

    {"account_id": "<ACCOUNT_ID>","user_action_set_id": "<USER_ACTION_SET_ID>","actions": [{"action_time": 1535097324,"user_id": {"hash_imei": "f9efca36a3c30e1cf28170d86ecbf5e9"},"action_type": "REGISTER",}]
}
复制代码

account_id 怎么获取呢?两种方式:

一种就是我们在获取 access_token 的时候,返回结果数据里面还有一个 account_id 的字段,没错,就是那个了。

第二种就是我们在应用详情下面的绑定账号管理里面的广点通账号ID

user_action_set_id 就是用户属性数据源 id ,让对面对接人员提供。

action_time :时间戳(秒级别的)

hash_imei :imei的MD5加密字符串

action_type :本次上报的类型

如果接口返回的是

{"code": 0,"message": ""
}
复制代码

那就恭喜你,流程已经走通了。

现在是不是要开始上代码了呢,别急,还有一些要注意的东西。

比如说,上面获取到的 access_token 是会过期的,需要使用到 refresh_token 去刷新有效期的。具体怎么刷新?看腾讯文档。现在的问题在哪里呢?比如说,今天对接测试通过了,打包上线并且审核通过了,过两天下载的用户就会出现 access_token 过期的问题,怎么处理呢?有同学肯定会说,那我们在用户调用上报数据接口的时候去刷新一下不就行了。其实也可以的,但是我觉得这个刷新也太频繁了吧。所以我特意询问过腾讯的技术支持,他们建议把刷新 access_token 的机制放到我们的服务器端去做,也就是让服务器端帮我们一天刷新一下这个 token ,刷新 access_token 并不会改变 access_token 的值,只会改变 access_token 的有效期。那我们在客户端所要做的事情就很简单了,那就是上报数据就行了。

代码该上还是要上的(注意:以下代码由kotlin编写):

实体类

class OCPABean(/*** 广点通帐号ID,(可以自己查找,也可以由对方提供)*/var accountID: String?,/*** 用户行为源 id,这个由对方提供(广点通)*/var userActionSetId: String?,/*** 通过code获取到的token*/var token: String?,/****/var channelIdList: List<String>?)
复制代码

下面这个类主要是用来初始化我们的一些必要的数据

object OCPAStorage {/*** 用于存储app包名所对应的渠道号*/var ocpaConfig = mutableMapOf<String, OCPABean>()init {initTest()}private fun initTest() {var list = listOf("getui1")var ocpaBean = OCPABean("83005", "177844", "5a42ed16464f8cda38c7e4ea000", list)ocpaConfig["com.baidu.test"] = ocpaBean}}
复制代码

工具类,提供一些方法,注:currentRegisterNeedReport 这个方法可以根据自己的需求进行实现

object OCPAUtil {var ocpaBean: OCPABean? = null/*** 当前的包名和渠道是否需要上报*/fun currentRegisterNeedReport(context: Context): Boolean {var packageName = context.packageNamevar ocpaConfigMap = OCPAStorage.ocpaConfigvar keys = ocpaConfigMap.keysif (packageName in keys) {var ocpaBean = ocpaConfigMap[packageName]var channelIdList = ocpaBean?.channelIdListvar channelName = ChannelUtil.getChannelName(context)if (channelIdList?.contains(channelName) == true) {this@OCPAUtil.ocpaBean = ocpaBeanreturn true}}return false}/*** 获取当前秒级的时间戳*/fun getTimeStamp(): String {var timeStamp = System.currentTimeMillis() / 1000return timeStamp.toString()}/*** 生成32位编码* @return string*/fun getUUID(): String {return UUID.randomUUID().toString().trim().replace("-", "")}}
复制代码

下面这个类是主要做网络请求,上报接口的,采用的Okhttp3网络框架

object OCPAHttpClient {const val SP_CONSTANT = "OCPA_SP_CONSTANT"fun register(context: Context) {var spConstant = FRSharedPreferences.getStringNotClear(SP_CONSTANT, "")
//        var spConstant = ""if (TextUtils.isEmpty(spConstant) && OCPAUtil.currentRegisterNeedReport(context)) {httpRegister()}}private fun httpRegister() {var ocpaBean = OCPAUtil.ocpaBeanocpaBean?.let {val okHttpClient = OkHttpClient.Builder().connectTimeout(30, TimeUnit.SECONDS).writeTimeout(30, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS).build()//获取当前的秒级时间戳var timeStamp = OCPAUtil.getTimeStamp()//构造一个urlvar baseUrl = "https://api.e.qq.com/v1.0/user_actions/add?access_token=${ocpaBean.token}&timestamp=$timeStamp&nonce=${OCPAUtil.getUUID()}"var dataJsonObject = JSONObject()//构造参数try {dataJsonObject.put("account_id", ocpaBean.accountID)dataJsonObject.put("user_action_set_id", ocpaBean.userActionSetId)var actionJA = JSONArray()var actionJO = JSONObject()actionJO.put("action_time", timeStamp)actionJO.put("action_type", "REGISTER")var userIdJO = JSONObject()var imei = FRDeviceUtil.getPhoneInfo()imei?.let {userIdJO.put("hash_imei", FREncryptUtil.string2MD5(imei))}actionJO.put("user_id", userIdJO)actionJA.put(actionJO)dataJsonObject.put("actions", actionJA)} catch (e: JSONException) {e.printStackTrace()}var requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), dataJsonObject.toString())var request = Request.Builder().url(baseUrl).post(requestBody).build()okHttpClient.newCall(request).enqueue(object : Callback {override fun onFailure(call: Call?, e: IOException?) {FRLog.e("log", "OCPA注册失败")}override fun onResponse(call: Call?, response: Response?) {FRSharedPreferences.setStringNotClear(SP_CONSTANT, SP_CONSTANT)FRLog.e("log", response?.body()?.string())}})}}
}
复制代码

MD5加密类:

public class FREncryptUtil {/*** 利用MD5进行加密** @param inStr 待加密的字符串* @return 加密后的字符串* @throws NoSuchAlgorithmException     没有这种产生消息摘要的算法* @throws UnsupportedEncodingException*/public static String string2MD5(String inStr) {if (TextUtils.isEmpty(inStr))return "";MessageDigest md5 = null;try {md5 = MessageDigest.getInstance("MD5");} catch (Exception e) {System.out.println(e.toString());e.printStackTrace();return "";}char[] charArray = inStr.toCharArray();byte[] byteArray = new byte[charArray.length];for (int i = 0; i < charArray.length; i++)byteArray[i] = (byte) charArray[i];byte[] md5Bytes = md5.digest(byteArray);StringBuffer hexValue = new StringBuffer();for (int i = 0; i < md5Bytes.length; i++) {int val = ((int) md5Bytes[i]) & 0xff;if (val < 16)hexValue.append("0");hexValue.append(Integer.toHexString(val));}return hexValue.toString();}
}
复制代码

获取Imei的方法:这个方法可能和使用的时候有点不一样,具体的修改自己看着改一下吧。

/*** 获取手机的IMEI** @return*/
public static String getPhoneInfo(Context context) {TelephonyManager tm = null;try {tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);return tm.getDeviceId();} catch (Exception e) {return "";}
}
复制代码

好了,到此结束吧。不要忘记叫后台帮忙刷新 token 啊!!!

转载于:https://juejin.im/post/5b7fda3cf265da437d6e02ef

相关文章:

Linux下的下载工具 axel

下载地址&#xff1a;http://wilmer.gaast.net/main.php/axel.html Axel是命令行下的多线程下载工具&#xff0c;支持断点续传&#xff0c;速度通常情况下是Wget的几倍。 下载后使用如下命令编译安装&#xff1a; #tar zxvf axel-1.0a.tar.gz #cd axel-1.0a/ #./con…

集成学习知识点汇总

为啥叫集成学习 结合多个学习器来完成学习任务。 俗话说就是&#xff0c;团结力量大。 个体学习器可以相同可以不同。如果相同叫同质集成&#xff0c;如果不尽相同叫异质集成。 个体学习器最好满足&#xff1a;好而不同。 所谓好(准确性)&#xff0c;就是个体学习器不能太坏&…

hdu 2028 Lowest Common Multiple Plus

题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid2028 题目大意&#xff1a;求最小公倍数&#xff0c;用辗转相除法。 1 #include <stdio.h>2 int main ()3 {4 int gcd(int a,int b);5 int a,b,n,i,c;6 while (scanf("%d",&n)…

TreeView

6.遍历TreeView节点(递归算法) private void Page_Load(object sender, System.EventArgs e) { GetAllNodeText(TreeView1.Nodes); } void GetAllNodeText(TreeNodeCollection tnc) { foreach(TreeNode node in tnc) { if(node.Nodes.Count!0) GetAllNodeText(node.Nodes); Res…

FZU 2297 Number theory【线段树/单点更新/思维】

Given a integers x 1, you have to apply Q (Q ≤ 100000) operations: Multiply, Divide. Input First line of the input file contains an integer T(0 < T ≤ 10) that indicates how many cases of inputs are there. The description of each case is given below: …

<软件过程与改进>计算大题考点总结与例题

1.PSP_PROBE估算法 常见考法&#xff1a;给历史数据&#xff0c;需要选择代理规模的估算值和程序规模/所需资源的实际值&#xff0c;用以下公式求得拟合公式参数 然后使用公式计算出未知的程序规模/所需资源 例题 2.PSP过程质量的度量指标_yield 常见考法&#xff1a;给出缺…

c语言exit和return区别,在fork和vfork中使用

转自c语言exit和return区别&#xff0c;在fork和vfork中使用 exit函数在头文件stdlib.h中。 简述&#xff1a; exit&#xff08;0&#xff09;&#xff1a;正常运行程序并退出程序&#xff1b; exit&#xff08;1&#xff09;&#xff1a;非正常运行导致退出程序&#xff1b; r…

WIKI与BLOG殊途同归(转)

现在很多朋友都拥有了自己的BLOG网页&#xff0c;尽管他们可能并不打算走木子美那种写私人日记的路子&#xff0c;但彰显个性、张扬自我的目的&#xff0c;大都类似。其实在这个时候&#xff0c;中国的许多技术迷们已经把目光投向了WIKI。 历经了网络反黄与木子美&#xff0c;中…

Spring MVC中DispatcherServlet理解总结(1)

DispatcherServlet在web.xml中的配置 <context-param><!--默认配置文件为/WEB-INF/[servlet名字]-servlet.xml--><param-name>contextConfigLocation</param-name><param-value>WebApplicationContext的上下文配置</param-value> </con…

功能点度量方法介绍

功能点度量方法是利用软件需求分析度量软件规模。 软件需求分析包括&#xff1a;软件功能需求分析、软件性能需求分析 在需求分析阶段可以利用数据流图和用例图对软件规模进行度量&#xff0c;分别对应功能点度量与用例点度量方法 1.功能点度量方法的分类 第三种 IFPUG是我…

微软2014校园招聘笔试试题

转载请标明出处&#xff0c;原文地址&#xff1a;http://blog.csdn.net/hackbuteer1/article/details/121908071、Which statement(s) is(are) correct about thread and process&#xff1f;Select all that apply.(5 Points) A、Threads share the same address space of the…

vi(vim)快捷键小记

1、前言 vi是“visual interface”的缩写&#xff0c;vim是vi IMproved(增强版的vi)。总结一下自己平时常用的vim快捷键&#xff0c;当是忘记也好&#xff0c;后续会不定期更新。 2、vim 快捷键 快捷键说明vi[m] file打开[新建]文件命令模式可以移动光标、删除字符等h,j,k,l左…

Premiere Pro2.0用DebugMode2.3搭桥小日本4.0输出图解

看图说话&#xff0c;不懂的多试试看首先明确几点&#xff1a;1。3个软件&#xff1a;Premiere Pro2.0、DebugMode&#xff08;帧服务器&#xff09;、小日本&#xff08;TMPGEnc 4.0 XPress&#xff09;2。渲染过程是在小日本中完成&#xff0c;与DebugMode无关&#xff0c;De…

用例点度量方法介绍

用例点度量方法分为6个步骤&#xff0c;分别是 step 1:计算未调整前的角色(执行者)权重 将角色按照复杂程度分为3类&#xff0c;具体如下 则本例中 UAW1121329 计算未调整前的用例权重UUC 有三种评估用例复杂程度的方法&#xff0c;具体如下 以下是用例权重评估表(普通那…

NYOJ——街区最短路径问题

街区最短路径问题 时间限制&#xff1a;3000 ms | 内存限制&#xff1a;65535 KB难度&#xff1a;4描述一个街区有很多住户&#xff0c;街区的街道只能为东西、南北两种方向。住户只可以沿着街道行走。各个街道之间的间隔相等。用(x,y)来表示住户坐在的街区。例如&#xff08…

Git 中常用的 4 个命令

使用 Git 进行版本管理时&#xff0c;肯定不只做提交&#xff0c;有时候也会需要回退修改&#xff0c;并且在回退的基础上进行重新提交&#xff0c;这时候有几个常用的命令就需要用到了&#xff0c;下面分别做介绍。 1、查看提交日志 首先&#xff0c;我们查看当前提交记录的命…

7月17日 晴

小懒猫&#xff0c;太阳晒PP拉Mua转载于:https://www.cnblogs.com/loverain/archive/2008/07/17/1244992.html

AS更改初始布局遇到的问题

将所有的simple.xml.ftl的内容都改成 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"…

android Json解析详解

JSON的定义&#xff1a; 一种轻量级的数据交换格式&#xff0c;具有良好的可读和便于快速编写的特性。业内主流技术为其提供了完整的解决方案&#xff08;有点类似于正则表达式 &#xff0c;获得了当今大部分语 言的支持&#xff09;&#xff0c;从而可以在不同平台间进行数据交…

[二]Java虚拟机 jvm内存结构 运行时数据内存 class文件与jvm内存结构的映射 jvm数据类型 虚拟机栈 方法区 堆 含义...

前言简介 class文件是源代码经过编译后的一种平台中立的格式 里面包含了虚拟机运行所需要的所有信息,相当于 JVM的机器语言 JVM全称是Java Virtual Machine ,既然是虚拟机,他终归要运行在物理机上 在操作系统中体现出来的也就是一个进程 操作系统会给他分配资源,割一块内存作为…

import android.support.v7.widget.RecyclerView失败

换成 androidx.recyclerview.widget.RecyclerView 参考文章 https://blog.csdn.net/u013183608/article/details/89428611/

CrackMe_001

本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己)&#xff0c;一步步尝试将160个CrackMe全部破解&#xff0c;如果可以&#xff0c;通过任何方式写出一个类似于注册机的东西。 其中&#xff0c;文章中按照如下逻辑编排&#xff08;解决如下问题&#xff09;&…

用javascript实现的纵版飞行射击游戏—《天机》

花了一个半月的时间用javascript完成了这款web版飞行射击游戏&#xff0c;游戏效果接近一般的客户端游戏&#xff0c;不过对机器的要求稍微高点点&#xff0c;主要是CPU&#xff0c;最好在1.5GHZ以上&#xff0c;不然可能会比较卡&#xff0c;支持IE、FF、Opera、safari。 用ja…

对分组交换(packet switching)高效迅速灵活可靠四个优点的理解

1.什么是分组&#xff1f; 通信过程中要发送的整块数据被称为一个报文(message)&#xff0c;报文被划分为一个个更小的等长数据段&#xff0c;每个数据段前加入一些由必要的控制信息组成的首部后&#xff0c;就构成了一个分组。分组是在互联网中传送的数据单元(长报文&#xff…

06、ActivationDeactivation

1、将App.xaml中的StartupUri"MainWindow.xaml"删除。 2、使用NuGet安装Prism.Wpf、Prism.Core、Prism.Unity。 3、添加类“Bootstrapper”&#xff0c;编辑如下&#xff1a; 1 using System;2 using System.Collections.Generic;3 using System.Linq;4 using System…

Git 学习笔记一

Git的基本配置和使用 一、git add ;git commit;git commit -a(默认跟踪修改直接提交(不包括新文件))。 二、tig命令 查看修改记录的前端工具&#xff0c;方面查看修改记录。相当于git log –p。 三、git config --global alias.ci "commit -a -v"添加命令别名&#x…

vb 取得计算机名及目录

Public gCompName 取得计算机名及Windows目录 Dim i% Dim c$ Dim cSql As String Dim cProduct As String c Space(256) i GetComputerName(c, 256) gCompName Trim(c) gCompName Left(gCompName, Len(gCompName) - 1) 读取MAC地址 Dim…

速率单位和信息量单位区分

网络技术钟的速率指的是数据的传送速率&#xff0c;也称为数据率或比特率。 单位是bit/s 比特每秒 也写作b/s 或bps(bit per second) 当数据率较高时 常常在bit/s前面加一个字母&#xff0c;如 k 10^3 M 10^6 G 10^9 T 10^12 P 10^15 …… 数据量往往用字节B作为度量单位…

python 自动生成C++代码 (代码生成器)

python 代码自动生成的方法 &#xff08;代码生成器&#xff09; 遇到的问题 工作中遇到这么一个事&#xff0c;需要写很多C的底层数据库类&#xff0c;但这些类大同小异&#xff0c;无非是增删改查&#xff0c;如果人工来写代码&#xff0c;既费力又容易出错&#xff1b;而借用…

WPF实用指南二:移除窗体的图标

原文:WPF实用指南二&#xff1a;移除窗体的图标WPF没有提供任何功能来移除窗体上的icon图标。一般的做法是设置一个空白的图标&#xff0c;如下图1: 这种做法在窗体边框与标题之间仍然会保留一片空白。比较好的做法是使用Win32API提供的函数来移除这个图标。使用如下的代码&…