├── .gitignore
├── LICENSE
├── README.md
├── README_ZH.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── huawei
│ │ └── hms
│ │ └── ads
│ │ └── sdk
│ │ ├── AdFormat.kt
│ │ ├── AdSampleAdapter.kt
│ │ ├── AdSampleApplication.kt
│ │ ├── AdsConstant.kt
│ │ ├── BannerActivity.kt
│ │ ├── BaseActivity.kt
│ │ ├── ConsentActivity.kt
│ │ ├── InstreamActivity.kt
│ │ ├── InterstitialActivity.kt
│ │ ├── MainActivity.kt
│ │ ├── NativeActivity.kt
│ │ ├── NativeViewFactory.kt
│ │ ├── ProtocolActivity.kt
│ │ ├── RewardActivity.kt
│ │ ├── SplashActivity.kt
│ │ └── dialogs
│ │ ├── ConsentDialog.kt
│ │ └── ProtocolDialog.kt
│ └── res
│ ├── drawable-v24
│ └── ic_launcher_foreground.xml
│ ├── drawable-xhdpi
│ ├── btn_check_off_emui.png
│ ├── btn_check_on_emui.png
│ ├── btn_check_on_pressed_emui.png
│ ├── ic_sb_cancel_gray.png
│ └── popup_full_bright_emui.9.png
│ ├── drawable-xxhdpi
│ ├── btn_default_disabled_emui.9.png
│ ├── btn_default_normal_emui.9.png
│ └── btn_default_pressed_emui.9.png
│ ├── drawable
│ ├── app_whythisad_info.xml
│ ├── btn_check_off_emui.png
│ ├── btn_check_on_emui.png
│ ├── btn_check_on_pressed_emui.png
│ ├── default_slogan.png
│ ├── default_slogan_landscape.png
│ ├── detail_checkbox_selector.xml
│ ├── emui_button_select.xml
│ ├── ic_launcher_background.xml
│ ├── native_button_rounded_corners_shape.xml
│ └── native_flag_rounded_corners_shape.xml
│ ├── layout
│ ├── activity_banner.xml
│ ├── activity_consent.xml
│ ├── activity_instream.xml
│ ├── activity_interstitial.xml
│ ├── activity_main.xml
│ ├── activity_native.xml
│ ├── activity_reward.xml
│ ├── activity_splash.xml
│ ├── dialog_consent.xml
│ ├── dialog_consent_content.xml
│ ├── dialog_consent_moreinfo.xml
│ ├── dialog_consent_partner_list.xml
│ ├── dialog_protocol.xml
│ ├── native_ad_with_app_download_btn_template.xml
│ ├── native_common_medium_template.xml
│ ├── native_image_only_template.xml
│ ├── native_small_image_template.xml
│ ├── native_small_template.xml
│ ├── native_three_images_template.xml
│ └── native_video_template.xml
│ ├── menu
│ └── ad_sample_menu.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ ├── ic_launcher_foreground.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ ├── ic_launcher_foreground.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ ├── ic_launcher_foreground.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ ├── ic_launcher_foreground.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ ├── ic_launcher_foreground.png
│ └── ic_launcher_round.png
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── ic_launcher_background.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle/*
3 | .idea/*
4 | /local.properties
5 | /build
6 | gradlew*
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright 2020 HUAWEI
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Petal Ads Demo for Kotlin
2 | English | [中文](https://github.com/HMS-Core/hms-ads-demo-kotlin/blob/master/README_ZH.md)
3 | ## Table of Contents
4 |
5 | * [Introduction](#introduction)
6 | * [Installation](#installation)
7 | * [Supported Environments](#supported-environments)
8 | * [Sample Code](#sample-code)
9 | * [License](#license)
10 |
11 | ## Introduction
12 | The HuaweiAdsSdk_Demo program demonstrates how to integrate the Petal Ads SDK into an Android app and display ads.
13 |
14 | ## Installation
15 | Install the program on Huawei Android mobile phones.
16 | You also can use HMS Toolkit to quickly integrate the kit and run the demo project, as well as debug the app using a remote device for free.
17 | For details, please visit [HMS Toolkit](https://developer.huawei.com/consumer/en/doc/development/Tools-Guides/getting-started-0000001077381096)。
18 |
19 | ## Supported Environments
20 | HMS Core (APK) 4.0.0 or later has been installed on Huawei Android phones.
21 |
22 | ## Sample Code
23 | The HuaweiAdsSdk_Demo program integrates the Petal Ads SDK and provides the pages for displaying banner, native, rewarded, interstitial, and splash ads, respectively.
24 | The following classes in the demo are used for loading and displaying ads and collecting user comments:
25 |
26 | 1. BannerActivity.kt
27 | Loads and displays banner ads.
28 | Code location: HuaweiAdsSdk_Demo\app\src\main\java\com\huawei\hms\ads\sdk\BannerActivity.kt
29 |
30 | 2. NativeActivity.kt
31 | Loads and displays native ads.
32 | Code location: HuaweiAdsSdk_Demo\app\src\main\java\com\huawei\hms\ads\sdk\NativeActivity.kt
33 |
34 | 3. RewardActivity.kt
35 | Loads and displays rewarded ads.
36 | Code location: HuaweiAdsSdk_Demo\app\src\main\java\com\huawei\hms\ads\sdk\RewardActivity.kt
37 |
38 | 4. InterstitialActivity.kt
39 | Loads and displays interstitial ads.
40 | Code location: HuaweiAdsSdk_Demo\app\src\main\java\com\huawei\hms\ads\sdk\InterstitialActivity.kt
41 |
42 | 5. SplashActivity.kt
43 | Loads and displays splash ads.
44 | Code location: HuaweiAdsSdk_Demo\app\src\main\java\com\huawei\hms\ads\sdk\SplashActivity.kt
45 |
46 | 6. ConsentActivity.kt
47 | Collects user consent.
48 | Code location: HuaweiAdsSdk_Demo\app\src\main\java\com\huawei\hms\ads\sdk\ConsentActivity.kt
49 |
50 | 7. ProtocolActivity.kt
51 | Collects user consent on privacy terms.
52 | Code location:HuaweiAdsSdk_Demo\app\src\main\java\com\huawei\hms\ads\sdk\ProtocolActivity.kt
53 |
54 | ## Question or issues
55 | If you want to evaluate more about HMS Core,
56 | [HMSCore on Reddit](https://www.reddit.com/r/HuaweiDevelopers/) is for you to keep up with latest news about HMS Core, and to exchange insights with other developers.
57 |
58 | If you have questions about how to use HMS samples, try the following options:
59 | - [Stack Overflow](https://stackoverflow.com/questions/tagged/huawei-mobile-services?tab=Votes) is the best place for any programming questions. Be sure to tag your question with
60 | `huawei-mobile-services`.
61 | - [Huawei Developer Forum](https://forums.developer.huawei.com/forumPortal/en/home?fid=0101187876626530001) HMS Core Module is great for general questions, or seeking recommendations and opinions.
62 |
63 | If you run into a bug in our samples, please submit an [issue](https://github.com/HMS-Core/hms-ads-demo-kotlin/issues) to the Repository. Even better you can submit a [Pull Request](https://github.com/HMS-Core/hms-ads-demo-kotlin/pulls) with a fix.
64 |
65 |
66 | ## License
67 | HuaweiAdsSdk_Demo is licensed under the [Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0).
68 |
--------------------------------------------------------------------------------
/README_ZH.md:
--------------------------------------------------------------------------------
1 | # 鲸鸿动能广告服务Kotlin示例代码
2 | 中文 | [English](https://github.com/HMS-Core/hms-ads-demo-kotlin)
3 | ## 目录
4 |
5 | * [简介](#简介)
6 | * [安装](#安装)
7 | * [环境要求](#环境要求)
8 | * [示例代码](#示例代码)
9 | * [授权许可](#授权许可)
10 |
11 | ## 简介
12 | 鲸鸿动能广告服务Kotlin示例代码向您介绍如何将鲸鸿动能SDK集成到安卓应用中,实现广告展示。
13 |
14 | ## 安装
15 | 在华为手机上安装该示例代码项目。
16 | 该示例也可以通过HMS Toolkit快速启动运行,且支持各Kit一站式集成,并提供远程真机免费调测等功能。了解更多信息,请参见[HMS Toolkit](https://developer.huawei.com/consumer/cn/doc/development/Tools-Guides/getting-started-0000001077381096)。
17 |
18 | ## 环境要求
19 | 在华为手机上安装HMS Core (APK) 4.0.0及以上版本。
20 |
21 | ## 示例代码
22 | 鲸鸿动能广告服务Kotlin示例代码集成了HMS Core Ads SDK,为您提供横幅广告、原生广告、激励广告、插屏广告、开屏广告和贴片广告的展示页面。
23 | 本示例代码包括以下六个文件,便于您进行广告加载、展示和用户意见征集:
24 |
25 | 1. BannerActivity.kt
26 | 用于加载、展示横幅广告。
27 | 代码位置: HuaweiAdsSdk_Demo\app\src\main\java\com\huawei\hms\ads\sdk\BannerActivity.kt
28 |
29 | 2. NativeActivity.kt
30 | 用于加载、展示原生广告。
31 | 代码位置: HuaweiAdsSdk_Demo\app\src\main\java\com\huawei\hms\ads\sdk\NativeActivity.kt
32 |
33 | 3. RewardActivity.kt
34 | 用于加载、展示激励广告。
35 | 代码位置: HuaweiAdsSdk_Demo\app\src\main\java\com\huawei\hms\ads\sdk\RewardActivity.kt
36 |
37 | 4. InterstitialActivity.kt
38 | 用于加载、展示插屏广告。
39 | 代码位置: HuaweiAdsSdk_Demo\app\src\main\java\com\huawei\hms\ads\sdk\InterstitialActivity.kt
40 |
41 | 5. SplashActivity.kt
42 | 用于加载、展示开屏广告。
43 | 代码位置: HuaweiAdsSdk_Demo\app\src\main\java\com\huawei\hms\ads\sdk\SplashActivity.kt
44 |
45 | 6. ConsentActivity.kt
46 | 用于征求用户意见。
47 | 代码位置: HuaweiAdsSdk_Demo\app\src\main\java\com\huawei\hms\ads\sdk\ConsentActivity.kt
48 |
49 | 7. ProtocolActivity.kt
50 | 用于收集用户对隐私条款的意见。
51 | 代码位置:HuaweiAdsSdk_Demo\app\src\main\java\com\huawei\hms\ads\sdk\ProtocolActivity.kt
52 |
53 | ## 技术支持
54 | 如果您对HMS Core还处于评估阶段,可在[Reddit社区](https://www.reddit.com/r/HuaweiDevelopers/)获取关于HMS Core的最新讯息,并与其他开发者交流见解。
55 |
56 | 如果您对使用HMS示例代码有疑问,请尝试:
57 | - 开发过程遇到问题上[Stack Overflow](https://stackoverflow.com/questions/tagged/huawei-mobile-services),在`huawei-mobile-services`标签下提问,有华为研发专家在线一对一解决您的问题。
58 | - 到[华为开发者论坛](https://forums.developer.huawei.com/forumPortal/en/home?fid=0101187876626530001) HMS Core板块与其他开发者进行交流。
59 |
60 | 如果您在尝试示例代码中遇到问题,请向仓库提交[issue](https://github.com/HMS-Core/hms-ads-demo-kotlin/issues),也欢迎您提交[Pull Request](https://github.com/HMS-Core/hms-ads-demo-kotlin/pulls)。
61 |
62 | ## 授权许可
63 | 鲸鸿动能广告服务Kotlin示例代码经过 [Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0)授权许可。
64 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | *.iml
3 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 |
4 | android {
5 | compileSdkVersion 29
6 | buildToolsVersion "29.0.2"
7 | defaultConfig {
8 | applicationId "com.huawei.hms.ads.sdk"
9 | minSdkVersion 19
10 | targetSdkVersion 29
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | compileOptions {
21 | sourceCompatibility JavaVersion.VERSION_1_8
22 | targetCompatibility JavaVersion.VERSION_1_8
23 | }
24 | }
25 |
26 | repositories {
27 | flatDir {
28 | dirs 'libs'
29 | }
30 | mavenCentral()
31 | }
32 |
33 | dependencies {
34 | implementation fileTree(dir: 'libs', include: ['*.jar'])
35 | implementation 'androidx.appcompat:appcompat:1.1.0'
36 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
37 | implementation 'com.huawei.hms:ads-lite:13.4.54.300'
38 | implementation 'com.huawei.hms:ads-consent:3.4.54.300'
39 | implementation "androidx.core:core-ktx:1.6.0"
40 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
41 | }
42 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 | -keep class com.huawei.openalliance.ad.** { *; }
23 | -keep class com.huawei.hms.ads.** { *; }
24 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
15 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
32 |
36 |
40 |
44 |
48 |
53 |
58 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/app/src/main/java/com/huawei/hms/ads/sdk/AdFormat.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package com.huawei.hms.ads.sdk
17 |
18 | class AdFormat(
19 | /**
20 | * Item name
21 | */
22 | val title: String,
23 | /**
24 | * Target activity
25 | */
26 | val targetClass: Class<*>)
--------------------------------------------------------------------------------
/app/src/main/java/com/huawei/hms/ads/sdk/AdSampleAdapter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package com.huawei.hms.ads.sdk
17 |
18 | import android.R
19 | import android.content.Context
20 | import android.view.LayoutInflater
21 | import android.view.View
22 | import android.view.ViewGroup
23 | import android.widget.ArrayAdapter
24 | import android.widget.TextView
25 |
26 | class AdSampleAdapter(private val mContext: Context, private val resourceId: Int, formatList: List?) : ArrayAdapter(mContext, resourceId, formatList!!) {
27 | override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
28 | val adFormat = getItem(position)
29 | val view = LayoutInflater.from(mContext).inflate(resourceId, parent, false)
30 | val title = view.findViewById(R.id.text1)
31 | title.text = adFormat!!.title
32 | return view
33 | }
34 |
35 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/huawei/hms/ads/sdk/AdSampleApplication.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package com.huawei.hms.ads.sdk
17 |
18 | import android.app.Application
19 | import com.huawei.hms.ads.HwAds
20 |
21 | class AdSampleApplication : Application() {
22 | override fun onCreate() {
23 | super.onCreate()
24 |
25 | // Initialize the Petal Ads SDK.
26 | HwAds.init(this)
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/java/com/huawei/hms/ads/sdk/AdsConstant.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package com.huawei.hms.ads.sdk
17 |
18 | object AdsConstant {
19 | /**
20 | * SharedPreferences name.
21 | */
22 | const val SP_NAME = "HuaweiAdsSdkSharedPreferences"
23 |
24 | /**
25 | * The SP key of protocol.
26 | */
27 | const val SP_PROTOCOL_KEY = "protocol"
28 |
29 | /**
30 | * The SP key of consent.
31 | */
32 | const val SP_CONSENT_KEY = "consent"
33 |
34 | /**
35 | * The SP default value of protocol.
36 | */
37 | const val DEFAULT_SP_PROTOCOL_VALUE = 0
38 |
39 | /**
40 | * The SP default value of consent.
41 | */
42 | const val DEFAULT_SP_CONSENT_VALUE = -1
43 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/huawei/hms/ads/sdk/BannerActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package com.huawei.hms.ads.sdk
17 |
18 | import android.graphics.Color
19 | import android.os.Bundle
20 | import android.view.View
21 | import android.widget.*
22 | import com.huawei.hms.ads.AdListener
23 | import com.huawei.hms.ads.AdParam
24 | import com.huawei.hms.ads.BannerAdSize
25 | import com.huawei.hms.ads.banner.BannerView
26 | import com.huawei.hms.ads.sdk.BannerActivity
27 | import java.util.*
28 |
29 | /**
30 | * Activity for displaying a banner ad.
31 | */
32 | class BannerActivity : BaseActivity() {
33 | private var bannerView: BannerView? = null
34 | private var defaultBannerView: BannerView? = null
35 | private var adFrameLayout: FrameLayout? = null
36 | private var sizeRadioGroup: RadioGroup? = null
37 | private var colorRadioGroup: RadioGroup? = null
38 |
39 | /**
40 | * Button tapping event listener.
41 | */
42 | private val buttonListener = View.OnClickListener { v ->
43 | defaultBannerView!!.visibility = View.INVISIBLE
44 | if (bannerView != null) {
45 | adFrameLayout!!.removeView(bannerView)
46 | bannerView!!.destroy()
47 | }
48 |
49 | // Call new BannerView(Context context) to create a BannerView class.
50 | bannerView = BannerView(v.context)
51 |
52 | // Set an ad slot ID.
53 | bannerView!!.adId = getString(R.string.banner_ad_id)
54 |
55 | // Set the background color and size based on user selection.
56 | val adSize = getBannerAdSize(sizeRadioGroup!!.checkedRadioButtonId)
57 | bannerView!!.bannerAdSize = adSize
58 | val color = getBannerViewBackground(colorRadioGroup!!.checkedRadioButtonId)
59 | bannerView!!.setBackgroundColor(color)
60 | adFrameLayout!!.addView(bannerView)
61 | bannerView!!.adListener = adListener
62 | bannerView!!.setBannerRefresh(60)
63 | bannerView!!.loadAd(AdParam.Builder().build())
64 | }
65 |
66 | /**
67 | * Ad listener.
68 | */
69 | private val adListener: AdListener = object : AdListener() {
70 | override fun onAdLoaded() {
71 | // Called when an ad is loaded successfully.
72 | showToast("Ad loaded.")
73 | }
74 |
75 | override fun onAdFailed(errorCode: Int) {
76 | // Called when an ad fails to be loaded.
77 | showToast(String.format(Locale.ROOT, "Ad failed to load with error code %d.", errorCode))
78 | }
79 |
80 | override fun onAdOpened() {
81 | // Called when an ad is opened.
82 | showToast(String.format("Ad opened "))
83 | }
84 |
85 | override fun onAdClicked() {
86 | // Called when a user taps an ad.
87 | showToast("Ad clicked")
88 | }
89 |
90 | override fun onAdLeave() {
91 | // Called when a user has left the app.
92 | showToast("Ad Leave")
93 | }
94 |
95 | override fun onAdClosed() {
96 | // Called when an ad is closed.
97 | showToast("Ad closed")
98 | }
99 | }
100 |
101 | override fun onCreate(savedInstanceState: Bundle?) {
102 | super.onCreate(savedInstanceState)
103 | title = getString(R.string.banner_ad)
104 | setContentView(R.layout.activity_banner)
105 | val bannerTitle = findViewById(R.id.text_banner)
106 | bannerTitle.text = "This is banner ads sample."
107 | sizeRadioGroup = findViewById(R.id.size_radioGroup)
108 | colorRadioGroup = findViewById(R.id.color_radioGroup)
109 |
110 | // Load the default banner ad.
111 | loadDefaultBannerAd()
112 |
113 | // Set the button for loading an ad.
114 | val loadButton = findViewById(R.id.refreshButton)
115 | loadButton.setOnClickListener(buttonListener)
116 | adFrameLayout = findViewById(R.id.ad_frame)
117 | }
118 |
119 | /**
120 | * Load the default banner ad.
121 | */
122 | private fun loadDefaultBannerAd() {
123 | // Obtain BannerView based on the configuration in layout/activity_main.xml.
124 | defaultBannerView = findViewById(R.id.hw_banner_view)
125 | defaultBannerView!!.adListener = adListener
126 | defaultBannerView!!.setBannerRefresh(REFRESH_TIME.toLong())
127 | val adParam = AdParam.Builder().build()
128 | defaultBannerView!!.loadAd(adParam)
129 | }
130 |
131 | private fun showToast(message: String) {
132 | Toast.makeText(this@BannerActivity, message, Toast.LENGTH_SHORT).show()
133 | }
134 |
135 | private fun getBannerAdSize(checkedId: Int): BannerAdSize? {
136 | var adSize: BannerAdSize? = null
137 | when (checkedId) {
138 | R.id.size_320_50 -> adSize = BannerAdSize.BANNER_SIZE_320_50
139 | R.id.size_320_100 -> adSize = BannerAdSize.BANNER_SIZE_320_100
140 | R.id.size_300_250 -> adSize = BannerAdSize.BANNER_SIZE_300_250
141 | R.id.size_smart -> adSize = BannerAdSize.BANNER_SIZE_SMART
142 | R.id.size_360_57 -> adSize = BannerAdSize.BANNER_SIZE_360_57
143 | R.id.size_360_144 -> adSize = BannerAdSize.BANNER_SIZE_360_144
144 | else -> {
145 | }
146 | }
147 | return adSize
148 | }
149 |
150 | private fun getBannerViewBackground(checkedId: Int): Int {
151 | var color = Color.TRANSPARENT
152 | when (checkedId) {
153 | R.id.color_white -> color = Color.WHITE
154 | R.id.color_black -> color = Color.BLACK
155 | R.id.color_red -> color = Color.RED
156 | R.id.color_transparent -> color = Color.TRANSPARENT
157 | else -> {
158 | }
159 | }
160 | return color
161 | }
162 |
163 | companion object {
164 | private const val REFRESH_TIME = 60
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/app/src/main/java/com/huawei/hms/ads/sdk/BaseActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package com.huawei.hms.ads.sdk
17 |
18 | import android.os.Bundle
19 | import androidx.appcompat.app.AppCompatActivity
20 |
21 | /**
22 | * This base activity for support navigate up within activity hierarchy from the action bar.
23 | */
24 | open class BaseActivity : AppCompatActivity() {
25 | override fun onCreate(savedInstanceState: Bundle?) {
26 | super.onCreate(savedInstanceState)
27 | val actionBar = supportActionBar
28 | actionBar!!.setDisplayHomeAsUpEnabled(true)
29 | }
30 |
31 | override fun onSupportNavigateUp(): Boolean {
32 | finish()
33 | return super.onSupportNavigateUp()
34 | }
35 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/huawei/hms/ads/sdk/ConsentActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package com.huawei.hms.ads.sdk
17 |
18 | import android.os.Bundle
19 | import android.util.Log
20 | import android.widget.TextView
21 | import android.widget.Toast
22 | import com.huawei.hms.ads.*
23 | import com.huawei.hms.ads.banner.BannerView
24 | import com.huawei.hms.ads.consent.bean.AdProvider
25 | import com.huawei.hms.ads.consent.constant.ConsentStatus
26 | import com.huawei.hms.ads.consent.constant.DebugNeedConsent
27 | import com.huawei.hms.ads.consent.inter.Consent
28 | import com.huawei.hms.ads.consent.inter.ConsentUpdateListener
29 | import com.huawei.hms.ads.sdk.ConsentActivity
30 | import com.huawei.hms.ads.sdk.dialogs.ConsentDialog
31 | import com.huawei.hms.ads.sdk.dialogs.ConsentDialog.ConsentDialogCallback
32 | import java.util.*
33 |
34 | /**
35 | * Activity for displaying consent.
36 | */
37 | class ConsentActivity : BaseActivity(), ConsentDialogCallback {
38 | private var adView: BannerView? = null
39 | private var adTypeTv: TextView? = null
40 | private var requestOptions: RequestOptions? = null
41 | private val mAdProviders: MutableList = ArrayList()
42 | override fun onCreate(savedInstanceState: Bundle?) {
43 | super.onCreate(savedInstanceState)
44 | title = getString(R.string.consent_settings)
45 | setContentView(R.layout.activity_consent)
46 | adTypeTv = findViewById(R.id.ad_load_tip)
47 | adView = findViewById(R.id.consent_ad_view)
48 |
49 | // Check consent status.
50 | checkConsentStatus()
51 | }
52 |
53 | /**
54 | * Check consent status.
55 | */
56 | private fun checkConsentStatus() {
57 | val consentInfo = Consent.getInstance(this)
58 |
59 | // To ensure that a dialog box is displayed each time you access the code demo, set ConsentStatus to UNKNOWN. In normal cases, the code does not need to be added.
60 | consentInfo.setConsentStatus(ConsentStatus.UNKNOWN)
61 | val testDeviceId = consentInfo.testDeviceId
62 | consentInfo.addTestDeviceId(testDeviceId)
63 |
64 | // After DEBUG_NEED_CONSENT is set, ensure that the consent is required even if a device is not located in a specified area.
65 | consentInfo.setDebugNeedConsent(DebugNeedConsent.DEBUG_NEED_CONSENT)
66 | consentInfo.requestConsentUpdate(object : ConsentUpdateListener {
67 | override fun onSuccess(consentStatus: ConsentStatus, isNeedConsent: Boolean, adProviders: List?) {
68 | Log.d(TAG, "ConsentStatus: $consentStatus, isNeedConsent: $isNeedConsent")
69 |
70 | // The parameter indicating whether the consent is required is returned.
71 | if (isNeedConsent) {
72 | // If ConsentStatus is set to UNKNOWN, re-collect user consent.
73 | if (consentStatus == ConsentStatus.UNKNOWN) {
74 | mAdProviders.clear()
75 | adProviders?.let { mAdProviders.addAll(it) }
76 | showConsentDialog()
77 | } else {
78 | // If ConsentStatus is set to PERSONALIZED or NON_PERSONALIZED, no dialog box is displayed to collect user consent.
79 | loadBannerAd(consentStatus.value)
80 | }
81 | } else {
82 | // If a country does not require your app to collect user consent before displaying ads, your app can request a personalized ad directly.
83 | Log.d(TAG, "User is NOT need Consent")
84 | loadBannerAd(ConsentStatus.PERSONALIZED.value)
85 | }
86 | }
87 |
88 | override fun onFail(errorDescription: String) {
89 | Log.e(TAG, "User's consent status failed to update: $errorDescription")
90 | Toast
91 | .makeText(this@ConsentActivity, "User's consent status failed to update: $errorDescription",
92 | Toast.LENGTH_LONG)
93 | .show()
94 |
95 | // In this demo,if the request fails ,you can load a non-personalized ad by default.
96 | loadBannerAd(ConsentStatus.NON_PERSONALIZED.value)
97 | }
98 | })
99 | }
100 |
101 | /**
102 | * Display the consent dialog box.
103 | */
104 | private fun showConsentDialog() {
105 | // Start to process the consent dialog box.
106 | val dialog = ConsentDialog(this, mAdProviders)
107 | dialog.setCallback(this)
108 | dialog.setCanceledOnTouchOutside(false)
109 | dialog.show()
110 | }
111 |
112 | override fun updateConsentStatus(consentStatus: ConsentStatus) {
113 | loadBannerAd(consentStatus.value)
114 | }
115 |
116 | private fun loadBannerAd(consentStatus: Int) {
117 | Log.d(TAG, "Load banner ad, consent status: $consentStatus")
118 | if (consentStatus == ConsentStatus.UNKNOWN.value) {
119 | removeBannerAd()
120 | }
121 |
122 | // Obtain global ad singleton variables and add personalized ad request parameters.
123 | requestOptions = if (HwAds.getRequestOptions() == null) {
124 | RequestOptions()
125 | } else {
126 | HwAds.getRequestOptions()
127 | }
128 |
129 | // For non-personalized ads, reset this parameter.
130 | requestOptions = requestOptions!!.toBuilder()
131 | .setTagForUnderAgeOfPromise(UnderAge.PROMISE_TRUE)
132 | .setNonPersonalizedAd(consentStatus)
133 | .build()
134 | HwAds.setRequestOptions(requestOptions)
135 | val adParam = AdParam.Builder().build()
136 | adView!!.adId = getString(R.string.banner_ad_id)
137 | adView!!.bannerAdSize = BannerAdSize.BANNER_SIZE_SMART
138 | adView!!.adListener = adListener
139 | adView!!.loadAd(adParam)
140 | updateTextViewTips(consentStatus)
141 | }
142 |
143 | private val adListener: AdListener = object : AdListener() {
144 | override fun onAdLoaded() {
145 | // Called when an ad is loaded successfully.
146 | Toast.makeText(this@ConsentActivity, "Ad loaded successfully", Toast.LENGTH_SHORT).show()
147 | }
148 |
149 | override fun onAdFailed(errorCode: Int) {
150 | // Called when an ad fails to be loaded.
151 | Toast.makeText(this@ConsentActivity, "Ad failed to load", Toast.LENGTH_SHORT).show()
152 | }
153 | }
154 |
155 | private fun removeBannerAd() {
156 | if (adView != null) {
157 | adView!!.removeAllViews()
158 | }
159 | updateTextViewTips(ConsentStatus.UNKNOWN.value)
160 | }
161 |
162 | private fun updateTextViewTips(consentStatus: Int) {
163 | when {
164 | ConsentStatus.NON_PERSONALIZED.value == consentStatus -> {
165 | adTypeTv!!.text = getString(R.string.load_non_personalized_text)
166 | }
167 | ConsentStatus.PERSONALIZED.value == consentStatus -> {
168 | adTypeTv!!.text = getString(R.string.load_personalized_text)
169 | }
170 | else -> { // ConsentStatus.UNKNOWN
171 | adTypeTv!!.text = getString(R.string.no_ads_text)
172 | }
173 | }
174 | }
175 |
176 | companion object {
177 | private val TAG = ConsentActivity::class.java.simpleName
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/app/src/main/java/com/huawei/hms/ads/sdk/InstreamActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package com.huawei.hms.ads.sdk
17 |
18 | import android.content.Context
19 | import android.content.Intent
20 | import android.net.Uri
21 | import android.os.Bundle
22 | import android.text.TextUtils
23 | import android.util.Log
24 | import android.view.View
25 | import android.widget.*
26 | import com.huawei.hms.ads.AdParam
27 | import com.huawei.hms.ads.MediaMuteListener
28 | import com.huawei.hms.ads.instreamad.*
29 | import com.huawei.hms.ads.instreamad.InstreamView.OnInstreamAdClickListener
30 | import java.util.*
31 |
32 | class InstreamActivity : BaseActivity() {
33 | private var videoContent: TextView? = null
34 | private var skipAd: TextView? = null
35 | private var countDown: TextView? = null
36 | private var callToAction: TextView? = null
37 | private var loadButton: Button? = null
38 | private var registerButton: Button? = null
39 | private var muteButton: Button? = null
40 | private var pauseButton: Button? = null
41 | private var instreamContainer: RelativeLayout? = null
42 | private var instreamView: InstreamView? = null
43 | private var whyThisAd: ImageView? = null
44 | private var context: Context? = null
45 | private var maxAdDuration = 0
46 | private var whyThisAdUrl: String? = null
47 | private var isMuted = false
48 | private var adLoader: InstreamAdLoader? = null
49 | private var instreamAds: List? = ArrayList()
50 | override fun onCreate(savedInstanceState: Bundle?) {
51 | super.onCreate(savedInstanceState)
52 | context = applicationContext
53 | setTitle(R.string.instream_ad)
54 | setContentView(R.layout.activity_instream)
55 | initInstreamAdView()
56 | initButtons()
57 | configAdLoader()
58 | }
59 |
60 | private val mediaChangeListener = InstreamMediaChangeListener { instreamAd ->
61 | whyThisAdUrl = null
62 | whyThisAdUrl = instreamAd.whyThisAd
63 | Log.i(TAG, "onSegmentMediaChange, whyThisAd: $whyThisAdUrl")
64 | if (!TextUtils.isEmpty(whyThisAdUrl)) {
65 | whyThisAd!!.visibility = View.VISIBLE
66 | whyThisAd!!.setOnClickListener { startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(whyThisAdUrl))) }
67 | } else {
68 | whyThisAd!!.visibility = View.GONE
69 | }
70 | val cta = instreamAd.callToAction
71 | if (!TextUtils.isEmpty(cta)) {
72 | callToAction!!.visibility = View.VISIBLE
73 | callToAction!!.text = cta
74 | instreamView!!.callToActionView = callToAction
75 | }
76 | }
77 | private val mediaStateListener: InstreamMediaStateListener = object : InstreamMediaStateListener {
78 | override fun onMediaProgress(per: Int, playTime: Int) {
79 | updateCountDown(playTime.toLong())
80 | }
81 |
82 | override fun onMediaStart(playTime: Int) {
83 | updateCountDown(playTime.toLong())
84 | }
85 |
86 | override fun onMediaPause(playTime: Int) {
87 | updateCountDown(playTime.toLong())
88 | }
89 |
90 | override fun onMediaStop(playTime: Int) {
91 | updateCountDown(playTime.toLong())
92 | }
93 |
94 | override fun onMediaCompletion(playTime: Int) {
95 | updateCountDown(playTime.toLong())
96 | playVideo()
97 | }
98 |
99 | override fun onMediaError(playTime: Int, errorCode: Int, extra: Int) {
100 | updateCountDown(playTime.toLong())
101 | }
102 | }
103 | private val mediaMuteListener: MediaMuteListener = object : MediaMuteListener {
104 | override fun onMute() {
105 | isMuted = true
106 | Toast.makeText(context, "Ad muted", Toast.LENGTH_SHORT).show()
107 | }
108 |
109 | override fun onUnmute() {
110 | isMuted = false
111 | Toast.makeText(context, "Ad unmuted", Toast.LENGTH_SHORT).show()
112 | }
113 | }
114 |
115 | private fun initInstreamAdView() {
116 | instreamContainer = findViewById(R.id.instream_ad_container)
117 | videoContent = findViewById(R.id.instream_video_content)
118 | skipAd = findViewById(R.id.instream_skip)
119 | skipAd!!.setOnClickListener(View.OnClickListener {
120 | if (null != instreamView) {
121 | instreamView!!.onClose()
122 | instreamView!!.destroy()
123 | instreamContainer!!.visibility = View.GONE
124 | }
125 | })
126 | countDown = findViewById(R.id.instream_count_down)
127 | callToAction = findViewById(R.id.instream_call_to_action)
128 | whyThisAd = findViewById(R.id.instream_why_this_ad)
129 | instreamView = findViewById(R.id.instream_view)
130 | instreamView!!.setInstreamMediaChangeListener(mediaChangeListener)
131 | instreamView!!.setInstreamMediaStateListener(mediaStateListener)
132 | instreamView!!.setMediaMuteListener(mediaMuteListener)
133 | instreamView!!.setOnInstreamAdClickListener(OnInstreamAdClickListener { Toast.makeText(context, "instream clicked.", Toast.LENGTH_SHORT).show() })
134 | }
135 |
136 | private val clickListener = View.OnClickListener { view ->
137 | when (view.id) {
138 | R.id.instream_load -> if (null != adLoader) {
139 | loadButton!!.text = getString(R.string.instream_loading)
140 | adLoader!!.loadAd(AdParam.Builder().build())
141 | }
142 | R.id.instream_register -> if (null == instreamAds || instreamAds!!.isEmpty()) {
143 | playVideo()
144 | } else {
145 | playInstreamAds(instreamAds!!)
146 | }
147 | R.id.instream_mute -> if (isMuted) {
148 | instreamView!!.unmute()
149 | muteButton!!.text = getString(R.string.instream_mute)
150 | } else {
151 | instreamView!!.mute()
152 | muteButton!!.text = getString(R.string.instream_unmute)
153 | }
154 | R.id.instream_pause_play -> if (instreamView!!.isPlaying) {
155 | instreamView!!.pause()
156 | pauseButton!!.text = getString(R.string.instream_play)
157 | } else {
158 | instreamView!!.play()
159 | pauseButton!!.text = getString(R.string.instream_pause)
160 | }
161 | else -> {
162 | }
163 | }
164 | }
165 |
166 | private fun initButtons() {
167 | loadButton = findViewById(R.id.instream_load)
168 | registerButton = findViewById(R.id.instream_register)
169 | muteButton = findViewById(R.id.instream_mute)
170 | pauseButton = findViewById(R.id.instream_pause_play)
171 | loadButton!!.setOnClickListener(clickListener)
172 | registerButton!!.setOnClickListener(clickListener)
173 | muteButton!!.setOnClickListener(clickListener)
174 | pauseButton!!.setOnClickListener(clickListener)
175 | }
176 |
177 | private val instreamAdLoadListener: InstreamAdLoadListener = object : InstreamAdLoadListener {
178 | override fun onAdLoaded(ads: MutableList) {
179 | if (null == ads || ads.size == 0) {
180 | playVideo()
181 | return
182 | }
183 | val it = ads.iterator()
184 | while (it.hasNext()) {
185 | val ad = it.next()
186 | if (ad.isExpired) {
187 | it.remove()
188 | }
189 | }
190 | if (ads.size == 0) {
191 | playVideo()
192 | return
193 | }
194 | loadButton!!.text = getString(R.string.instream_loaded)
195 | instreamAds = ads
196 | Toast.makeText(context, "onAdLoaded, ad size: " + ads.size + ", click REGISTER to play.", Toast.LENGTH_SHORT).show()
197 | }
198 |
199 | override fun onAdFailed(errorCode: Int) {
200 | Log.w(TAG, "onAdFailed: $errorCode")
201 | loadButton!!.text = getString(R.string.instream_load)
202 | Toast.makeText(context, "onAdFailed: $errorCode", Toast.LENGTH_SHORT).show()
203 | playVideo()
204 | }
205 | }
206 |
207 | private fun configAdLoader() {
208 | /**
209 | * if the maximum total duration is 60 seconds and the maximum number of roll ads is eight,
210 | * at most four 15-second roll ads or two 30-second roll ads will be returned.
211 | * If the maximum total duration is 120 seconds and the maximum number of roll ads is four,
212 | * no more roll ads will be returned after whichever is reached.
213 | */
214 | val totalDuration = 60
215 | val maxCount = 4
216 | val builder = InstreamAdLoader.Builder(context, getString(R.string.instream_ad_id))
217 | adLoader = builder.setTotalDuration(totalDuration)
218 | .setMaxCount(maxCount)
219 | .setInstreamAdLoadListener(instreamAdLoadListener)
220 | .build()
221 | }
222 |
223 | // play your normal video content.
224 | private fun playVideo() {
225 | hideAdViews()
226 | videoContent!!.setText(R.string.instream_normal_video_playing)
227 | }
228 |
229 | private fun hideAdViews() {
230 | instreamContainer!!.visibility = View.GONE
231 | }
232 |
233 | private fun playInstreamAds(ads: List) {
234 | maxAdDuration = getMaxInstreamDuration(ads)
235 | instreamContainer!!.visibility = View.VISIBLE
236 | loadButton!!.text = getString(R.string.instream_load)
237 | instreamView!!.setInstreamAds(ads)
238 | }
239 |
240 | private fun updateCountDown(playTime: Long) {
241 | val time = Math.round((maxAdDuration - playTime) / 1000.toFloat()).toString()
242 | runOnUiThread { countDown!!.text = time + "s" }
243 | }
244 |
245 | private fun getMaxInstreamDuration(ads: List): Int {
246 | var duration = 0
247 | for (ad in ads) {
248 | duration += ad.duration.toInt()
249 | }
250 | return duration
251 | }
252 |
253 | override fun onPause() {
254 | super.onPause()
255 | if (null != instreamView && instreamView!!.isPlaying) {
256 | instreamView!!.pause()
257 | pauseButton!!.text = getText(R.string.instream_play)
258 | }
259 | }
260 |
261 | override fun onResume() {
262 | super.onResume()
263 | if (null != instreamView && !instreamView!!.isPlaying) {
264 | instreamView!!.play()
265 | pauseButton!!.text = getText(R.string.instream_pause)
266 | }
267 | }
268 |
269 | override fun onDestroy() {
270 | super.onDestroy()
271 | if (null != instreamView) {
272 | instreamView!!.removeInstreamMediaStateListener()
273 | instreamView!!.removeInstreamMediaChangeListener()
274 | instreamView!!.removeMediaMuteListener()
275 | instreamView!!.destroy()
276 | }
277 | }
278 |
279 | companion object {
280 | private val TAG = InstreamActivity::class.java.simpleName
281 | }
282 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/huawei/hms/ads/sdk/InterstitialActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package com.huawei.hms.ads.sdk
17 |
18 | import android.os.Bundle
19 | import android.util.Log
20 | import android.view.View
21 | import android.widget.Button
22 | import android.widget.RadioGroup
23 | import android.widget.Toast
24 | import com.huawei.hms.ads.AdListener
25 | import com.huawei.hms.ads.AdParam
26 | import com.huawei.hms.ads.HwAds
27 | import com.huawei.hms.ads.InterstitialAd
28 |
29 | /**
30 | * Activity for displaying an interstitial ad.
31 | */
32 | class InterstitialActivity : BaseActivity() {
33 | private var displayRadioGroup: RadioGroup? = null
34 | private var loadAdButton: Button? = null
35 | private var interstitialAd: InterstitialAd? = null
36 | override fun onCreate(savedInstanceState: Bundle?) {
37 | super.onCreate(savedInstanceState)
38 | title = getString(R.string.interstitial_ad)
39 | setContentView(R.layout.activity_interstitial)
40 |
41 | // Initialize the Petal Ads SDK.
42 | HwAds.init(this)
43 | displayRadioGroup = findViewById(R.id.display_radio_group)
44 | loadAdButton = findViewById(R.id.load_ad)
45 | loadAdButton!!.setOnClickListener(View.OnClickListener { loadInterstitialAd() })
46 | }
47 |
48 | private val adListener: AdListener = object : AdListener() {
49 | override fun onAdLoaded() {
50 | super.onAdLoaded()
51 | showToast("Ad loaded")
52 | // Display an interstitial ad.
53 | showInterstitial()
54 | }
55 |
56 | override fun onAdFailed(errorCode: Int) {
57 | showToast("Ad load failed with error code: $errorCode")
58 | Log.d(TAG, "Ad load failed with error code: $errorCode")
59 | }
60 |
61 | override fun onAdClosed() {
62 | super.onAdClosed()
63 | showToast("Ad closed")
64 | Log.d(TAG, "onAdClosed")
65 | }
66 |
67 | override fun onAdClicked() {
68 | Log.d(TAG, "onAdClicked")
69 | super.onAdClicked()
70 | }
71 |
72 | override fun onAdOpened() {
73 | Log.d(TAG, "onAdOpened")
74 | super.onAdOpened()
75 | }
76 | }
77 |
78 | private fun loadInterstitialAd() {
79 | interstitialAd = InterstitialAd(this)
80 | interstitialAd!!.adId = adId
81 | interstitialAd!!.adListener = adListener
82 | val adParam = AdParam.Builder().build()
83 | interstitialAd!!.loadAd(adParam)
84 | }
85 |
86 | private val adId: String
87 | private get() = if (displayRadioGroup!!.checkedRadioButtonId == R.id.display_image) {
88 | getString(R.string.image_ad_id)
89 | } else {
90 | getString(R.string.video_ad_id)
91 | }
92 |
93 | private fun showInterstitial() {
94 | // Display an interstitial ad.
95 | if (interstitialAd != null && interstitialAd!!.isLoaded) {
96 | interstitialAd!!.show(this)
97 | } else {
98 | showToast("Ad did not load")
99 | }
100 | }
101 |
102 |
103 | private fun showToast(text: String) {
104 | runOnUiThread {
105 | Toast.makeText(this@InterstitialActivity, text, Toast.LENGTH_SHORT).show()
106 | }
107 | }
108 |
109 | companion object {
110 | private val TAG = InterstitialActivity::class.java.simpleName
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/app/src/main/java/com/huawei/hms/ads/sdk/MainActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package com.huawei.hms.ads.sdk
17 |
18 | import android.content.Context
19 | import android.content.Intent
20 | import android.content.res.Configuration
21 | import android.os.Bundle
22 | import android.os.Handler
23 | import android.os.Message
24 | import android.util.Log
25 | import android.view.Menu
26 | import android.view.MenuItem
27 | import android.widget.AdapterView.OnItemClickListener
28 | import android.widget.ListView
29 | import androidx.appcompat.app.AppCompatActivity
30 | import com.huawei.hms.ads.consent.bean.AdProvider
31 | import com.huawei.hms.ads.consent.constant.ConsentStatus
32 | import com.huawei.hms.ads.consent.constant.DebugNeedConsent
33 | import com.huawei.hms.ads.consent.inter.Consent
34 | import com.huawei.hms.ads.consent.inter.ConsentUpdateListener
35 | import com.huawei.hms.ads.sdk.MainActivity
36 | import com.huawei.hms.ads.sdk.dialogs.ConsentDialog
37 | import com.huawei.hms.ads.sdk.dialogs.ProtocolDialog
38 | import com.huawei.hms.ads.sdk.dialogs.ProtocolDialog.ProtocolDialogCallback
39 | import java.util.*
40 |
41 | class MainActivity : AppCompatActivity() {
42 | private var listView: ListView? = null
43 | private val adFormats: MutableList = ArrayList()
44 | private val mHandler = Handler(Handler.Callback { msg ->
45 | if (hasWindowFocus()) {
46 | when (msg.what) {
47 | PROTOCOL_MSG_TYPE -> showPrivacyDialog()
48 | CONSENT_MSG_TYPE -> checkConsentStatus()
49 | }
50 | }
51 | false
52 | })
53 |
54 | override fun onCreate(savedInstanceState: Bundle?) {
55 | super.onCreate(savedInstanceState)
56 | setContentView(R.layout.activity_main)
57 | initAdItems()
58 | listView = findViewById(R.id.item_list_view)
59 | val adapter = AdSampleAdapter(this@MainActivity, android.R.layout.simple_list_item_1, adFormats)
60 | listView!!.adapter = adapter
61 | listView!!.onItemClickListener = OnItemClickListener { parent, view, position, id ->
62 | val adFormat = adapter.getItem(position)
63 | val intent = Intent(applicationContext, adFormat!!.targetClass)
64 | startActivity(intent)
65 | }
66 |
67 | // Show the dialog for setting user privacy.
68 | sendMessage(PROTOCOL_MSG_TYPE, MSG_DELAY_MS)
69 | }
70 |
71 | private fun initAdItems() {
72 | adFormats.add(AdFormat(getString(R.string.banner_ad), BannerActivity::class.java))
73 | adFormats.add(AdFormat(getString(R.string.native_ad), NativeActivity::class.java))
74 | adFormats.add(AdFormat(getString(R.string.reward_ad), RewardActivity::class.java))
75 | adFormats.add(AdFormat(getString(R.string.interstitial_ad), InterstitialActivity::class.java))
76 | adFormats.add(AdFormat(getString(R.string.instream_ad), InstreamActivity::class.java))
77 | }
78 |
79 | /**
80 | * Display the app privacy protocol dialog box.
81 | */
82 | private fun showPrivacyDialog() {
83 | // If a user does not agree to the service agreement, the service agreement dialog is displayed.
84 | if (getPreferences(AdsConstant.SP_PROTOCOL_KEY, AdsConstant.DEFAULT_SP_PROTOCOL_VALUE) == 0) {
85 | Log.i(TAG, "Show protocol dialog.")
86 | val dialog = ProtocolDialog(this)
87 | dialog.setCallback(object : ProtocolDialogCallback {
88 | override fun agree() {
89 | sendMessage(CONSENT_MSG_TYPE, MSG_DELAY_MS)
90 | }
91 |
92 | override fun cancel() {
93 | // if the user selects the CANCEL button, exit application.
94 | finish()
95 | }
96 | })
97 | dialog.setCanceledOnTouchOutside(false)
98 | dialog.show()
99 | } else {
100 | sendMessage(CONSENT_MSG_TYPE, MSG_DELAY_MS)
101 | }
102 | }
103 |
104 | /**
105 | * If a user has not set consent, the consent dialog box is displayed.
106 | */
107 | private fun showConsentDialog(adProviders: List) {
108 | Log.i(TAG, "Show consent dialog.")
109 | val dialog = ConsentDialog(this, adProviders)
110 | dialog.setCanceledOnTouchOutside(false)
111 | dialog.show()
112 | }
113 |
114 | private fun getPreferences(key: String?, defValue: Int): Int {
115 | val preferences = getSharedPreferences(AdsConstant.SP_NAME, Context.MODE_PRIVATE)
116 | val value = preferences.getInt(key, defValue)
117 | Log.i(TAG, "Key:$key, Preference value is: $value")
118 | return value
119 | }
120 |
121 | private fun sendMessage(what: Int, delayMillis: Int) {
122 | val msg = Message.obtain()
123 | msg.what = what
124 | mHandler.sendMessageDelayed(msg, delayMillis.toLong())
125 | }
126 |
127 | override fun onCreateOptionsMenu(menu: Menu): Boolean {
128 | val inflater = menuInflater
129 | inflater.inflate(R.menu.ad_sample_menu, menu)
130 | return true
131 | }
132 |
133 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
134 | when (item.itemId) {
135 | R.id.privacy_settings -> startActivity(Intent(applicationContext, ProtocolActivity::class.java))
136 | R.id.consent_settings -> startActivity(Intent(applicationContext, ConsentActivity::class.java))
137 | }
138 | return super.onOptionsItemSelected(item)
139 | }
140 |
141 | override fun onConfigurationChanged(newConfig: Configuration) {
142 | super.onConfigurationChanged(newConfig)
143 | }
144 |
145 | private fun checkConsentStatus() {
146 | val adProviderList: MutableList = ArrayList()
147 | val consentInfo = Consent.getInstance(this)
148 | consentInfo.addTestDeviceId("********")
149 | consentInfo.setDebugNeedConsent(DebugNeedConsent.DEBUG_NEED_CONSENT)
150 | consentInfo.requestConsentUpdate(object : ConsentUpdateListener {
151 | override fun onSuccess(consentStatus: ConsentStatus?, isNeedConsent: Boolean, adProviders: List?) {
152 | Log.i(TAG, "ConsentStatus: $consentStatus, isNeedConsent: $isNeedConsent")
153 | if (isNeedConsent && consentStatus == ConsentStatus.UNKNOWN) {
154 | if (adProviders != null && adProviders.isNotEmpty()) {
155 | adProviderList.addAll(adProviders)
156 | }
157 | showConsentDialog(adProviderList)
158 | }
159 | }
160 |
161 | override fun onFail(errorDescription: String?) {
162 | Log.e(TAG, "User's consent status failed to update: $errorDescription")
163 | if (getPreferences(AdsConstant.SP_CONSENT_KEY, AdsConstant.DEFAULT_SP_CONSENT_VALUE) < 0) {
164 | // In this example, if the request fails, the consent dialog box is still displayed. In this case, the ad publisher list is empty.
165 | showConsentDialog(adProviderList)
166 | }
167 | }
168 | })
169 | }
170 |
171 | companion object {
172 | private val TAG = MainActivity::class.java.simpleName
173 | private const val PROTOCOL_MSG_TYPE = 100
174 | private const val CONSENT_MSG_TYPE = 200
175 | private const val MSG_DELAY_MS = 1000
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/app/src/main/java/com/huawei/hms/ads/sdk/NativeActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package com.huawei.hms.ads.sdk
17 |
18 | import android.os.Bundle
19 | import android.util.Log
20 | import android.view.View
21 | import android.view.ViewGroup
22 | import android.widget.*
23 | import com.huawei.hms.ads.AdListener
24 | import com.huawei.hms.ads.AdParam
25 | import com.huawei.hms.ads.VideoConfiguration
26 | import com.huawei.hms.ads.nativead.*
27 |
28 | class NativeActivity : BaseActivity() {
29 |
30 | private lateinit var bigImage: RadioButton
31 | private lateinit var threeSmall: RadioButton
32 | private lateinit var smallImage: RadioButton
33 | private lateinit var videoWithText: RadioButton
34 | private lateinit var appDownloadBtn: RadioButton
35 | private lateinit var loadBtn: Button
36 | private lateinit var adScrollView: ScrollView
37 | private var globalNativeAd: NativeAd? = null
38 |
39 | override fun onCreate(savedInstanceState: Bundle?) {
40 | super.onCreate(savedInstanceState)
41 | setContentView(R.layout.activity_native)
42 |
43 | bigImage = findViewById(R.id.radio_button_large)
44 | threeSmall = findViewById(R.id.radio_button_three_small)
45 | smallImage = findViewById(R.id.radio_button_small)
46 | videoWithText = findViewById(R.id.radio_button_video)
47 | appDownloadBtn = findViewById(R.id.radio_button_app_download_button)
48 |
49 | loadBtn = findViewById(R.id.btn_load)
50 | adScrollView = findViewById(R.id.scroll_view_ad)
51 |
52 | loadBtn.setOnClickListener(View.OnClickListener { loadAd(getAdId()) })
53 |
54 | loadAd(getAdId())
55 | }
56 |
57 | /**
58 | * Initialize ad slot ID and layout template.
59 | *
60 | * @return ad slot ID
61 | */
62 | private fun getAdId(): String {
63 | var adId = getString(R.string.ad_id_native)
64 | when {
65 | bigImage!!.isChecked -> {
66 | adId = getString(R.string.ad_id_native)
67 | }
68 | smallImage!!.isChecked -> {
69 | adId = getString(R.string.ad_id_native_small)
70 | }
71 | threeSmall!!.isChecked -> {
72 | adId = getString(R.string.ad_id_native_three)
73 | }
74 | videoWithText!!.isChecked -> {
75 | adId = getString(R.string.ad_id_native_video)
76 | }
77 | appDownloadBtn!!.isChecked -> {
78 | adId = getString(R.string.ad_id_native_video)
79 | }
80 | }
81 | return adId
82 | }
83 |
84 | /**
85 | * Load a native ad.
86 | *
87 | * @param adId ad slot ID.
88 | */
89 | private fun loadAd(adId: String) {
90 | updateStatus(null, false)
91 | val builder = NativeAdLoader.Builder(this, adId)
92 | builder.setNativeAdLoadedListener { nativeAd -> // Call this method when an ad is successfully loaded.
93 | updateStatus(getString(R.string.status_load_ad_success), true)
94 |
95 | // Display native ad.
96 | showNativeAd(nativeAd)
97 | }.setAdListener(object : AdListener() {
98 | override fun onAdLoaded() {
99 | updateStatus(getString(R.string.status_load_ad_finish), true)
100 | }
101 |
102 | override fun onAdFailed(errorCode: Int) {
103 | // Call this method when an ad fails to be loaded.
104 | updateStatus(getString(R.string.status_load_ad_fail) + errorCode, true)
105 | }
106 | })
107 | val videoConfiguration = VideoConfiguration.Builder()
108 | .setStartMuted(true)
109 | .build()
110 | val adConfiguration = NativeAdConfiguration.Builder()
111 | .setChoicesPosition(NativeAdConfiguration.ChoicesPosition.BOTTOM_RIGHT) // Set custom attributes.
112 | .setVideoConfiguration(videoConfiguration)
113 | .setRequestMultiImages(true)
114 | .build()
115 | val nativeAdLoader = builder.setNativeAdOptions(adConfiguration).build()
116 | nativeAdLoader.loadAd(AdParam.Builder().build())
117 | updateStatus(getString(R.string.status_ad_loading), false)
118 | }
119 |
120 | /**
121 | * Display native ad.
122 | *
123 | * @param nativeAd native ad object that contains ad materials.
124 | */
125 | private fun showNativeAd(nativeAd: NativeAd) {
126 | // Destroy the original native ad.
127 | if (null != globalNativeAd) {
128 | globalNativeAd!!.destroy()
129 | }
130 | globalNativeAd = nativeAd
131 | val nativeView: View = createNativeView(nativeAd, adScrollView)!!
132 | if (nativeView != null) {
133 | globalNativeAd!!.setDislikeAdListener { // Call this method when an ad is closed.
134 | updateStatus(getString(R.string.ad_is_closed), true)
135 | adScrollView.removeView(nativeView)
136 | }
137 |
138 | // Add NativeView to the app UI.
139 | adScrollView.removeAllViews()
140 | adScrollView.addView(nativeView)
141 | }
142 | }
143 |
144 | /**
145 | * Create a nativeView by creativeType and fill in ad material.
146 | *
147 | * @param nativeAd native ad object that contains ad materials.
148 | * @param parentView parent view of nativeView.
149 | */
150 | private fun createNativeView(nativeAd: NativeAd, parentView: ViewGroup): View? {
151 | val createType = nativeAd.creativeType
152 | Log.i(TAG, "Native ad createType is $createType")
153 | if (createType == 2 || createType == 102) {
154 | // Large image
155 | return NativeViewFactory.createImageOnlyAdView(nativeAd, parentView)
156 | } else if (createType == 3 || createType == 6) {
157 | // Large image with text or video with text
158 | return NativeViewFactory.createMediumAdView(nativeAd, parentView)
159 | } else if (createType == 103 || createType == 106) {
160 | // Large image with text or Video with text, using AppDownloadButton template.
161 | return NativeViewFactory.createAppDownloadButtonAdView(nativeAd, parentView)
162 | } else if (createType == 7 || createType == 107) {
163 | // Small image with text-
164 | return NativeViewFactory.createSmallImageAdView(nativeAd, parentView)
165 | } else if (createType == 8 || createType == 108) {
166 | // Three small images with text
167 | return NativeViewFactory.createThreeImagesAdView(nativeAd, parentView)
168 | } else {
169 | return null
170 | }
171 | }
172 |
173 | /**
174 | * Update tip and status of the load button.
175 | *
176 | * @param text tip.
177 | * @param loadBtnEnabled status of the load button.
178 | */
179 | private fun updateStatus(text: String?, loadBtnEnabled: Boolean) {
180 | if (null != text) {
181 | Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
182 | }
183 | loadBtn.isEnabled = loadBtnEnabled
184 | }
185 |
186 | override fun onDestroy() {
187 | if (null != globalNativeAd) {
188 | globalNativeAd!!.destroy()
189 | }
190 | super.onDestroy()
191 | }
192 |
193 | companion object{
194 | private val TAG = NativeActivity::class.java.simpleName
195 | }
196 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/huawei/hms/ads/sdk/NativeViewFactory.kt:
--------------------------------------------------------------------------------
1 | package com.huawei.hms.ads.sdk
2 |
3 | import android.content.Context
4 | import android.util.Log
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.view.ViewGroup
8 | import android.widget.Button
9 | import android.widget.ImageView
10 | import android.widget.TextView
11 | import com.huawei.hms.ads.AppDownloadButton
12 | import com.huawei.hms.ads.AppDownloadButtonStyle
13 | import com.huawei.hms.ads.VideoOperator.VideoLifecycleListener
14 | import com.huawei.hms.ads.nativead.MediaView
15 | import com.huawei.hms.ads.nativead.NativeAd
16 | import com.huawei.hms.ads.nativead.NativeView
17 |
18 | class NativeViewFactory {
19 |
20 | companion object {
21 |
22 | private val TAG = NativeViewFactory::class.java.simpleName
23 |
24 | fun createMediumAdView(nativeAd: NativeAd, parentView: ViewGroup): View? {
25 | val inflater = LayoutInflater.from(parentView.context)
26 | val adRootView: View = inflater.inflate(R.layout.native_common_medium_template, null)
27 | val nativeView: NativeView = adRootView.findViewById(R.id.native_medium_view)
28 | nativeView.titleView = adRootView.findViewById(R.id.ad_title)
29 | nativeView.mediaView = adRootView.findViewById(R.id.ad_media) as MediaView
30 | nativeView.adSourceView = adRootView.findViewById(R.id.ad_source)
31 | nativeView.callToActionView = adRootView.findViewById(R.id.ad_call_to_action)
32 |
33 | // Populate a native ad material view.
34 | (nativeView.titleView as TextView).text = nativeAd.title
35 | nativeView.mediaView.setMediaContent(nativeAd.mediaContent)
36 | if (null != nativeAd.adSource) {
37 | (nativeView.adSourceView as TextView).text = nativeAd.adSource
38 | }
39 | nativeView.adSourceView.visibility =
40 | if (null != nativeAd.adSource) View.VISIBLE else View.INVISIBLE
41 | if (null != nativeAd.callToAction) {
42 | (nativeView.callToActionView as Button).text = nativeAd.callToAction
43 | }
44 | nativeView.callToActionView.visibility =
45 | if (null != nativeAd.callToAction) View.VISIBLE else View.INVISIBLE
46 |
47 | // Obtain a video controller.
48 | val videoOperator = nativeAd.videoOperator
49 |
50 | // Check whether a native ad contains video materials.
51 | if (videoOperator.hasVideo()) {
52 | // Add a video lifecycle event listener.
53 | videoOperator.videoLifecycleListener = object : VideoLifecycleListener() {
54 | override fun onVideoStart() {
55 | Log.i(NativeViewFactory.TAG, "NativeAd video play start.")
56 | }
57 |
58 | override fun onVideoPlay() {
59 | Log.i(NativeViewFactory.TAG, "NativeAd video playing.")
60 | }
61 |
62 | override fun onVideoEnd() {
63 | Log.i(NativeViewFactory.TAG, "NativeAd video play end.")
64 | }
65 | }
66 | }
67 |
68 | // Register a native ad object.
69 | nativeView.setNativeAd(nativeAd)
70 | return nativeView
71 | }
72 |
73 |
74 | fun createSmallImageAdView(nativeAd: NativeAd, parentView: ViewGroup): View? {
75 | val inflater = LayoutInflater.from(parentView.context)
76 | val adRootView: View = inflater.inflate(R.layout.native_small_image_template, null)
77 | val nativeView: NativeView = adRootView.findViewById(R.id.native_small_view)
78 | nativeView.titleView = adRootView.findViewById(R.id.ad_title)
79 | nativeView.mediaView = adRootView.findViewById(R.id.ad_media) as MediaView
80 | nativeView.adSourceView = adRootView.findViewById(R.id.ad_source)
81 | nativeView.callToActionView = adRootView.findViewById(R.id.ad_call_to_action)
82 |
83 | // Populate a native ad material view.
84 | (nativeView.titleView as TextView).text = nativeAd.title
85 | nativeView.mediaView.setMediaContent(nativeAd.mediaContent)
86 | if (null != nativeAd.adSource) {
87 | (nativeView.adSourceView as TextView).text = nativeAd.adSource
88 | }
89 | nativeView.adSourceView.visibility =
90 | if (null != nativeAd.adSource) View.VISIBLE else View.INVISIBLE
91 | if (null != nativeAd.callToAction) {
92 | (nativeView.callToActionView as Button).text = nativeAd.callToAction
93 | }
94 | nativeView.callToActionView.visibility =
95 | if (null != nativeAd.callToAction) View.VISIBLE else View.INVISIBLE
96 |
97 | // Register a native ad object.
98 | nativeView.setNativeAd(nativeAd)
99 | return nativeView
100 | }
101 |
102 | fun createThreeImagesAdView(nativeAd: NativeAd, parentView: ViewGroup): View? {
103 | val inflater = LayoutInflater.from(parentView.context)
104 | val adRootView: View = inflater.inflate(R.layout.native_three_images_template, null)
105 | val nativeView: NativeView = adRootView.findViewById(R.id.native_three_images)
106 | nativeView.titleView = adRootView.findViewById(R.id.ad_title)
107 | nativeView.adSourceView = adRootView.findViewById(R.id.ad_source)
108 | nativeView.callToActionView = adRootView.findViewById(R.id.ad_call_to_action)
109 | val imageView1 = adRootView.findViewById(R.id.image_view_1)
110 | val imageView2 = adRootView.findViewById(R.id.image_view_2)
111 | val imageView3 = adRootView.findViewById(R.id.image_view_3)
112 |
113 | // Populate a native ad material view.
114 | (nativeView.titleView as TextView).text = nativeAd.title
115 | if (null != nativeAd.adSource) {
116 | (nativeView.adSourceView as TextView).text = nativeAd.adSource
117 | }
118 | nativeView.adSourceView.visibility =
119 | if (null != nativeAd.adSource) View.VISIBLE else View.INVISIBLE
120 | if (null != nativeAd.callToAction) {
121 | (nativeView.callToActionView as Button).text = nativeAd.callToAction
122 | }
123 | nativeView.callToActionView.visibility =
124 | if (null != nativeAd.callToAction) View.VISIBLE else View.INVISIBLE
125 | if (nativeAd.images != null && nativeAd.images.size >= 3) {
126 | imageView1.setImageDrawable(nativeAd.images[0].drawable)
127 | imageView2.setImageDrawable(nativeAd.images[1].drawable)
128 | imageView3.setImageDrawable(nativeAd.images[2].drawable)
129 | }
130 |
131 | // Register a native ad object.
132 | nativeView.setNativeAd(nativeAd)
133 | return nativeView
134 | }
135 |
136 | fun createAppDownloadButtonAdView(nativeAd: NativeAd, parentView: ViewGroup): View? {
137 | val inflater = LayoutInflater.from(parentView.context)
138 | val adRootView: View =
139 | inflater.inflate(R.layout.native_ad_with_app_download_btn_template, null)
140 | val nativeView: NativeView = adRootView.findViewById(R.id.native_app_download_button_view)
141 | nativeView.titleView = adRootView.findViewById(R.id.ad_title)
142 | nativeView.mediaView = adRootView.findViewById(R.id.ad_media) as MediaView
143 | nativeView.adSourceView = adRootView.findViewById(R.id.ad_source)
144 | nativeView.callToActionView = adRootView.findViewById(R.id.ad_call_to_action)
145 |
146 | // Populate a native ad material view.
147 | (nativeView.titleView as TextView).text = nativeAd.title
148 | nativeView.mediaView.setMediaContent(nativeAd.mediaContent)
149 | if (null != nativeAd.adSource) {
150 | (nativeView.adSourceView as TextView).text = nativeAd.adSource
151 | }
152 | nativeView.adSourceView.visibility =
153 | if (null != nativeAd.adSource) View.VISIBLE else View.INVISIBLE
154 | if (null != nativeAd.callToAction) {
155 | (nativeView.callToActionView as Button).text = nativeAd.callToAction
156 | }
157 |
158 | // Register a native ad object.
159 | nativeView.setNativeAd(nativeAd)
160 | val appDownloadButton: AppDownloadButton = nativeView.findViewById(R.id.app_download_btn)
161 | appDownloadButton.setAppDownloadButtonStyle(NativeViewFactory.MyAppDownloadStyle(parentView.context))
162 | if (nativeView.register(appDownloadButton)) {
163 | appDownloadButton.visibility = View.VISIBLE
164 | appDownloadButton.refreshAppStatus()
165 | nativeView.callToActionView.visibility = View.GONE
166 | } else {
167 | appDownloadButton.visibility = View.GONE
168 | nativeView.callToActionView.visibility = View.VISIBLE
169 | }
170 | return nativeView
171 | }
172 |
173 | fun createImageOnlyAdView(nativeAd: NativeAd, parentView: ViewGroup): View? {
174 | val inflater = LayoutInflater.from(parentView.context)
175 | val adRootView: View = inflater.inflate(R.layout.native_image_only_template, null)
176 | val nativeView: NativeView = adRootView.findViewById(R.id.native_image_only_view)
177 | nativeView.mediaView = adRootView.findViewById(R.id.ad_media) as MediaView
178 | nativeView.callToActionView = adRootView.findViewById(R.id.ad_call_to_action)
179 | nativeView.mediaView.setMediaContent(nativeAd.mediaContent)
180 | if (null != nativeAd.callToAction) {
181 | (nativeView.callToActionView as Button).text = nativeAd.callToAction
182 | }
183 | nativeView.callToActionView.visibility =
184 | if (null != nativeAd.callToAction) View.VISIBLE else View.INVISIBLE
185 |
186 | // Register a native ad object.
187 | nativeView.setNativeAd(nativeAd)
188 | return nativeView
189 | }
190 |
191 | }
192 |
193 | /**
194 | * Custom AppDownloadButton Style
195 | */
196 | private class MyAppDownloadStyle(context: Context) :
197 | AppDownloadButtonStyle(context) {
198 | init {
199 | normalStyle.textColor = context.resources.getColor(R.color.white)
200 | normalStyle.background = context.resources.getDrawable(R.drawable.native_button_rounded_corners_shape)
201 | processingStyle.textColor = context.resources.getColor(R.color.black)
202 | }
203 | }
204 |
205 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/huawei/hms/ads/sdk/ProtocolActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package com.huawei.hms.ads.sdk
17 |
18 | import android.os.Bundle
19 | import com.huawei.hms.ads.sdk.dialogs.ProtocolDialog
20 | import com.huawei.hms.ads.sdk.dialogs.ProtocolDialog.ProtocolDialogCallback
21 |
22 | /**
23 | * Activity for displaying privacy information.
24 | */
25 | class ProtocolActivity : BaseActivity(), ProtocolDialogCallback {
26 | override fun onCreate(savedInstanceState: Bundle?) {
27 | super.onCreate(savedInstanceState)
28 | title = getString(R.string.privacy_settings)
29 | showProtocolDialog()
30 | }
31 |
32 | /**
33 | * Display a protocol dialog.
34 | */
35 | private fun showProtocolDialog() {
36 | // Start to process the protocol dialog box.
37 | val dialog = ProtocolDialog(this)
38 | dialog.setCallback(this)
39 | dialog.setCanceledOnTouchOutside(false)
40 | dialog.show()
41 | }
42 |
43 | override fun agree() {
44 | finish()
45 | }
46 |
47 | override fun cancel() {
48 | finish()
49 | }
50 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/huawei/hms/ads/sdk/RewardActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package com.huawei.hms.ads.sdk
17 |
18 | import android.os.Bundle
19 | import android.view.View
20 | import android.widget.Button
21 | import android.widget.TextView
22 | import android.widget.Toast
23 | import com.huawei.hms.ads.AdParam
24 | import com.huawei.hms.ads.reward.Reward
25 | import com.huawei.hms.ads.reward.RewardAd
26 | import com.huawei.hms.ads.reward.RewardAdLoadListener
27 | import com.huawei.hms.ads.reward.RewardAdStatusListener
28 | import java.util.*
29 |
30 | /**
31 | * Activity for displaying a rewarded ad.
32 | */
33 | class RewardActivity : BaseActivity() {
34 | private var rewardedTitle: TextView? = null
35 | private var scoreView: TextView? = null
36 | private var reStartButton: Button? = null
37 | private var watchAdButton: Button? = null
38 | private var rewardedAd: RewardAd? = null
39 | private var score = 1
40 | private val defaultScore = 10
41 | override fun onCreate(savedInstanceState: Bundle?) {
42 | super.onCreate(savedInstanceState)
43 | title = getString(R.string.reward_ad)
44 | setContentView(R.layout.activity_reward)
45 | rewardedTitle = findViewById(R.id.text_reward)
46 | rewardedTitle!!.setText(R.string.reward_ad_title)
47 |
48 | // Load a rewarded ad.
49 | loadRewardAd()
50 |
51 | // Load a score view.
52 | loadScoreView()
53 |
54 | // Load the button for watching a rewarded ad.
55 | loadWatchButton()
56 |
57 | // Load the button for starting a game.
58 | loadPlayButton()
59 | }
60 |
61 | /**
62 | * Load a rewarded ad.
63 | */
64 | private fun loadRewardAd() {
65 | if (rewardedAd == null) {
66 | rewardedAd = RewardAd(this@RewardActivity, getString(R.string.ad_id_reward))
67 | }
68 | val rewardAdLoadListener: RewardAdLoadListener = object : RewardAdLoadListener() {
69 | override fun onRewardAdFailedToLoad(errorCode: Int) {
70 | showToast("onRewardAdFailedToLoad errorCode is :$errorCode");
71 | }
72 |
73 | override fun onRewardedLoaded() {
74 | showToast("onRewardedLoaded")
75 | }
76 | }
77 | rewardedAd!!.loadAd(AdParam.Builder().build(), rewardAdLoadListener)
78 | }
79 |
80 | /**
81 | * Display a rewarded ad.
82 | */
83 | private fun rewardAdShow() {
84 | if (rewardedAd!!.isLoaded) {
85 | rewardedAd!!.show(this@RewardActivity, object : RewardAdStatusListener() {
86 | override fun onRewardAdClosed() {
87 | showToast("onRewardAdClosed")
88 | loadRewardAd()
89 | }
90 |
91 | override fun onRewardAdFailedToShow(errorCode: Int) {
92 | showToast("onRewardAdFailedToShow errorCode is :$errorCode")
93 | }
94 |
95 | override fun onRewardAdOpened() {
96 | showToast("onRewardAdOpened")
97 | }
98 |
99 | override fun onRewarded(reward: Reward) {
100 | // You are advised to grant a reward immediately and at the same time, check whether the reward
101 | // takes effect on the server. If no reward information is configured, grant a reward based on the
102 | // actual scenario.
103 | val addScore = if (reward.amount == 0) defaultScore else reward.amount
104 | showToast("Watch video show finished , add $addScore scores")
105 | score += addScore
106 | setScore(score)
107 | loadRewardAd()
108 | }
109 | })
110 | }
111 | }
112 |
113 | private fun showToast(text: String) {
114 | runOnUiThread {
115 | Toast.makeText(this@RewardActivity, text, Toast.LENGTH_SHORT).show()
116 | }
117 | }
118 |
119 | /**
120 | * Set a score.
121 | *
122 | * @param score
123 | */
124 | private fun setScore(score: Int) {
125 | scoreView!!.text = "Score:$score"
126 | }
127 |
128 | /**
129 | * Load the button for watching a rewarded ad.
130 | */
131 | private fun loadWatchButton() {
132 | watchAdButton = findViewById(R.id.show_video_button)
133 | watchAdButton!!.setOnClickListener(View.OnClickListener { rewardAdShow() })
134 | }
135 |
136 | /**
137 | * Load the button for starting a game.
138 | */
139 | private fun loadPlayButton() {
140 | reStartButton = findViewById(R.id.play_button)
141 | reStartButton!!.setOnClickListener(View.OnClickListener { play() })
142 | }
143 |
144 | private fun loadScoreView() {
145 | scoreView = findViewById(R.id.score_count_text)
146 | scoreView!!.text = "Score:$score"
147 | }
148 |
149 | /**
150 | * Used to play a game.
151 | */
152 | private fun play() {
153 | // If the score is 0, a message is displayed, asking users to watch the ad in exchange for scores.
154 | if (score == 0) {
155 | Toast.makeText(this@RewardActivity, "Watch video ad to add score", Toast.LENGTH_SHORT).show()
156 | return
157 | }
158 |
159 | // The value 0 or 1 is returned randomly. If the value is 1, the score increases by 1. If the value is 0, the
160 | // score decreases by 5. If the score is a negative number, the score is set to 0.
161 | val random = Random().nextInt(RANGE)
162 | if (random == 1) {
163 | score += PLUS_SCORE
164 | Toast.makeText(this@RewardActivity, "You win!", Toast.LENGTH_SHORT).show()
165 | } else {
166 | score -= MINUS_SCORE
167 | score = if (score < 0) 0 else score
168 | Toast.makeText(this@RewardActivity, "You lose!", Toast.LENGTH_SHORT).show()
169 | }
170 | setScore(score)
171 | }
172 |
173 | companion object {
174 | private const val PLUS_SCORE = 1
175 | private const val MINUS_SCORE = 5
176 | private const val RANGE = 2
177 | }
178 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/huawei/hms/ads/sdk/SplashActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package com.huawei.hms.ads.sdk
17 |
18 | import android.app.Activity
19 | import android.content.Intent
20 | import android.content.pm.ActivityInfo
21 | import android.content.res.Configuration
22 | import android.os.Bundle
23 | import android.os.Handler
24 | import android.util.Log
25 | import android.widget.Toast
26 | import com.huawei.hms.ads.AdParam
27 | import com.huawei.hms.ads.AudioFocusType
28 | import com.huawei.hms.ads.sdk.SplashActivity
29 | import com.huawei.hms.ads.splash.SplashAdDisplayListener
30 | import com.huawei.hms.ads.splash.SplashView
31 | import com.huawei.hms.ads.splash.SplashView.SplashAdLoadListener
32 |
33 | class SplashActivity : Activity() {
34 | /**
35 | * Pause flag.
36 | * On the splash ad screen:
37 | * Set this parameter to true when exiting the app to ensure that the app home screen is not displayed.
38 | * Set this parameter to false when returning to the splash ad screen from another screen to ensure that the app home screen can be displayed properly.
39 | */
40 | private var hasPaused = false
41 |
42 | // Callback handler used when the ad display timeout message is received.
43 | private val timeoutHandler = Handler(Handler.Callback {
44 | if (hasWindowFocus()) {
45 | jump()
46 | }
47 | false
48 | })
49 | private var splashView: SplashView? = null
50 | private val splashAdLoadListener: SplashAdLoadListener = object : SplashAdLoadListener() {
51 | override fun onAdLoaded() {
52 | // Call this method when an ad is successfully loaded.
53 | Log.i(TAG, "SplashAdLoadListener onAdLoaded.")
54 | Toast.makeText(this@SplashActivity, getString(R.string.status_load_ad_success), Toast.LENGTH_SHORT).show()
55 | }
56 |
57 | override fun onAdFailedToLoad(errorCode: Int) {
58 | // Call this method when an ad fails to be loaded.
59 | Log.i(TAG, "SplashAdLoadListener onAdFailedToLoad, errorCode: $errorCode")
60 | Toast.makeText(this@SplashActivity, getString(R.string.status_load_ad_fail) + errorCode, Toast.LENGTH_SHORT).show()
61 | jump()
62 | }
63 |
64 | override fun onAdDismissed() {
65 | // Call this method when the ad display is complete.
66 | Log.i(TAG, "SplashAdLoadListener onAdDismissed.")
67 | Toast.makeText(this@SplashActivity, getString(R.string.status_ad_dismissed), Toast.LENGTH_SHORT).show()
68 | jump()
69 | }
70 | }
71 | private val adDisplayListener: SplashAdDisplayListener = object : SplashAdDisplayListener() {
72 | override fun onAdShowed() {
73 | // Call this method when an ad is displayed.
74 | Log.i(TAG, "SplashAdDisplayListener onAdShowed.")
75 | }
76 |
77 | override fun onAdClick() {
78 | // Call this method when an ad is clicked.
79 | Log.i(TAG, "SplashAdDisplayListener onAdClick.")
80 | }
81 | }
82 |
83 | override fun onCreate(savedInstanceState: Bundle?) {
84 | super.onCreate(savedInstanceState)
85 |
86 | // Lock screen orientation
87 | requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LOCKED
88 | setContentView(R.layout.activity_splash)
89 | loadAd()
90 | }
91 |
92 | private fun loadAd() {
93 | Log.i(TAG, "Start to load ad")
94 | val adParam = AdParam.Builder().build()
95 | splashView = findViewById(R.id.splash_ad_view)
96 | splashView!!.setAdDisplayListener(adDisplayListener)
97 |
98 | val slotId: String
99 | // Lock the screen orientation on the device. Your app will automatically adapt to the screen orientation.
100 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED)
101 | val orientation = screenOrientation
102 | // Set the default slogan and the splash ad unit ID based on the screen orientation on the device.
103 | slotId = if (orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
104 | splashView!!.setSloganResId(R.drawable.default_slogan)
105 | getString(R.string.ad_id_splash)
106 | } else {
107 | splashView!!.setSloganResId(R.drawable.default_slogan_landscape)
108 | getString(R.string.ad_id_splash_landscape)
109 | }
110 | splashView!!.setLogo(findViewById(R.id.logo_area))
111 |
112 | // Set a logo image.
113 | splashView!!.setLogoResId(R.mipmap.ic_launcher)
114 | // Set logo description.
115 | splashView!!.setMediaNameResId(R.string.media_name)
116 | // Set the audio focus type for a video splash ad.
117 | splashView!!.setAudioFocusType(AudioFocusType.NOT_GAIN_AUDIO_FOCUS_WHEN_MUTE)
118 | splashView!!.load(slotId, orientation, adParam, splashAdLoadListener)
119 | Log.i(TAG, "End to load ad")
120 |
121 | // Remove the timeout message from the message queue.
122 | timeoutHandler.removeMessages(MSG_AD_TIMEOUT)
123 | // Send a delay message to ensure that the app home screen can be displayed when the ad display times out.
124 | timeoutHandler.sendEmptyMessageDelayed(MSG_AD_TIMEOUT, AD_TIMEOUT.toLong())
125 | }
126 |
127 | private val screenOrientation: Int
128 | private get() {
129 | val config = resources.configuration
130 | return if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
131 | ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
132 | } else {
133 | ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
134 | }
135 | }
136 |
137 | /**
138 | * Switch from the splash ad screen to the app home screen when the ad display is complete.
139 | */
140 | private fun jump() {
141 | Log.i(TAG, "jump hasPaused: $hasPaused")
142 | if (!hasPaused) {
143 | hasPaused = true
144 | Log.i(TAG, "jump into application")
145 | startActivity(Intent(this@SplashActivity, MainActivity::class.java))
146 | val mainHandler = Handler()
147 | mainHandler.postDelayed({ finish() }, 1000)
148 | }
149 | }
150 |
151 | /**
152 | * Set this parameter to true when exiting the app to ensure that the app home screen is not displayed.
153 | */
154 | override fun onStop() {
155 | Log.i(TAG, "SplashActivity onStop.")
156 | // Remove the timeout message from the message queue.
157 | timeoutHandler.removeMessages(MSG_AD_TIMEOUT)
158 | hasPaused = true
159 | super.onStop()
160 | }
161 |
162 | /**
163 | * Call this method when returning to the splash ad screen from another screen to access the app home screen.
164 | */
165 | override fun onRestart() {
166 | Log.i(TAG, "SplashActivity onRestart.")
167 | super.onRestart()
168 | hasPaused = false
169 | jump()
170 | }
171 |
172 | override fun onDestroy() {
173 | Log.i(TAG, "SplashActivity onDestroy.")
174 | super.onDestroy()
175 | if (splashView != null) {
176 | splashView!!.destroyView()
177 | }
178 | }
179 |
180 | override fun onPause() {
181 | Log.i(TAG, "SplashActivity onPause.")
182 | super.onPause()
183 | if (splashView != null) {
184 | splashView!!.pauseView()
185 | }
186 | }
187 |
188 | override fun onResume() {
189 | Log.i(TAG, "SplashActivity onResume.")
190 | super.onResume()
191 | if (splashView != null) {
192 | splashView!!.resumeView()
193 | }
194 | }
195 |
196 | companion object {
197 | private val TAG = SplashActivity::class.java.simpleName
198 |
199 | // Ad display timeout interval, in milliseconds.
200 | private const val AD_TIMEOUT = 10000
201 |
202 | // Ad display timeout message flag.
203 | private const val MSG_AD_TIMEOUT = 1001
204 | }
205 | }
206 |
--------------------------------------------------------------------------------
/app/src/main/java/com/huawei/hms/ads/sdk/dialogs/ConsentDialog.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package com.huawei.hms.ads.sdk.dialogs
17 |
18 | import android.app.Dialog
19 | import android.content.Context
20 | import android.graphics.Color
21 | import android.os.Bundle
22 | import android.text.Html
23 | import android.text.Spannable
24 | import android.text.SpannableStringBuilder
25 | import android.text.method.LinkMovementMethod
26 | import android.text.method.ScrollingMovementMethod
27 | import android.text.style.ClickableSpan
28 | import android.text.style.ForegroundColorSpan
29 | import android.view.LayoutInflater
30 | import android.view.View
31 | import android.view.Window
32 | import android.widget.Button
33 | import android.widget.LinearLayout
34 | import android.widget.TextView
35 | import com.huawei.hms.ads.consent.bean.AdProvider
36 | import com.huawei.hms.ads.consent.constant.ConsentStatus
37 | import com.huawei.hms.ads.consent.inter.Consent
38 | import com.huawei.hms.ads.sdk.AdsConstant
39 | import com.huawei.hms.ads.sdk.R
40 | import com.huawei.hms.ads.sdk.dialogs.ConsentDialog.ConsentDialogCallback
41 |
42 | /**
43 | * Control on consent-related dialog boxes.
44 | */
45 | class ConsentDialog(
46 | private val mContext: Context, private
47 | val madProviders: List) : Dialog(mContext, R.style.dialog)
48 | {
49 | var inflater: LayoutInflater? = null
50 | var contentLayout: LinearLayout? = null
51 | var titleTv: TextView? = null
52 | var initInfoTv: TextView? = null
53 | var moreInfoTv: TextView? = null
54 | var partnersListTv: TextView? = null
55 | var consentDialogView: View? = null
56 | var initView: View? = null
57 | var moreInfoView: View? = null
58 | var partnersListView: View? = null
59 | var consentYesBtn: Button? = null
60 | var consentNoBtn: Button? = null
61 | var moreInfoBackBtn: Button? = null
62 | var partnerListBackBtn: Button? = null
63 | var mCallback: ConsentDialogCallback? = null
64 |
65 | /**
66 | * Consent dialog box callback interface.
67 | */
68 | interface ConsentDialogCallback {
69 | /**
70 | * Update a user selection result.
71 | *
72 | * @param consentStatus ConsentStatus
73 | */
74 | fun updateConsentStatus(consentStatus: ConsentStatus)
75 | }
76 |
77 | /**
78 | * Set a dialog box callback.
79 | *
80 | * @param callback callback
81 | */
82 | fun setCallback(callback: ConsentDialogCallback?) {
83 | mCallback = callback
84 | }
85 |
86 | override fun onCreate(savedInstanceState: Bundle?) {
87 | super.onCreate(savedInstanceState)
88 | val dialogWindow: Window? = window
89 | dialogWindow!!.requestFeature(Window.FEATURE_NO_TITLE)
90 | inflater = LayoutInflater.from(mContext)
91 | consentDialogView = inflater!!.inflate(R.layout.dialog_consent, null)
92 | setContentView(consentDialogView!!)
93 | titleTv = findViewById(R.id.consent_dialog_title_text)
94 | titleTv!!.text = mContext.getString(R.string.consent_title)
95 | initView = inflater!!.inflate(R.layout.dialog_consent_content, null)
96 | moreInfoView = inflater!!.inflate(R.layout.dialog_consent_moreinfo, null)
97 | partnersListView = inflater!!.inflate(R.layout.dialog_consent_partner_list, null)
98 |
99 | // Add content to the initialization dialog box.
100 | showInitConsentInfo()
101 | }
102 |
103 | /**
104 | * Update the consent status.
105 | *
106 | * @param consentStatus ConsentStatus
107 | */
108 | private fun updateConsentStatus(consentStatus: ConsentStatus) {
109 | // Update the consent status.
110 | Consent.getInstance(mContext).setConsentStatus(consentStatus)
111 |
112 | // Save a user selection to the local SP.
113 | val preferences = mContext.getSharedPreferences(AdsConstant.SP_NAME, Context.MODE_PRIVATE)
114 | val editor = preferences.edit()
115 | editor.putInt(AdsConstant.SP_CONSENT_KEY, consentStatus.value).commit()
116 |
117 | // Callback activity
118 | if (mCallback != null) {
119 | mCallback!!.updateConsentStatus(consentStatus)
120 | }
121 | }
122 |
123 | /**
124 | * Display initial consent content.
125 | */
126 | private fun showInitConsentInfo() {
127 | addContentView(initView)
128 |
129 | // Add a button and text link and their tapping events to the initialization page.
130 | addInitButtonAndLinkClick(consentDialogView)
131 | }
132 |
133 | /**
134 | * Add a button and a text link and their tapping events to the initial page.
135 | *
136 | * @param rootView rootView
137 | */
138 | private fun addInitButtonAndLinkClick(rootView: View?) {
139 | consentYesBtn = rootView!!.findViewById(R.id.btn_consent_init_yes)
140 | consentYesBtn!!.setOnClickListener(View.OnClickListener {
141 | dismiss()
142 | updateConsentStatus(ConsentStatus.PERSONALIZED)
143 | })
144 | consentNoBtn = rootView.findViewById(R.id.btn_consent_init_skip)
145 | consentNoBtn!!.setOnClickListener(View.OnClickListener {
146 | dismiss()
147 | updateConsentStatus(ConsentStatus.NON_PERSONALIZED)
148 | })
149 | initInfoTv = rootView.findViewById(R.id.consent_center_init_content)
150 | initInfoTv!!.movementMethod = ScrollingMovementMethod.getInstance()
151 | val initText = mContext.getString(R.string.consent_init_text)
152 | val spanInitText = SpannableStringBuilder(initText)
153 |
154 | // Set the listener on the event for tapping some text.
155 | val initTouchHere: ClickableSpan = object : ClickableSpan() {
156 | override fun onClick(widget: View) {
157 | showTouchHereInfo()
158 | }
159 | }
160 | val colorSpan = ForegroundColorSpan(Color.parseColor("#0000FF"))
161 | val initTouchHereStart = mContext.resources.getInteger(R.integer.init_here_start)
162 | val initTouchHereEnd = mContext.resources.getInteger(R.integer.init_here_end)
163 | spanInitText.setSpan(initTouchHere, initTouchHereStart, initTouchHereEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
164 | spanInitText.setSpan(colorSpan, initTouchHereStart, initTouchHereEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
165 | initInfoTv!!.text = spanInitText
166 | initInfoTv!!.movementMethod = LinkMovementMethod.getInstance()
167 | }
168 |
169 | /**
170 | * Display the content on the more information page.
171 | */
172 | fun showTouchHereInfo() {
173 | addContentView(moreInfoView)
174 |
175 | // Set the listener on the tapping event on the more information page.
176 | addMoreInfoButtonAndLinkClick(consentDialogView)
177 | }
178 |
179 | /**
180 | * Add a button and a text link and their tapping events to the more information page.
181 | *
182 | * @param rootView rootView
183 | */
184 | private fun addMoreInfoButtonAndLinkClick(rootView: View?) {
185 | moreInfoBackBtn = rootView!!.findViewById(R.id.btn_consent_more_info_back)
186 | moreInfoBackBtn!!.setOnClickListener(View.OnClickListener { showInitConsentInfo() })
187 | moreInfoTv = rootView.findViewById(R.id.consent_center_more_info_content)
188 | moreInfoTv!!.movementMethod = ScrollingMovementMethod.getInstance()
189 | val moreInfoText = mContext.getString(R.string.consent_more_info_text)
190 | val spanMoreInfoText = SpannableStringBuilder(moreInfoText)
191 |
192 | // Set the listener on the event for tapping some text.
193 | val moreInfoTouchHere: ClickableSpan = object : ClickableSpan() {
194 | override fun onClick(widget: View) {
195 | showPartnersListInfo()
196 | }
197 | }
198 | val colorSpan = ForegroundColorSpan(Color.parseColor("#0000FF"))
199 | val moreInfoTouchHereStart = mContext.resources.getInteger(R.integer.more_info_here_start)
200 | val moreInfoTouchHereEnd = mContext.resources.getInteger(R.integer.more_info_here_end)
201 | spanMoreInfoText.setSpan(moreInfoTouchHere, moreInfoTouchHereStart, moreInfoTouchHereEnd,
202 | Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
203 | spanMoreInfoText.setSpan(colorSpan, moreInfoTouchHereStart, moreInfoTouchHereEnd,
204 | Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
205 | moreInfoTv!!.text = spanMoreInfoText
206 | moreInfoTv!!.movementMethod = LinkMovementMethod.getInstance()
207 | }
208 |
209 | /**
210 | * Display the partner list page.
211 | */
212 | fun showPartnersListInfo() {
213 | partnersListTv = partnersListView!!.findViewById(R.id.partners_list_content)
214 | partnersListTv!!.movementMethod = ScrollingMovementMethod.getInstance()
215 | partnersListTv!!.text = ""
216 | val learnAdProviders = madProviders
217 | if (learnAdProviders != null) {
218 | for (learnAdProvider in learnAdProviders) {
219 | val link = (""
220 | + learnAdProvider.name + " ")
221 | partnersListTv!!.append(Html.fromHtml(link))
222 | partnersListTv!!.append(" ")
223 | }
224 | } else {
225 | partnersListTv!!.append(" 3rd party’s full list of advertisers is empty")
226 | }
227 | partnersListTv!!.movementMethod = LinkMovementMethod.getInstance()
228 | addContentView(partnersListView)
229 |
230 | // Set the listener on the tapping event on the partner list page.
231 | addPartnersListButtonAndLinkClick(consentDialogView)
232 | }
233 |
234 | /**
235 | * Add a button and a text link and their tapping events to the partner list page.
236 | *
237 | * @param rootView rootView
238 | */
239 | private fun addPartnersListButtonAndLinkClick(rootView: View?) {
240 | partnerListBackBtn = rootView!!.findViewById(R.id.btn_partners_list_back)
241 | partnerListBackBtn!!.setOnClickListener(View.OnClickListener { showTouchHereInfo() })
242 | }
243 |
244 | /**
245 | * Add layout content in the dialog box that is displayed.
246 | */
247 | private fun addContentView(view: View?) {
248 | contentLayout = findViewById(R.id.consent_center_layout)
249 | contentLayout!!.removeAllViews()
250 | contentLayout!!.addView(view)
251 | }
252 |
253 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/huawei/hms/ads/sdk/dialogs/ProtocolDialog.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package com.huawei.hms.ads.sdk.dialogs
17 |
18 | import android.app.AlertDialog
19 | import android.app.Dialog
20 | import android.content.Context
21 | import android.content.Intent
22 | import android.graphics.Color
23 | import android.graphics.Typeface
24 | import android.os.Bundle
25 | import android.text.Spannable
26 | import android.text.SpannableStringBuilder
27 | import android.text.method.LinkMovementMethod
28 | import android.text.method.ScrollingMovementMethod
29 | import android.text.style.ClickableSpan
30 | import android.text.style.ForegroundColorSpan
31 | import android.text.style.StyleSpan
32 | import android.view.LayoutInflater
33 | import android.view.View
34 | import android.view.Window
35 | import android.widget.Button
36 | import android.widget.LinearLayout
37 | import android.widget.TextView
38 | import com.huawei.hms.ads.sdk.AdsConstant
39 | import com.huawei.hms.ads.sdk.R
40 | import com.huawei.hms.ads.sdk.dialogs.ProtocolDialog.ProtocolDialogCallback
41 |
42 | /**
43 | * Control on privacy-related dialog boxes.
44 | */
45 | class ProtocolDialog(
46 | private val mContext: Context) : Dialog(mContext, R.style.dialog)
47 | {
48 | var titleTv: TextView? = null
49 | var protocolTv: TextView? = null
50 | var confirmButton: Button? = null
51 | var cancelButton: Button? = null
52 | var inflater: LayoutInflater? = null
53 | var mCallback: ProtocolDialogCallback? = null
54 |
55 | /**
56 | * Privacy protocol dialog box callback interface.
57 | */
58 | interface ProtocolDialogCallback {
59 | fun agree()
60 | fun cancel()
61 | }
62 |
63 | /**
64 | * Set a dialog box callback.
65 | *
66 | * @param callback callback
67 | */
68 | fun setCallback(callback: ProtocolDialogCallback?) {
69 | mCallback = callback
70 | }
71 |
72 | override fun onCreate(savedInstanceState: Bundle?) {
73 | super.onCreate(savedInstanceState)
74 | val dialogWindow: Window? = window
75 | dialogWindow!!.requestFeature(Window.FEATURE_NO_TITLE)
76 | inflater = LayoutInflater.from(mContext)
77 | val rootView = inflater!!.inflate(R.layout.dialog_protocol, null) as LinearLayout
78 | setContentView(rootView)
79 | titleTv = findViewById(R.id.uniform_dialog_title)
80 | titleTv!!.text = mContext.getString(R.string.protocol_title)
81 | protocolTv = findViewById(R.id.protocol_center_content)
82 | initClickableSpan()
83 | initButtonBar(rootView)
84 | }
85 |
86 | /**
87 | * Initialize the page of the button bar.
88 | *
89 | * @param rootView rootView
90 | */
91 | fun initButtonBar(rootView: LinearLayout) {
92 | confirmButton = rootView.findViewById(R.id.base_okBtn)
93 | confirmButton!!.setOnClickListener(View.OnClickListener {
94 | val preferences = mContext.getSharedPreferences(AdsConstant.SP_NAME, Context.MODE_PRIVATE)
95 | val editor = preferences.edit()
96 | editor.putInt(AdsConstant.SP_PROTOCOL_KEY, 1).commit()
97 | dismiss()
98 | if (mCallback != null) {
99 | mCallback!!.agree()
100 | }
101 | })
102 | cancelButton = rootView.findViewById(R.id.base_cancelBtn)
103 | cancelButton!!.setOnClickListener(View.OnClickListener {
104 | dismiss()
105 | if (mCallback != null) {
106 | mCallback!!.cancel()
107 | }
108 | })
109 | }
110 |
111 | private fun initClickableSpan() {
112 | // Add a text-based tapping event.
113 | protocolTv!!.movementMethod = ScrollingMovementMethod.getInstance()
114 | val privacyInfoText = mContext.getString(R.string.protocol_content_text)
115 | val spanPrivacyInfoText = SpannableStringBuilder(privacyInfoText)
116 |
117 | // Set the listener on the event for tapping some text.
118 | val personalizedAdsTouchHere: ClickableSpan = object : ClickableSpan() {
119 | override fun onClick(widget: View) {
120 | startActivity(ACTION_OAID_SETTING)
121 | }
122 | }
123 | val privacyStart = mContext.resources.getInteger(R.integer.privacy_start)
124 | val privacyEnd = mContext.resources.getInteger(R.integer.privacy_end)
125 | val privacySpan = StyleSpan(Typeface.BOLD)
126 | spanPrivacyInfoText.setSpan(privacySpan, privacyStart, privacyEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
127 | val colorPersonalize = ForegroundColorSpan(Color.BLUE)
128 | val personalizedStart = mContext.resources.getInteger(R.integer.personalized_start)
129 | val personalizedEnd = mContext.resources.getInteger(R.integer.personalized_end)
130 | spanPrivacyInfoText.setSpan(personalizedAdsTouchHere, personalizedStart, personalizedEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
131 | spanPrivacyInfoText.setSpan(colorPersonalize, personalizedStart, personalizedEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
132 | protocolTv!!.text = spanPrivacyInfoText
133 | protocolTv!!.movementMethod = LinkMovementMethod.getInstance()
134 | }
135 |
136 | fun startActivity(action: String) {
137 | val enterNative = Intent(action)
138 | val pkgMng = mContext.packageManager
139 | if (pkgMng != null) {
140 | val list = pkgMng.queryIntentActivities(enterNative, 0)
141 | if (!list.isEmpty()) {
142 | enterNative.setPackage("com.huawei.hwid")
143 | mContext.startActivity(enterNative)
144 | } else {
145 | // A message is displayed, indicating that no function is available and asking users to install HMS Core of the latest version.
146 | addAlertView()
147 | }
148 | }
149 | }
150 |
151 | /**
152 | * Prompt dialog box, indicating that no function is available and asking users to install Huawei Mobile Services (APK) of the latest version.
153 | */
154 | fun addAlertView() {
155 | val builder = AlertDialog.Builder(mContext)
156 | builder.setTitle(mContext.getString(R.string.alert_title))
157 | builder.setMessage(mContext.getString(R.string.alert_content))
158 | builder.setPositiveButton(mContext.getString(R.string.alert_confirm), null)
159 | builder.show()
160 | }
161 |
162 | companion object {
163 | private val ACTION_SIMPLE_PRIVACY = "com.huawei.hms.ppskit.ACTION.SIMPLE_PRIVACY"
164 | private val ACTION_OAID_SETTING = "com.huawei.hms.action.OAID_SETTING"
165 | }
166 |
167 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/btn_check_off_emui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/drawable-xhdpi/btn_check_off_emui.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/btn_check_on_emui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/drawable-xhdpi/btn_check_on_emui.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/btn_check_on_pressed_emui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/drawable-xhdpi/btn_check_on_pressed_emui.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_sb_cancel_gray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/drawable-xhdpi/ic_sb_cancel_gray.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/popup_full_bright_emui.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/drawable-xhdpi/popup_full_bright_emui.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_default_disabled_emui.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/drawable-xxhdpi/btn_default_disabled_emui.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_default_normal_emui.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/drawable-xxhdpi/btn_default_normal_emui.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_default_pressed_emui.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/drawable-xxhdpi/btn_default_pressed_emui.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/app_whythisad_info.xml:
--------------------------------------------------------------------------------
1 |
3 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_check_off_emui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/drawable/btn_check_off_emui.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_check_on_emui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/drawable/btn_check_on_emui.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_check_on_pressed_emui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/drawable/btn_check_on_pressed_emui.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/default_slogan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/drawable/default_slogan.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/default_slogan_landscape.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/drawable/default_slogan_landscape.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/detail_checkbox_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/emui_button_select.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/native_button_rounded_corners_shape.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/native_flag_rounded_corners_shape.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_banner.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
14 |
15 |
24 |
25 |
33 |
34 |
42 |
43 |
44 |
45 |
53 |
54 |
59 |
60 |
66 |
67 |
72 |
73 |
78 |
79 |
84 |
85 |
90 |
91 |
96 |
97 |
98 |
103 |
104 |
110 |
111 |
116 |
117 |
122 |
123 |
128 |
129 |
130 |
131 |
142 |
143 |
150 |
151 |
159 |
160 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_consent.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
15 |
16 |
23 |
24 |
31 |
32 |
33 |
40 |
41 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_instream.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
11 |
12 |
17 |
25 |
26 |
27 |
32 |
33 |
37 |
38 |
54 |
55 |
70 |
71 |
87 |
88 |
99 |
100 |
116 |
117 |
118 |
125 |
131 |
136 |
141 |
142 |
149 |
154 |
159 |
160 |
161 |
162 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_interstitial.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
15 |
16 |
24 |
25 |
33 |
34 |
40 |
41 |
47 |
48 |
53 |
54 |
55 |
56 |
65 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_native.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
11 |
12 |
22 |
23 |
27 |
28 |
34 |
35 |
41 |
42 |
47 |
48 |
53 |
54 |
59 |
60 |
65 |
66 |
67 |
74 |
75 |
76 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_reward.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
14 |
15 |
16 |
24 |
25 |
33 |
34 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_splash.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
23 |
24 |
31 |
32 |
36 |
37 |
44 |
45 |
52 |
53 |
54 |
62 |
63 |
64 |
65 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_consent.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
25 |
26 |
27 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_consent_content.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
20 |
21 |
29 |
30 |
40 |
41 |
50 |
51 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_consent_moreinfo.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
20 |
21 |
29 |
30 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_consent_partner_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
19 |
20 |
30 |
31 |
39 |
40 |
48 |
49 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_protocol.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
25 |
26 |
27 |
36 |
37 |
50 |
51 |
52 |
53 |
60 |
61 |
71 |
72 |
81 |
82 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/native_ad_with_app_download_btn_template.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
19 |
20 |
25 |
26 |
35 |
36 |
48 |
49 |
62 |
63 |
64 |
70 |
71 |
85 |
86 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/native_common_medium_template.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
19 |
20 |
25 |
26 |
35 |
36 |
48 |
49 |
62 |
63 |
64 |
70 |
71 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/native_image_only_template.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
19 |
20 |
33 |
34 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/native_small_image_template.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
26 |
27 |
36 |
37 |
45 |
46 |
55 |
56 |
69 |
70 |
79 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/native_small_template.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
26 |
27 |
36 |
37 |
45 |
46 |
55 |
56 |
69 |
70 |
79 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/native_three_images_template.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
20 |
21 |
27 |
28 |
34 |
35 |
41 |
42 |
43 |
50 |
58 |
69 |
82 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/native_video_template.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
19 |
20 |
25 |
26 |
35 |
36 |
48 |
49 |
62 |
63 |
64 |
70 |
71 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/ad_sample_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 | #e6000000
8 | #000000
9 | #ffffff
10 | #338D8D8D
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 200dp
6 | 3dp
7 | 5dp
8 | 8dp
9 | 16dp
10 | 100dp
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #26A69A
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | PatelAdsSdk_Demo_Kotlin
3 | Banner Ad
4 | Native Ad
5 | Reward Ad
6 | Interstitial Ad
7 | Instream Ad
8 | Privacy Settings
9 | Consent Settings
10 | Load Ad
11 |
12 |
13 | testw6vs28auh3
14 | SIZE_320*50
15 | SIZE_320*100
16 | SIZE_SMART
17 | SIZE_300*250
18 | SIZE_360*57
19 | SIZE_360*144
20 | Black
21 | White
22 | Red
23 | Transparent
24 | Size:
25 | Color:
26 |
27 |
28 | testu7m3hc4gvm
29 | testb65czjivt9
30 | testr6w14o0hqz
31 | testy63txaom86
32 | Ad
33 | Display form:
34 | Large image with text.
35 | Three images with text.
36 | Small image with text.
37 | Video with text.
38 | Ad with app download button.
39 | Ad loading state: being loaded.
40 | Ad loading state: loaded successfully.
41 | Ad loading state: loaded finish.
42 | Ad loading state: failed to be loaded. Error code:
43 | Video playback state: starting to be played.
44 | Video playback state: being played.
45 | Video playback state: playback completed.
46 | Ad is closed.
47 |
48 |
49 | testx9dtjwj8hp
50 | This is rewarded ads sample.
51 | Play
52 | Watch Video
53 |
54 |
55 | testd7c5cewoj6
56 | testq6zq98hecj
57 | HUAWEI Developer
58 | Petal Ads
59 | Copyright 2020. Huawei Technologies Co., Ltd
60 | Splash Ad is dismissed.
61 |
62 |
63 | This is interstitial ad sample.
64 | teste9ih9j0rc3
65 | testb4znbuh3n2
66 | Load Ad
67 | Image
68 | Video
69 |
70 |
71 | Your video content
72 | Skip
73 | Learn more
74 | testy3cglm3pj0
75 | Normal video is playing
76 | Load Ad
77 | Register
78 | Mute
79 | UnMute
80 | Play
81 | Pause
82 | Loading
83 | Ad Loaded
84 |
85 |
86 | Privacy Example of HUAWEI X
87 |
88 | 1.Privacy description\n
89 | The PetalAdsSdk_Demo is software providing a code demo for the Petal Ads SDK. Connecting to the network, the software collects and processes information to identify devices, providing customized services or ads. If you do not agree to collect the preceding information or do not agree to call related permissions or functions of your mobile phones, the software cannot run properly. You can stop data collection and uploading by uninstalling or exiting this software.\n\n
90 | 2.Demo description\n
91 | This demo is for reference only. Modify the content based on the user protocol specifications. \n\n
92 | 3.Advertising and marketing\n
93 | We will create a user group based on your personal information, collect your device information, usage information, and ad interaction information in this app, and display more relevant personalized ads and other promotion content. In this process, we will strictly protect your privacy. You can learn more about how we collect and use your personal information in personalized ads based on Ads and Privacy.
94 | If you want to restrict personalized ads, you can tap here to open the ad setting page and enable the function of restricting personalized ads. After the function is enabled, you will still receive equivalent number of ads. However, the ad relevance will be reduced.
95 |
96 | 1033
97 | 1048
98 | 1104
99 | 1108
100 | Don\'t remind me again
101 | Cancel
102 | Setting
103 | Agree
104 | Cancel
105 | Reminder
106 | HMS Core of this version does not have the related function. Please install HMS Core (APK) of the latest version in AppGallery.
107 | OK
108 |
109 |
110 | Consent Example of HUAWEI X
111 | Privacy Policy
112 | Close
113 | Do Not Load Ads
114 | The Ads in HUAWEI X is provided in collaboration with our advertising partners. To provide this service, we need to share certain information about you with these partners, including your city-level location as well as your usage records for the news service.\n\n
115 | For more information about our partners and how your data is processed, please touch here.\n\n
116 | By touching AGREE, you indicate that you agree to share the above personal information with our partners so that they can provide you with personalized advertisements on behalf of their customers, based on interests and preferences identified or predicted through analysis of your personal information.
117 | \n\nYou can withdraw your consent at any time by going to [app settings].
118 | \n\nIf you touch SKIP, your data will not be shared with our partners and you will not receive personalized ads.
119 | 347
120 | 351
121 | The Ads in HUAWEI X is provided in collaboration with our partners. You can find a full list of our partners for each country/region here.\n\n
122 | In order to provide you with personalized advertisements, we need to share the following information with our partners:\n\n
123 | • User information, including advertising ID, city of residence, country, and language.\n\n
124 | • Device information, including device name and model, operating system version, screen size, and network type.\n\n
125 | • Service usage information, including news ID and records of views, clicks, dislikes, shares, and comments for news content and advertisements.\n\n
126 | With your consent, the above information will be shared with our partners so that they can provide you with personalized advertisements on behalf of their customers, based on interests and preferences identified or predicted through analysis of your personal information.\n\n
127 | You can withdraw your consent at any time by going to app settings.\n\n
128 | Without your consent, no data will be shared with our partners and you will not receive personalized ads.
129 | 133
130 | 137
131 | You can find a full list of our partners for each country/region here:\n\n
132 | Back
133 | Agree
134 | Skip
135 | You can change this setting anytime in the app.
136 | Thank you!
137 | This is a Consent Example
138 |
139 | Load Personalized Ads.
140 | Load Non-Personalized Ads.
141 | Do Not Load Ads.
142 |
143 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.4.0'
5 | repositories {
6 | google()
7 | jcenter()
8 | maven { url 'https://developer.huawei.com/repo/' }
9 | }
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:3.5.1'
12 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
13 |
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 | }
17 | }
18 |
19 | allprojects {
20 | repositories {
21 | google()
22 | jcenter()
23 | maven { url 'https://developer.huawei.com/repo/' }
24 | }
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 |
21 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HMS-Core/hms-ads-demo-kotlin/032e8773ef36a257c7f2b976ecdaf8c0a4f662ef/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Nov 05 22:40:05 CST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
7 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 | rootProject.name='HuaweiAdsSdk_Demo'
3 |
--------------------------------------------------------------------------------