应用程序在启动时崩溃。这是什么错误,如何修复它,我不明白
FATAL EXCEPTION: main
Process: ru.bruimafia.pixabaylite, PID: 11137
java.lang.Error: Can not init animatorClazz instance
at androidx.appcompat.app.r.t(SourceFile:109)
at androidx.swiperefreshlayout.widget.c.onAnimationEnd(SourceFile:12)
at android.graphics.animation.RenderNodeAnimator.onFinished(RenderNodeAnimator.java:370)
at android.animation.RevealAnimator.onFinished(RevealAnimator.java:43)
at android.graphics.animation.RenderNodeAnimator$$ExternalSyntheticLambda0.run(Unknown Source:2)
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7872)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
字符串
的数据
这是类代码MainActivity类。怎么了?应用程序启动并因错误而崩溃。Splashscreen有时间加载。这是类代码MainActivity类。怎么了?应用程序启动并因错误而崩溃。Splashscreen有时间加载这是类代码MainActivity类。怎么了?应用程序启动并因错误而崩溃。启动画面有时间加载
class MainActivity : AppCompatActivity(), BillingProcessor.IBillingHandler {
private var TAG = "ADS"
private lateinit var consentInformation: ConsentInformation
private var isMobileAdsInitializeCalled = AtomicBoolean(false)
private lateinit var notificationBuilder: NotificationCompat.Builder
private lateinit var bind: ActivityMainBinding
private lateinit var appUpdateManager: AppUpdateManager
private var adapter: ImageAdapter = ImageAdapter()
private lateinit var disposable: Disposable
private lateinit var searchView: SearchView
private lateinit var bottomSheetDialog: BottomSheetDialog
//private var googleInterstitialAd: InterstitialAd? = null
private var yandexInterstitialAd: YandexInterstitialAd? = null
private var bannerAd: YandexBannerAdView? = null
private lateinit var bp: BillingProcessor
private var order = "popular"
private var query = ""
private var page = 1
private fun initializeMobileAdsSdk() {
if (isMobileAdsInitializeCalled.get()) {
return
}
isMobileAdsInitializeCalled.set(true)
// Initialize the Google Mobile Ads SDK.
MobileAds.initialize(this)
// TODO: Request an ad.
// InterstitialAd.load(...)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
bind = DataBindingUtil.setContentView(this, R.layout.activity_main)
setSupportActionBar(bind.toolbar)
bp = BillingProcessor.newBillingProcessor(bind.root.context, getString(R.string.billing_license_key), this)
bp.initialize()
if (bp.isPurchased(getString(R.string.billing_product_id)))
SharedPreferencesManager.isFullVersion = true
checkPermission()
loadData(query, order, page)
//initGoogleAdsInterstitial()
initYandexAdsInterstitial()
loadingYandexAdsBanner()
checkUpdateAvailability()
adapter.setReachEndListener(object : ImageAdapter.OnReachEndListener {
override fun onLoad() {
bind.progressBarHor.visibility = View.VISIBLE
loadData(query, order, page)
}
})
adapter.setSaveButtonListener(object : ImageAdapter.OnSaveButtonListener {
override fun onSave(image: Image, position: Int) {
showYandexAdsInterstitial()
downloadFile(image.imageURL.replace("https://pixabay.com/get/", ""))
}
})
adapter.setSearchTagListener(object : ImageAdapter.OnSearchTagListener {
override fun onSearch(title: String) {
searchView.setQuery(title, true)
searchView.isIconified = false
searchView.clearFocus()
loadData(title, order, page)
}
})
bind.swipeRefreshLayout.setOnRefreshListener {
page = 1
loadData(query, order, page)
}
bind.fab.setOnClickListener { bind.recycler.smoothScrollToPosition(0) }
bind.recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
if (dy > 0)
bind.fab.visibility = View.VISIBLE
else
bind.fab.visibility = View.GONE
}
})
if (SharedPreferencesManager.isFirstLaunch)
showAlertDialog()
}
// сервис в РФ заблокирован
private fun showAlertDialog() {
val view = layoutInflater.inflate(R.layout.bottom_sheet, null)
bottomSheetDialog = BottomSheetDialog(this, R.style.BottomSheetDialogTheme)
view.findViewById<MaterialButton>(R.id.btn_ok).setOnClickListener {
SharedPreferencesManager.isFirstLaunch = false
bottomSheetDialog.dismiss()
}
bottomSheetDialog.setContentView(view)
bottomSheetDialog.show()
}
// проверка разрешений
private fun checkPermission() {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.WRITE_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
) {
val permissions = arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE)
ActivityCompat.requestPermissions(this, permissions, 0)
}
}
// проверка обновлений
private fun checkUpdateAvailability() {
appUpdateManager = AppUpdateManagerFactory.create(this)
val appUpdateInfoTask = appUpdateManager.appUpdateInfo
appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
&& appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)
) {
appUpdateManager.startUpdateFlowForResult(
appUpdateInfo,
AppUpdateType.IMMEDIATE,
this,
8
)
}
}
}
// окно выставления оценки и отзыва
private fun requestReview() {
val reviewManager = ReviewManagerFactory.create(this)
val requestReviewFlow = reviewManager.requestReviewFlow()
requestReviewFlow.addOnCompleteListener { request ->
if (request.isSuccessful) {
val reviewInfo = request.result
val flow = reviewManager.launchReviewFlow(this, reviewInfo)
flow.addOnCompleteListener {
// SharedPreferencesManager.isPlayRating = true
}
}
}
}
// меню и строка поиска
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.main, menu)
menu?.findItem(R.id.action_buy)?.isVisible = !bp.isPurchased(getString(R.string.billing_product_id))
val searchManager = getSystemService(SEARCH_SERVICE) as SearchManager
searchView = menu!!.findItem(R.id.action_search).actionView as SearchView
searchView.maxWidth = Int.MAX_VALUE
searchView.queryHint = getString(R.string.menu_search)
searchView.setSearchableInfo(searchManager.getSearchableInfo(componentName))
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(newText: String?): Boolean {
query = newText ?: ""
page = 1
bind.progressBar.visibility = View.VISIBLE
loadData(query, order, page)
return false
}
override fun onQueryTextChange(newText: String?): Boolean {
query = newText ?: ""
page = 1
bind.progressBar.visibility = View.VISIBLE
loadData(query, order, page)
return false
}
})
return super.onCreateOptionsMenu(menu)
}
// выбор пунктов меню
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.action_sort) {
when (order) {
"popular" -> {
order = "latest"
page = 1
item.setIcon(R.drawable.ic_popular)
showMessage(getString(R.string.sort_by_latest))
}
"latest" -> {
order = "popular"
page = 1
item.setIcon(R.drawable.ic_latest)
showMessage(getString(R.string.sort_by_popular))
}
}
loadData(query, order, page)
}
if (item.itemId == R.id.action_buy) {
bp.purchase(this, getString(R.string.billing_product_id))
}
if (item.itemId == R.id.action_about) {
AboutDialog().show(supportFragmentManager, "AboutDialog")
}
return true
}
// загрузка данных
private fun loadData(q: String, order: String, page: Int) {
disposable = ApiClient.getClient("https://pixabay.com/api/")
.create(ApiService::class.java)
.getImages(q, order, page)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ imagesResponse ->
if (page <= 1)
showData(imagesResponse.images as MutableList<Image>)
else
showLoadedData(imagesResponse.images as MutableList<Image>)
},
{ throwable -> showMessage(throwable.message) }
)
}
// показ данных
private fun showData(list: MutableList<Image>) {
adapter.setList(list)
bind.recycler.adapter = adapter
page++
bind.progressBar.visibility = View.GONE
bind.swipeRefreshLayout.isRefreshing = false
}
// показ подгруженных данных
private fun showLoadedData(list: MutableList<Image>) {
adapter.updateList(list)
page++
bind.progressBarHor.visibility = View.GONE
requestReview()
}
// показ сообщения
private fun showMessage(msg: String?) {
Snackbar.make(bind.root, msg + "", Snackbar.LENGTH_LONG).show()
}
// скачивание файла
private fun downloadFile(url: String) {
showMessage(getString(R.string.download_started))
startNotificationDownload()
disposable = Retrofit.Builder()
.client(OkHttpClient.Builder().build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl("https://pixabay.com/get/")
.build()
.create(ApiService::class.java)
.downloadImage(url)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(
{
GlobalScope.launch {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
saveFileWithAPI29(it.body()!!, url)
else
saveFileBeforeAPI29(it.body()!!, url)
stopNotificationDownload()
}
},
{ throwable -> showMessage(throwable.message) }
)
}
// сохранение файла API>=29
@RequiresApi(Build.VERSION_CODES.Q)
private fun saveFileWithAPI29(body: ResponseBody, name: String): Boolean {
val fos: OutputStream
val bmp = BitmapFactory.decodeStream(body.byteStream())
try {
val contentValues = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, "pixabaylite_" + System.currentTimeMillis() + ".jpg")
put(MediaStore.Images.Media.MIME_TYPE, "image/jpg")
put(
MediaStore.Images.Media.RELATIVE_PATH,
Environment.DIRECTORY_PICTURES + File.separator + "PixabayLite"
)
}
val imageUri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
fos = contentResolver.openOutputStream(Objects.requireNonNull(imageUri)!!)!!
try {
bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos)
Objects.requireNonNull(fos)
} catch (e: Exception) {
println(e.toString())
} finally {
fos.close()
}
return true
} catch (e: Exception) {
println(e.toString())
}
return false
}
// сохранение файла API<29
private fun saveFileBeforeAPI29(body: ResponseBody, name: String): Boolean {
try {
val mediaStorageDir = File(Environment.getExternalStorageDirectory(), "PixabayLite")
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs())
showMessage(getString(R.string.error_create_folder))
}
val file = File(mediaStorageDir, "pixabaylite_" + System.currentTimeMillis() + ".jpg")
body.byteStream().use { input ->
file.outputStream().use { output -> input.copyTo(output) }
}
MediaScannerConnection.scanFile(this@MainActivity, arrayOf(file.absolutePath), null, null)
return true
} catch (e: Exception) {
println(e.toString())
}
return false
}
/*
// показ межстраничной Google рекламы в приложении
private fun showGoogleAdsInterstitial() {
if (googleInterstitialAd != null && !SharedPreferencesManager.isFullVersion)
googleInterstitialAd?.show(this)
else if (googleInterstitialAd == null && yandexInterstitialAd?.isLoaded == true && !SharedPreferencesManager.isFullVersion)
yandexInterstitialAd?.show()
else
Log.d(TAG, "Google & Yandex: the interstitial ad wasn't ready yet")
}
*/
// показ межстраничной Yandex рекламы в приложении
private fun showYandexAdsInterstitial() {
if (yandexInterstitialAd?.isLoaded == true && !SharedPreferencesManager.isFullVersion)
yandexInterstitialAd?.show()
else
Log.d(TAG, "Yandex: the interstitial ad wasn't ready yet")
}
/*
// инициализация межстраничной Google рекламы в приложении
private fun initGoogleAdsInterstitial() {
val adRequest = AdRequest.Builder().build()
InterstitialAd.load(
this,
getString(R.string.ads_google_interstitialAd_id),
adRequest,
object : InterstitialAdLoadCallback() {
override fun onAdFailedToLoad(adError: LoadAdError) {
Log.d(TAG, "Google (onAdFailedToLoad): " + adError.message)
googleInterstitialAd = null
}
override fun onAdLoaded(interstitialAd: InterstitialAd) {
Log.d(TAG, "Google: onAdLoaded")
googleInterstitialAd = interstitialAd
googleInterstitialAd?.fullScreenContentCallback = object : FullScreenContentCallback() {
override fun onAdDismissedFullScreenContent() {
Log.d(TAG, "Google: onAdDismissedFullScreenContent")
showMessage(getString(R.string.download_started))
googleInterstitialAd = null
initGoogleAdsInterstitial()
}
override fun onAdFailedToShowFullScreenContent(adError: AdError) {
Log.d(TAG, "Google: onAdFailedToShowFullScreenContent")
googleInterstitialAd = null
initGoogleAdsInterstitial()
// если с google ошибка, то тогда показываем рекламу Яндекс
if (yandexInterstitialAd?.isLoaded == true)
yandexInterstitialAd?.show()
}
override fun onAdShowedFullScreenContent() {
Log.d(TAG, "Google: onAdShowedFullScreenContent")
}
}
}
})
}
*/
// инициализация межстраничной Яндекс рекламы в приложении
private fun initYandexAdsInterstitial() {
yandexInterstitialAd = YandexInterstitialAd(this)
yandexInterstitialAd?.setAdUnitId(getString(R.string.ads_yandex_interstitialAd_unitId))
yandexInterstitialAd?.loadAd(YandexAdRequest.Builder().build())
yandexInterstitialAd?.setInterstitialAdEventListener(object : InterstitialAdEventListener {
override fun onAdLoaded() {
Log.d(TAG, "Yandex: onAdLoaded")
}
override fun onAdFailedToLoad(adRequestError: YandexAdRequestError) {
Log.d(TAG, "Yandex (onAdFailedToLoad): " + adRequestError.description)
yandexInterstitialAd = null
initYandexAdsInterstitial()
}
override fun onImpression(impressionData: YandexImpressionData?) {
Log.d(TAG, "Yandex: onImpression")
}
override fun onAdShown() {
Log.d(TAG, "Yandex: onAdShown")
}
override fun onAdDismissed() {
Log.d(TAG, "Yandex: onAdDismissed")
yandexInterstitialAd = null
initYandexAdsInterstitial()
showMessage(getString(R.string.download_started))
}
override fun onAdClicked() {
Log.d(TAG, "Yandex: onAdClicked")
}
override fun onLeftApplication() {
Log.d(TAG, "Yandex: onLeftApplication")
}
override fun onReturnedToApplication() {
Log.d(TAG, "Yandex: onReturnedToApplication")
}
})
}
// инициализация и отображение баннера Яндекс рекламы в приложении
private fun loadingYandexAdsBanner() {
bannerAd = bind.bannerAdView
bannerAd!!.setAdUnitId(getString(R.string.ads_yandex_banner_id))
bannerAd!!.setAdSize(AdSize.stickySize(this, Resources.getSystem().displayMetrics.widthPixels))
val adRequest = YandexAdRequest.Builder().build()
bannerAd!!.setBannerAdEventListener(object : YandexBannerAdEventListener {
override fun onAdLoaded() {
Log.d(TAG, "Yandex Banner: ")
}
override fun onAdFailedToLoad(error: YandexAdRequestError) {
Log.d(TAG, "Yandex Banner: Banner ad failed to load with code ${error.code}: ${error.description}")
}
override fun onAdClicked() {
Log.d(TAG, "Yandex Banner: Banner ad clicked")
}
override fun onLeftApplication() {
Log.d(TAG, "Yandex Banner: Left application")
}
override fun onReturnedToApplication() {
Log.d(TAG, "Yandex Banner: Returned to application")
}
override fun onImpression(data: YandexImpressionData?) {
Log.d(TAG, "Yandex Banner: Impression: ${data?.rawData}")
}
})
if (!SharedPreferencesManager.isFullVersion)
bannerAd?.loadAd(adRequest)
}
override fun onResume() {
super.onResume()
appUpdateManager
.appUpdateInfo
.addOnSuccessListener { appUpdateInfo ->
if (appUpdateInfo.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
appUpdateManager.startUpdateFlowForResult(
appUpdateInfo,
AppUpdateType.IMMEDIATE,
this,
8
)
}
}
}
override fun onDestroy() {
bp.release()
if (!disposable.isDisposed)
disposable.dispose()
yandexInterstitialAd?.destroy()
yandexInterstitialAd = null
bannerAd?.destroy()
bannerAd = null
super.onDestroy()
}
override fun onProductPurchased(productId: String, details: PurchaseInfo?) {
showMessage(getString(R.string.snackbar_reset_app))
SharedPreferencesManager.isFullVersion = true
}
override fun onPurchaseHistoryRestored() {}
override fun onBillingError(errorCode: Int, error: Throwable?) {
showMessage(error?.message)
}
override fun onBillingInitialized() {}
// запуск уведомления о скачивании файла
private fun startNotificationDownload() {
notificationBuilder = NotificationCompat.Builder(this, BuildConfig.APPLICATION_ID).apply {
setContentTitle(getString(R.string.download_process))
setSmallIcon(R.drawable.ic_download)
priority = NotificationCompat.PRIORITY_LOW
}
NotificationManagerCompat.from(this).apply {
notificationBuilder.setProgress(0, 0, true)
//notify(1, notificationBuilder.build())
}
}
// остановка уведомления о скачивании файла
private fun stopNotificationDownload() {
NotificationManagerCompat.from(this).apply {
notificationBuilder.setContentText(getString(R.string.download_complete))
.setProgress(0, 0, false)
//notify(1, notificationBuilder.build())
cancel(1)
}
}
// не работает с включенным VPN
private fun downloadFileWithDM(url: String) {
val downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val request = DownloadManager.Request(Uri.parse(url))
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE or DownloadManager.Request.NETWORK_WIFI)
.setTitle("Загрузка изображения")
.setMimeType("image/jpg")
.setAllowedOverRoaming(true)
.setAllowedOverMetered(true)
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
.setDestinationInExternalPublicDir(
Environment.DIRECTORY_PICTURES,
File.separator + "PixabayLite" + File.separator + "pixabaylite_" + System.currentTimeMillis() + ".jpg"
)
downloadManager.enqueue(request)
showMessage("Изображение будет сохранено в папку PixabayLite")
}
}
型
1条答案
按热度按时间vpfxa7rd1#
问题是Gradle版本和Splash Screen库的不兼容性。Splash Screen库(com.github.ViksaaSkool:AwesomeSplash:v1.0.0)不支持Gradle 8.1。我不得不将Gradle返回到版本7.4.2