parent
a282b3e72e
commit
cb83bc0ee7
@ -0,0 +1,35 @@
|
|||||||
|
plugins {
|
||||||
|
id("com.android.library")
|
||||||
|
kotlin("android")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "com.example.mylibrary"
|
||||||
|
compileSdk = 33
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdk = 21
|
||||||
|
targetSdk = 33
|
||||||
|
|
||||||
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
consumerProguardFiles("consumer-rules.pro")
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
isMinifyEnabled = false
|
||||||
|
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(projects.app.videolibrary)
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
# In your library's consumer-proguard-rules.pro
|
||||||
|
-keep, allowoptimization class * implements com.example.mylibrary.MyWorker {
|
||||||
|
<init>();
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepattributes *Annotation*
|
||||||
|
|
||||||
|
-keep @interface com.example.mylibrary.OnEvent
|
||||||
|
|
||||||
|
-keepclasseswithmembers class * {
|
||||||
|
@com.example.mylibrary.OnEvent <methods>;
|
||||||
|
}
|
||||||
|
|
||||||
|
-keep @interface com.example.mylibrary.ReflectiveExecutor
|
||||||
|
|
||||||
|
-keep @com.example.mylibrary.ReflectiveExecutor class *{
|
||||||
|
# Keep the public, no-argument constructor so that an instance of the class can be created.
|
||||||
|
# <init> is the internal name for a constructor.
|
||||||
|
public <init>();
|
||||||
|
|
||||||
|
# Keep the public execute() method that has no parameters.
|
||||||
|
# This is critical because TaskRunner calls getMethod("execute").
|
||||||
|
# If this method is renamed (obfuscated) or removed (shrunk), your app will crash.
|
||||||
|
public void execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.example.mylibrary
|
||||||
|
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
import org.junit.Assert.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instrumented test, which will execute on an Android device.
|
||||||
|
*
|
||||||
|
* See [testing documentation](http://d.android.com/tools/testing).
|
||||||
|
*/
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class ExampleInstrumentedTest {
|
||||||
|
@Test
|
||||||
|
fun useAppContext() {
|
||||||
|
// Context of the app under test.
|
||||||
|
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
|
assertEquals("com.example.mylibrary.test", appContext.packageName)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
</manifest>
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.example.mylibrary
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import kotlin.annotation.AnnotationRetention.RUNTIME
|
||||||
|
|
||||||
|
// In your library:
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Target(AnnotationTarget.FUNCTION)
|
||||||
|
annotation class OnEvent
|
||||||
|
|
||||||
|
class EventBus {
|
||||||
|
fun dispatch(listener: Any) {
|
||||||
|
Log.e("EventBus", "Dispatching event to $listener")
|
||||||
|
// Find all methods annotated with @OnEvent and invoke them
|
||||||
|
listener::class.java.declaredMethods.forEach { method ->
|
||||||
|
if (method.isAnnotationPresent(OnEvent::class.java)) {
|
||||||
|
try {
|
||||||
|
method.invoke(listener)
|
||||||
|
} catch (e: Exception) { /* ... */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.example.mylibrary
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This annotation is now targeted at classes.
|
||||||
|
*/
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
annotation class ReflectiveExecutor
|
||||||
|
|
||||||
|
class TaskRunner {
|
||||||
|
fun process(task: Any) {
|
||||||
|
Log.e("R8","TaskRunner processing " + task.toString())
|
||||||
|
// Get the Java Class object for the instance
|
||||||
|
val taskClass = task::class.java
|
||||||
|
// 1. Check if the CLASS is annotated with @ReflectiveExecutor
|
||||||
|
if (taskClass.isAnnotationPresent(ReflectiveExecutor::class.java)) {
|
||||||
|
// 2. If it's annotated, we assume a contract: the class must have a public method named "execute".
|
||||||
|
// We use getMethod() to find that specific method.
|
||||||
|
val methodToCall = taskClass.getMethod("execute") // Throws an exception if not found
|
||||||
|
|
||||||
|
// 3. Invoke the "execute" method on the provided 'task' instance.
|
||||||
|
methodToCall.invoke(task)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.example.mylibrary
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// This is an example of loading a class by name and running its doWork method.
|
||||||
|
|
||||||
|
interface MyWorker {
|
||||||
|
fun doWork()
|
||||||
|
}
|
||||||
|
|
||||||
|
object WorkerLoader {
|
||||||
|
fun loadAndRun(className: String) {
|
||||||
|
val workerClass = Class.forName(className)
|
||||||
|
val worker = workerClass.getDeclaredConstructor().newInstance() as MyWorker
|
||||||
|
worker.doWork()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.example.mylibrary
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
import org.junit.Assert.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example local unit test, which will execute on the development machine (host).
|
||||||
|
*
|
||||||
|
* See [testing documentation](http://d.android.com/tools/testing).
|
||||||
|
*/
|
||||||
|
class ExampleUnitTest {
|
||||||
|
@Test
|
||||||
|
fun addition_isCorrect() {
|
||||||
|
assertEquals(4, 2 + 2)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
plugins {
|
||||||
|
id("com.android.library")
|
||||||
|
kotlin("android")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "com.example.videolibrary"
|
||||||
|
compileSdk = 33
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdk = 21
|
||||||
|
targetSdk = 33
|
||||||
|
|
||||||
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
consumerProguardFiles("consumer-rules.pro")
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
isMinifyEnabled = false
|
||||||
|
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package com.example.analytics.video
|
||||||
|
|
||||||
|
class VideoEventTracker {
|
||||||
|
// This constructor must be kept for the reflection call to succeed.
|
||||||
|
init { /* ... */ }
|
||||||
|
}
|
Loading…
Reference in new issue