Как встроить admob в kotlin проект?
Есть проект созданный в android studio на kotlin, при встраивание admob проект собирается но при запуске крошиться, подскажите может я не в тот участок кода ставлю рекламу? Рекламу я правильно встроил на 100%. Создав новый проект реклама встроенная работает и приложение запускается.
package com.moez.QKSMS.feature.main
import android.Manifest
import android.animation.ObjectAnimator
import android.app.AlertDialog
import android.content.Intent
import android.content.res.ColorStateList
import android.os.Build
import android.os.Bundle
import android.view.Gravity
import android.view.Menu
import android.view.MenuItem
import android.view.View
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.core.app.ActivityCompat
import androidx.core.view.GravityCompat
import androidx.core.view.isVisible
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.ItemTouchHelper
import com.google.android.gms.ads.*
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.AdView
import com.google.android.material.snackbar.Snackbar
import com.jakewharton.rxbinding2.view.clicks
import com.jakewharton.rxbinding2.widget.textChanges
import com.moez.QKSMS.R
import com.moez.QKSMS.common.Navigator
import com.moez.QKSMS.common.androidxcompat.drawerOpen
import com.moez.QKSMS.common.base.QkThemedActivity
import com.moez.QKSMS.common.util.extensions.autoScrollToStart
import com.moez.QKSMS.common.util.extensions.dismissKeyboard
import com.moez.QKSMS.common.util.extensions.resolveThemeColor
import com.moez.QKSMS.common.util.extensions.scrapViews
import com.moez.QKSMS.common.util.extensions.setBackgroundTint
import com.moez.QKSMS.common.util.extensions.setTint
import com.moez.QKSMS.common.util.extensions.setVisible
import com.moez.QKSMS.common.util.extensions.viewBinding
import com.moez.QKSMS.databinding.MainActivityBinding
import com.moez.QKSMS.feature.blocking.BlockingDialog
import com.moez.QKSMS.feature.changelog.ChangelogDialog
import com.moez.QKSMS.feature.conversations.ConversationItemTouchCallback
import com.moez.QKSMS.feature.conversations.ConversationsAdapter
import com.moez.QKSMS.manager.ChangelogManager
import com.moez.QKSMS.repository.SyncRepository
import com.uber.autodispose.android.lifecycle.scope
import com.uber.autodispose.autoDisposable
import dagger.android.AndroidInjection
import io.reactivex.Observable
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.subjects.PublishSubject
import io.reactivex.subjects.Subject
import javax.inject.Inject
class MainActivity : QkThemedActivity(), MainView {
@Inject lateinit var blockingDialog: BlockingDialog
@Inject lateinit var disposables: CompositeDisposable
@Inject lateinit var navigator: Navigator
@Inject lateinit var conversationsAdapter: ConversationsAdapter
@Inject lateinit var drawerBadgesExperiment: DrawerBadgesExperiment
@Inject lateinit var searchAdapter: SearchAdapter
@Inject lateinit var itemTouchCallback: ConversationItemTouchCallback
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
override val onNewIntentIntent: Subject<Intent> = PublishSubject.create()
override val activityResumedIntent: Subject<Boolean> = PublishSubject.create()
override val queryChangedIntent by lazy { binding.toolbarSearch.textChanges() }
override val composeIntent by lazy { binding.compose.clicks() }
override val drawerOpenIntent: Observable<Boolean> by lazy {
binding.drawerLayout
.drawerOpen(Gravity.START)
.doOnNext { dismissKeyboard() }
}
override val homeIntent: Subject<Unit> = PublishSubject.create()
override val navigationIntent: Observable<NavItem> by lazy {
Observable.merge(listOf(
backPressedSubject,
binding.drawer.inbox.clicks().map { NavItem.INBOX },
binding.drawer.archived.clicks().map { NavItem.ARCHIVED },
binding.drawer.backup.clicks().map { NavItem.BACKUP },
binding.drawer.scheduled.clicks().map { NavItem.SCHEDULED },
binding.drawer.blocking.clicks().map { NavItem.BLOCKING },
binding.drawer.settings.clicks().map { NavItem.SETTINGS },
binding.drawer.plus.clicks().map { NavItem.PLUS },
binding.drawer.help.clicks().map { NavItem.HELP },
binding.drawer.invite.clicks().map { NavItem.INVITE }))
}
override val optionsItemIntent: Subject<Int> = PublishSubject.create()
override val plusBannerIntent by lazy { binding.drawer.plusBanner.clicks() }
override val dismissRatingIntent by lazy { binding.drawer.rateDismiss.clicks() }
override val rateIntent by lazy { binding.drawer.rateOkay.clicks() }
override val conversationsSelectedIntent by lazy { conversationsAdapter.selectionChanges }
override val confirmDeleteIntent: Subject<List<Long>> = PublishSubject.create()
override val swipeConversationIntent by lazy { itemTouchCallback.swipes }
override val changelogMoreIntent by lazy { changelogDialog.moreClicks }
override val undoArchiveIntent: Subject<Unit> = PublishSubject.create()
override val snackbarButtonIntent by lazy { binding.snackbar.button.clicks() }
private val binding by viewBinding(MainActivityBinding::inflate)
private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory)[MainViewModel::class.java] }
private val toggle by lazy { ActionBarDrawerToggle(this, binding.drawerLayout, binding.toolbar, R.string.main_drawer_open_cd, 0) }
private val itemTouchHelper by lazy { ItemTouchHelper(itemTouchCallback) }
private val progressAnimator by lazy { ObjectAnimator.ofInt(binding.syncing.progress, "progress", 0, 0) }
private val changelogDialog by lazy { ChangelogDialog(this) }
private val snackbar by lazy { findViewById<View>(R.id.snackbar) }
private val syncing by lazy { findViewById<View>(R.id.syncing) }
private val backPressedSubject: Subject<NavItem> = PublishSubject.create()
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.bindView(this)
onNewIntentIntent.onNext(intent)
toggle.syncState()
binding.toolbar.setNavigationOnClickListener {
dismissKeyboard()
homeIntent.onNext(Unit)
}
itemTouchCallback.adapter = conversationsAdapter
conversationsAdapter.autoScrollToStart(binding.recyclerView)
// Don't allow clicks to pass through the drawer layout
binding.drawer.root.clicks().autoDisposable(scope()).subscribe()
// Set the theme color tint to the recyclerView, progressbar, and FAB
theme
.autoDisposable(scope())
.subscribe { theme ->
// Set the color for the drawer icons
val states = arrayOf(
intArrayOf(android.R.attr.state_activated),
intArrayOf(-android.R.attr.state_activated))
resolveThemeColor(android.R.attr.textColorSecondary)
.let { textSecondary -> ColorStateList(states, intArrayOf(theme.theme, textSecondary)) }
.let { tintList ->
binding.drawer.inboxIcon.imageTintList = tintList
binding.drawer.archivedIcon.imageTintList = tintList
}
// Miscellaneous views
listOf(binding.drawer.plusBadge1, binding.drawer.plusBadge2).forEach { badge ->
badge.setBackgroundTint(theme.theme)
badge.setTextColor(theme.textPrimary)
}
binding.syncing.progress.progressTintList = ColorStateList.valueOf(theme.theme)
binding.syncing.progress.indeterminateTintList = ColorStateList.valueOf(theme.theme)
binding.drawer.plusIcon.setTint(theme.theme)
binding.drawer.rateIcon.setTint(theme.theme)
binding.compose.setBackgroundTint(theme.theme)
// Set the FAB compose icon color
binding.compose.setTint(theme.textPrimary)
// add admob
val adView = AdView(this)
MobileAds.initialize(this) {}
val adRequest = AdRequest.Builder().build()
adView.loadAd(adRequest)
adView.adListener = object: AdListener() {
override fun onAdLoaded() {
// Code to be executed when an ad finishes loading.
}
override fun onAdFailedToLoad(adError : LoadAdError) {
// Code to be executed when an ad request fails.
}
override fun onAdOpened() {
// Code to be executed when an ad opens an overlay that
// covers the screen.
}
override fun onAdClicked() {
// Code to be executed when the user clicks on an ad.
}
override fun onAdLeftApplication() {
// Code to be executed when the user has left the app.
}
override fun onAdClosed() {
// Code to be executed when the user is about to return
// to the app after tapping on an ad.
}
}
}
// These theme attributes don't apply themselves on API 21
if (Build.VERSION.SDK_INT <= 22) {
binding.toolbarSearch.setBackgroundTint(resolveThemeColor(R.attr.bubbleColor))
}
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
intent?.run(onNewIntentIntent::onNext)
}
override fun render(state: MainState) {
if (state.hasError) {
finish()
return
}
val addContact = when (state.page) {
is Inbox -> state.page.addContact
is Archived -> state.page.addContact
else -> false
}
val markPinned = when (state.page) {
is Inbox -> state.page.markPinned
is Archived -> state.page.markPinned
else -> true
}
val markRead = when (state.page) {
is Inbox -> state.page.markRead
is Archived -> state.page.markRead
else -> true
}
val selectedConversations = when (state.page) {
is Inbox -> state.page.selected
is Archived -> state.page.selected
else -> 0
}
binding.toolbarSearch.setVisible(state.page is Inbox && state.page.selected == 0 || state.page is Searching)
binding.toolbarTitle.setVisible(binding.toolbarSearch.visibility != View.VISIBLE)
binding.toolbar.menu.findItem(R.id.archive)?.isVisible = state.page is Inbox && selectedConversations != 0
binding.toolbar.menu.findItem(R.id.unarchive)?.isVisible = state.page is Archived && selectedConversations != 0
binding.toolbar.menu.findItem(R.id.delete)?.isVisible = selectedConversations != 0
binding.toolbar.menu.findItem(R.id.add)?.isVisible = addContact && selectedConversations != 0
binding.toolbar.menu.findItem(R.id.pin)?.isVisible = markPinned && selectedConversations != 0
binding.toolbar.menu.findItem(R.id.unpin)?.isVisible = !markPinned && selectedConversations != 0
binding.toolbar.menu.findItem(R.id.read)?.isVisible = markRead && selectedConversations != 0
binding.toolbar.menu.findItem(R.id.unread)?.isVisible = !markRead && selectedConversations != 0
binding.toolbar.menu.findItem(R.id.block)?.isVisible = selectedConversations != 0
listOf(binding.drawer.plusBadge1, binding.drawer.plusBadge2).forEach { badge ->
badge.isVisible = drawerBadgesExperiment.variant && !state.upgraded
}
binding.drawer.plus.isVisible = state.upgraded
binding.drawer.plusBanner.isVisible = !state.upgraded
binding.drawer.rateLayout.setVisible(state.showRating)
binding.compose.setVisible(state.page is Inbox || state.page is Archived)
conversationsAdapter.emptyView = binding.empty.takeIf { state.page is Inbox || state.page is Archived }
searchAdapter.emptyView = binding.empty.takeIf { state.page is Searching }
when (state.page) {
is Inbox -> {
showBackButton(state.page.selected > 0)
title = getString(R.string.main_title_selected, state.page.selected)
if (binding.recyclerView.adapter !== conversationsAdapter) binding.recyclerView.adapter = conversationsAdapter
conversationsAdapter.updateData(state.page.data)
itemTouchHelper.attachToRecyclerView(binding.recyclerView)
binding.empty.setText(R.string.inbox_empty_text)
}
is Searching -> {
showBackButton(true)
if (binding.recyclerView.adapter !== searchAdapter) binding.recyclerView.adapter = searchAdapter
searchAdapter.data = state.page.data ?: listOf()
itemTouchHelper.attachToRecyclerView(null)
binding.empty.setText(R.string.inbox_search_empty_text)
}
is Archived -> {
showBackButton(state.page.selected > 0)
title = when (state.page.selected != 0) {
true -> getString(R.string.main_title_selected, state.page.selected)
false -> getString(R.string.title_archived)
}
if (binding.recyclerView.adapter !== conversationsAdapter) binding.recyclerView.adapter = conversationsAdapter
conversationsAdapter.updateData(state.page.data)
itemTouchHelper.attachToRecyclerView(null)
binding.empty.setText(R.string.archived_empty_text)
}
}
binding.drawer.inbox.isActivated = state.page is Inbox
binding.drawer.archived.isActivated = state.page is Archived
if (binding.drawerLayout.isDrawerOpen(GravityCompat.START) && !state.drawerOpen) {
binding.drawerLayout.closeDrawer(GravityCompat.START)
} else if (!binding.drawerLayout.isDrawerVisible(GravityCompat.START) && state.drawerOpen) {
binding.drawerLayout.openDrawer(GravityCompat.START)
}
when (state.syncing) {
is SyncRepository.SyncProgress.Idle -> {
syncing.isVisible = false
snackbar.isVisible = !state.defaultSms || !state.smsPermission || !state.contactPermission
}
is SyncRepository.SyncProgress.Running -> {
syncing.isVisible = true
binding.syncing.progress.max = state.syncing.max
progressAnimator.apply { setIntValues(binding.syncing.progress.progress, state.syncing.progress) }.start()
binding.syncing.progress.isIndeterminate = state.syncing.indeterminate
snackbar.isVisible = false
}
}
when {
!state.defaultSms -> {
binding.snackbar.title.setText(R.string.main_default_sms_title)
binding.snackbar.message.setText(R.string.main_default_sms_message)
binding.snackbar.button.setText(R.string.main_default_sms_change)
}
!state.smsPermission -> {
binding.snackbar.title.setText(R.string.main_permission_required)
binding.snackbar.message.setText(R.string.main_permission_sms)
binding.snackbar.button.setText(R.string.main_permission_allow)
}
!state.contactPermission -> {
binding.snackbar.title.setText(R.string.main_permission_required)
binding.snackbar.message.setText(R.string.main_permission_contacts)
binding.snackbar.button.setText(R.string.main_permission_allow)
}
}
}
override fun onResume() {
super.onResume()
activityResumedIntent.onNext(true)
}
override fun onPause() {
super.onPause()
activityResumedIntent.onNext(false)
}
override fun onDestroy() {
super.onDestroy()
disposables.dispose()
}
override fun showBackButton(show: Boolean) {
toggle.onDrawerSlide(binding.drawer.root, if (show) 1f else 0f)
toggle.drawerArrowDrawable.color = when (show) {
true -> resolveThemeColor(android.R.attr.textColorSecondary)
false -> resolveThemeColor(android.R.attr.textColorPrimary)
}
}
override fun requestDefaultSms() {
navigator.showDefaultSmsDialog(this)
}
override fun requestPermissions() {
ActivityCompat.requestPermissions(this, arrayOf(
Manifest.permission.READ_SMS,
Manifest.permission.SEND_SMS,
Manifest.permission.READ_CONTACTS), 0)
}
override fun clearSearch() {
dismissKeyboard()
binding.toolbarSearch.text = null
}
override fun clearSelection() {
conversationsAdapter.clearSelection()
}
override fun themeChanged() {
binding.recyclerView.scrapViews()
}
override fun showBlockingDialog(conversations: List<Long>, block: Boolean) {
blockingDialog.show(this, conversations, block)
}
override fun showDeleteDialog(conversations: List<Long>) {
val count = conversations.size
AlertDialog.Builder(this)
.setTitle(R.string.dialog_delete_title)
.setMessage(resources.getQuantityString(R.plurals.dialog_delete_message, count, count))
.setPositiveButton(R.string.button_delete) { _, _ -> confirmDeleteIntent.onNext(conversations) }
.setNegativeButton(R.string.button_cancel, null)
.show()
}
override fun showChangelog(changelog: ChangelogManager.Changelog) {
changelogDialog.show(changelog)
}
override fun showArchivedSnackbar() {
Snackbar.make(binding.drawerLayout, R.string.toast_archived, Snackbar.LENGTH_LONG).apply {
setAction(R.string.button_undo) { undoArchiveIntent.onNext(Unit) }
setActionTextColor(colors.theme().theme)
show()
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.main, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
optionsItemIntent.onNext(item.itemId)
return true
}
override fun onBackPressed() {
backPressedSubject.onNext(NavItem.BACK)
}
}