1 /* <lambda>null2 * Copyright (C) 2023 The Android Open Source Project 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 17 package com.google.android.torus.core.activity 18 19 import android.annotation.SuppressLint 20 import android.content.Context 21 import android.content.pm.ActivityInfo 22 import android.content.res.Configuration 23 import android.os.Bundle 24 import android.view.SurfaceHolder 25 import android.view.SurfaceView 26 import androidx.appcompat.app.AppCompatActivity 27 import com.google.android.torus.core.content.ConfigurationChangeListener 28 import com.google.android.torus.core.engine.TorusEngine 29 import com.google.android.torus.core.engine.listener.TorusTouchListener 30 31 /** 32 * Helper activity to show a [TorusEngine] into a [SurfaceView]. To use it, you should override 33 * [getWallpaperEngine] and return an instance of your[TorusEngine] that will draw inside the 34 * given surface. 35 * 36 * Note: [TorusViewerActivity] subclasses must include the following attribute/s 37 * in the AndroidManifest.xml: 38 * - android:configChanges="uiMode" 39 */ 40 abstract class TorusViewerActivity : AppCompatActivity() { 41 private lateinit var wallpaperEngine: TorusEngine 42 private lateinit var surfaceView: SurfaceView 43 44 /** 45 * Must be implemented to return a new instance of [TorusEngine]. 46 */ 47 abstract fun getWallpaperEngine(context: Context, surfaceView: SurfaceView): TorusEngine 48 49 @SuppressLint("ClickableViewAccessibility") 50 override fun onCreate(savedInstanceState: Bundle?) { 51 super.onCreate(savedInstanceState) 52 53 // Check that class includes the proper attributes in the AndroidManifest.xml 54 checkManifestAttributes() 55 56 surfaceView = SurfaceView(this).apply { setContentView(this) } 57 wallpaperEngine = getWallpaperEngine(this, surfaceView) 58 wallpaperEngine.create() 59 surfaceView.holder.addCallback(object : SurfaceHolder.Callback { 60 override fun surfaceChanged( 61 holder: SurfaceHolder, 62 format: Int, 63 width: Int, 64 height: Int 65 ) { 66 wallpaperEngine.resize(width, height) 67 } 68 69 override fun surfaceDestroyed(holder: SurfaceHolder) { 70 } 71 72 override fun surfaceCreated(holder: SurfaceHolder) { 73 } 74 }) 75 76 // Pass the touch events. 77 if (wallpaperEngine is TorusTouchListener) { 78 surfaceView.setOnTouchListener { _, event -> 79 (wallpaperEngine as TorusTouchListener).onTouchEvent(event) 80 true 81 } 82 } 83 } 84 85 override fun onResume() { 86 super.onResume() 87 wallpaperEngine.resume() 88 } 89 90 override fun onPause() { 91 super.onPause() 92 wallpaperEngine.pause() 93 } 94 95 override fun onDestroy() { 96 super.onDestroy() 97 wallpaperEngine.destroy() 98 } 99 100 override fun onConfigurationChanged(newConfig: Configuration) { 101 super.onConfigurationChanged(newConfig) 102 103 if (wallpaperEngine is ConfigurationChangeListener) { 104 (wallpaperEngine as ConfigurationChangeListener).onConfigurationChanged(newConfig) 105 } 106 } 107 108 private fun checkManifestAttributes() { 109 val configChange = packageManager.getActivityInfo(componentName, 0).configChanges 110 111 // Check if Activity sets android:configChanges="uiMode" in the manifest. 112 if ((configChange and ActivityInfo.CONFIG_UI_MODE) != ActivityInfo.CONFIG_UI_MODE) { 113 throw RuntimeException( 114 "${TorusViewerActivity::class.simpleName} " + 115 "has to include the attribute android:configChanges=\"uiMode\" " + 116 "in the AndroidManifest.xml" 117 ) 118 } 119 } 120 } 121