2024年Android最新Android 如何接入穿山甲广告?_怎么给手机养穿山甲广告数据,零基础学android开发
最后
其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
下面分享的腾讯、头条、阿里、美团、字节跳动等公司2019-2021年的高频面试题全套解析,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,下面只是以图片的形式给大家展示一部分。

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
下载完成之后开始集成
集成SDK
集成方式一
导入aar及SDK依赖的jar包
将本SDK压缩包内的open_ad_sdk.aar复制到Application Module/libs文件夹(没有的话须手动创建), 并将以下代码添加到您app的build.gradle中:
dependencies {
implementation(name: 'open_ad_sdk_4.4.0.2', ext: 'aar')
}
方式二:从穿山甲3.5.0.6版本开始,开发者也可以使用Gradle依赖导入穿山甲SDK
- 步骤一:添加仓库
在project级别的build.gradle文件中添加Maven的引用,url ‘https://artifact.bytedance.com/repository/pangle’
示例:
allprojects {
repositories {
maven {
url 'https://artifact.bytedance.com/repository/pangle'
}
}
}
步骤二:添加依赖
在主module的build.gradle文件添加SDK依赖
dependencies {
implementation 'com.pangle.cn:ads-sdk-pro:4.4.0.9'
}
Gradle版本要求:
自3400版本开始,穿山甲支持了Android R,引入了Android R的 标签,需要对gradle版本进行限制,限制范围为:3.3.3、 3.4.3、 3.5.4、3.6.4、4.0.1 ,开发者根据自身情况酌情升级
AndroidManifest配置
添加权限
<!--必要权限-->
<uses-permission android:name="android.permission.INTERNET" />
<!--必要权限,解决安全风险漏洞,发送和注册广播事件需要调用带有传递权限的接口-->
<permission android:name="${applicationId}.openadsdk.permission.TT_PANGOLIN"
android:protectionLevel="signature" />
<uses-permission android:name="${applicationId}.openadsdk.permission.TT_PANGOLIN" />
<!--可选权限-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.GET_TASKS"/>
<!--可选,穿山甲提供“获取地理位置权限”和“不给予地理位置权限,开发者传入地理位置参数”两种方式上报用户位置,两种方式均可不选,添加位置权限或参数将帮助投放定位广告-->
<!--请注意:无论通过何种方式提供给穿山甲用户地理位置,均需向用户声明地理位置权限将应用于穿山甲广告投放,穿山甲不强制获取地理位置信息-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 如果视频广告使用textureView播放,请务必添加,否则黑屏 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!--demo场景用到的权限,不是必须的-->
<uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
<!-- 穿山甲3400版本新增:建议添加“query_all_package”权限,穿山甲将通过此权限在Android R系统上判定广告对应的应用是否在用户的app上安装,避免投放错误的广告,以此提高用户的广告体验。若添加此权限,需要在您的用户隐私文档中声明! -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
注意: 穿山甲SDK不强制获取以上权限,即使没有获取可选权限SDK也能正常运行;获取以上权限将帮助穿山甲优化投放广告精准度和用户的交互体验,提高eCPM。
建议在广告请求前,合适的时机调用SDK提供的方法,在用户可以授权的情况下获取到声明中的权限,提高广告变现效率
//TTAdManager接口中的方法,context可以是Activity或Application
void requestPermissionIfNecessary(Context context);
provider配置
注意:
(1)为不影响下载类型广告使用 无论APP处于任何阶段provider都需要在清单文件中正常配置
(2)为不影响到广告的转化及收益 请务必在清单文件中配置xxx.TTMultiProvider
(3)${applicationId} 必须与开发者包名保持一致,否则会引发崩溃问题
适配Anroid7.0及以上如果您的应用需要在Anroid7.0及以上环境运行,请在AndroidManifest中添加如下代码:
<provider
android:name="com.bytedance.sdk.openadsdk.TTFileProvider"
android:authorities="${applicationId}.TTFileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
在res/xml目录下,新建一个xml文件file_paths,在该文件中添加如下代码:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!--为了适配所有路径可以设置 path = "." -->
<external-path name="tt_external_root" path="." />
<external-path name="tt_external_download" path="Download" />
<external-files-path name="tt_external_files_download" path="Download" />
<files-path name="tt_internal_file_download" path="Download" />
<cache-path name="tt_internal_cache_download" path="Download" />
</paths>
为了适配下载和安装相关功能,在工程中引用的包 com.android.support:support-v4:24.2.0使用24.2.0以及以上版本
注意:单进程或多进程都必须配置
<provider
android:name="com.bytedance.sdk.openadsdk.multipro.TTMultiProvider" android:authorities="${applicationId}.TTMultiProvider" android:exported="false" />
运行环境配置
本SDK可运行于Android4.0 (API Level 14) 及以上版本。
如果开发者声明targetSdkVersion到API 23以上,请确保调用本SDK的任何接口前,已经申请到了SDK要求的所有权限,否则SDK部分特性可能受限
代码混淆
如果您需要使用proguard混淆代码,需确保不要混淆SDK的代码。 请在proguard.cfg文件(或其他混淆文件)尾部添加如下配置:35xx以及以下版本混淆规则如下:
-keep class com.bytedance.sdk.openadsdk.** { *; }
-keep public interface com.bytedance.sdk.openadsdk.downloadnew.** {*;}
-keep class com.pgl.sys.ces.* {*;}
-keep class com.bytedance.embed_dr.** {*;}
-keep class com.bytedance.embedapplog.** {*;}
36xx版本-38xx版本混淆规则如下:
-keep class com.bytedance.sdk.openadsdk.** { *; }
-keep public interface com.bytedance.sdk.openadsdk.downloadnew.** {*;}
-keep class ms.bd.c.**{*;}
-keep class com.bytedance.mobsec.**{*;}
-keep class com.bytedance.embed_dr.** {*;}
-keep class com.bytedance.embedapplog.** {*;}
-keep interface com.bytedance.frameworks.baselib.network.http.cronet.I* {*;}
-keepnames class com.bytedance.framwork.core.sdkmonitor.SDKMonitorUtils
3900版本及以上版本混淆规则如下:
-keep class com.bytedance.sdk.openadsdk.** { *; }
-keep class com.bytedance.frameworks.** { *; }
-keep class ms.bd.c.Pgl.**{*;}
-keep class com.bytedance.mobsec.metasec.ml.**{*;}
-keep class com.ss.android.**{*;}
-keep class com.bytedance.embedapplog.** {*;}
-keep class com.bytedance.embed_dr.** {*;}
-keep class com.bykv.vk.** {*;}
4000版本混淆规则:以aar包里的混淆文件为准
注意: SDK代码被混淆后会导致广告无法展现或者其它异常
支持架构
注意: 3900以及以上版本SDK默认支持armeabi-v7a,arm64-v8a两种架构,如果有其他架构需求,请联系技术支持同学; 3900以下版本SDK中使用的so文件支持五种架构:x86,x86_64,armeabi,armeabi-v7a,arm64-v8a如果您应用中支持的架构超出这 五种,请在build.gradle中使用abiFilters选择支持的架构。如下所示:
ndk { // 设置支持的 SO 库构架,注意这里要根据你的实际情况来设置
abiFilters armeabi-v7a , arm64-v8a , x86 , x86_64 , armeabi
}
说明:
1、36xx-38xx版本中穿山甲增加了libmetasec_ml.so 库。
2、36xx-38xx版本若开发者使用armeabi架构,那么需要把armeabi-v7a下的 libmetasec_ml.so 拷贝到armeabi目录下使用。
白名单配置
注意:平台SDK包中whiteList.txt 白名单上的资源不支持混淆

配置完成之后创建一个SDK初始化脚本内容如下 初始化调用是在开屏界面调用 调用初始化成功之后会自动调用开屏代码
package com.unity3d.player.chuanshanjia;
import android.content.Context;
import android.util.Log;
import com.bytedance.sdk.openadsdk.TTAdConfig;
import com.bytedance.sdk.openadsdk.TTAdConstant;
import com.bytedance.sdk.openadsdk.TTAdManager;
import com.bytedance.sdk.openadsdk.TTAdSdk;
/**
* 可以用一个单例来保存TTAdManager实例,在需要初始化sdk的时候调用
*/
public class TTAdManagerHolder {
private static final String TAG = "TTAdManagerHolder";
private static boolean sInit;
private static String appid;
private static String appName;
private static TTAdManagerHolder _Instance;
public static TTAdManager get() {
return TTAdSdk.getAdManager();
}
public static TTAdManagerHolder Inst(){
if (_Instance == null){
_Instance = new TTAdManagerHolder();
}
return _Instance;
}
public void init(final Context context,String aid,String aname) {
appid = aid;
appName = aname;
Log.d(TAG, "TTAdManagerHolderinit aid:"+aid+" aname:"+aname);
doInit(context);
}
//step1:接入网盟广告sdk的初始化操作,详情见接入文档和穿山甲平台说明
private void doInit(Context context) {
if (!sInit) {
TTAdSdk.init(context, buildConfig(context), new TTAdSdk.InitCallback() {
@Override
public void success() {
Log.i(TAG, "success: " );
CsjSplashActivity.Inst().loadSplashAd();
}
@Override
public void fail(int code, String msg) {
Log.i(TAG, "fail: code = " + code + " msg = " + msg);
}
});
sInit = true;
}
}
private TTAdConfig buildConfig(Context context) {
//强烈建议在应用对应的Application#onCreate()方法中调用,避免出现content为null的异常
return new TTAdConfig.Builder()
.appId(appid)
.useTextureView(true) //默认使用SurfaceView播放视频广告,当有SurfaceView冲突的场景,可以使用TextureView
.appName(appName)
.titleBarTheme(TTAdConstant.TITLE_BAR_THEME_DARK)//落地页主题
.allowShowNotify(true) //是否允许sdk展示通知栏提示,若设置为false则会导致通知栏不显示下载进度
.debug(true) //测试阶段打开,可以通过日志排查问题,上线时去除该调用
.directDownloadNetworkType(TTAdConstant.NETWORK_STATE_WIFI) //允许直接下载的网络状态集合,没有设置的网络下点击下载apk会有二次确认弹窗,弹窗中会披露应用信息
.supportMultiProcess(false) //是否支持多进程,true支持
.asyncInit(true) //是否异步初始化sdk,设置为true可以减少SDK初始化耗时。3450版本开始废弃~~
//.httpStack(new MyOkStack3())//自定义网络库,demo中给出了okhttp3版本的样例,其余请自行开发或者咨询工作人员。
.build();
}
}
SDK集成完成之后开始接入SDK
工具类
ChuanShanJiaUtil
package com.unity3d.player.tools;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ChuanShanJiaUtil {
public static float getScreenWidthDp(Context context){
final float scale = context.getResources().getDisplayMetrics().density;
float width = context.getResources().getDisplayMetrics().widthPixels;
return width / (scale <= 0 ? 1 : scale) + 0.5f;
}
//全面屏、刘海屏适配
public static float getHeight(Activity activity) {
hideBottomUIMenu(activity);
float height;
int realHeight = getRealHeight(activity);
if (ChuanShanJiaUtil.hasNotchScreen(activity)) {
height = px2dip(activity, realHeight - getStatusBarHeight(activity));
}else {
height = px2dip(activity, realHeight);
}
return height;
}
public static void hideBottomUIMenu(Activity activity) {
if (activity == null) {
return;
}
try {
//隐藏虚拟按键,并且全屏
if (Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) { // lower api
View v = activity.getWindow().getDecorView();
v.setSystemUiVisibility(View.GONE);
} else if (Build.VERSION.SDK_INT >= 19) {
//for new api versions.
View decorView = activity.getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
// | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
| View.SYSTEM_UI_FLAG_IMMERSIVE;
decorView.setSystemUiVisibility(uiOptions);
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//获取屏幕真实高度,不包含下方虚拟导航栏
public static int getRealHeight(Context context) {
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
DisplayMetrics dm = new DisplayMetrics();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
display.getRealMetrics(dm);
} else {
display.getMetrics(dm);
}
int realHeight = dm.heightPixels;
return realHeight;
}
//获取状态栏高度
public static float getStatusBarHeight(Context context) {
float height = 0;
int resourceId = context.getApplicationContext().getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
height = context.getApplicationContext().getResources().getDimensionPixelSize(resourceId);
}
return height;
}
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / (scale <= 0 ? 1 : scale) + 0.5f);
}
public static int dp2px(Context context, float dp) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
/**
* 判断是否是刘海屏
* @return
*/
public static boolean hasNotchScreen(Activity activity){
return isAndroidPHasNotch(activity)
|| getInt("ro.miui.notch", activity) == 1
|| hasNotchAtHuawei(activity)
|| hasNotchAtOPPO(activity)
|| hasNotchAtVivo(activity);
}
/**
* Android P 刘海屏判断
* @param activity
* @return
*/
public static boolean isAndroidPHasNotch(Activity activity){
boolean result = false;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
DisplayCutout displayCutout = null;
try {
WindowInsets windowInsets = activity.getWindow().getDecorView().getRootWindowInsets();
if (windowInsets != null) {
displayCutout = windowInsets.getDisplayCutout();
}
if (displayCutout != null) {
result = true;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
/**
* 小米刘海屏判断.
* @return 0 if it is not notch ; return 1 means notch
* @throws IllegalArgumentException if the key exceeds 32 characters
*/
public static int getInt(String key,Activity activity) {
int result = 0;
if (isMiui()){
try {
ClassLoader classLoader = activity.getClassLoader();
@SuppressWarnings("rawtypes")
Class SystemProperties = classLoader.loadClass("android.os.SystemProperties");
//参数类型
@SuppressWarnings("rawtypes")
Class[] paramTypes = new Class[2];
paramTypes[0] = String.class;
paramTypes[1] = int.class;
Method getInt = SystemProperties.getMethod("getInt", paramTypes);
//参数
Object[] params = new Object[2];
params[0] = new String(key);
params[1] = new Integer(0);
result = (Integer) getInt.invoke(SystemProperties, params);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
return result;
}
/**
* 华为刘海屏判断
* @return
## 最后
答应大伙的备战金三银四,大厂面试真题来啦!
这份资料我从春招开始,就会将各博客、论坛。网站上等优质的Android开发中高级面试题收集起来,然后全网寻找最优的解答方案。每一道面试题都是百分百的大厂面经真题+最优解答。包知识脉络 + 诸多细节。
节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
**《960全网最全Android开发笔记》**

**《379页Android开发面试宝典》**
包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。
如何使用它?
1.可以通过目录索引直接翻看需要的知识点,查漏补缺。
2.五角星数表示面试问到的频率,代表重要推荐指数

**《507页Android开发相关源码解析》**
只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。
真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

**腾讯、字节跳动、阿里、百度等BAT大厂 2020-2021面试真题解析**

>资料收集不易,如果大家喜欢这篇文章,或者对你有帮助不妨多多点赞转发关注哦。文章会持续更新的。绝对干货!!!
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618156601)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
外链图片转存中...(img-yArkf2sN-1715649423916)]
**《507页Android开发相关源码解析》**
只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。
真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。
[外链图片转存中...(img-Pj1yClsQ-1715649423916)]
**腾讯、字节跳动、阿里、百度等BAT大厂 2020-2021面试真题解析**
[外链图片转存中...(img-JdWAuBUj-1715649423917)]
>资料收集不易,如果大家喜欢这篇文章,或者对你有帮助不妨多多点赞转发关注哦。文章会持续更新的。绝对干货!!!
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618156601)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)