diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cedf103..e0298c8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -46,7 +46,6 @@ cd examples/hello-world && pn run android - `templates/` – Android/iOS project templates and zips - `examples/` – runnable example apps - `hello-world/` – minimal demo app using the library -- `experiments/` – platform experiments (Android/iOS/Briefcase) - `README.md`, `pyproject.toml` – repo docs and packaging ## Coding guidelines @@ -107,7 +106,6 @@ Recommended scopes (match the smallest accurate directory/module): - Templates and examples: - `templates` – `templates/` (Android/iOS templates, zips) - `examples` – `examples/` (e.g., `hello-world/`) - - `experiments` – `experiments/` diff --git a/docs/api/pythonnative.md b/docs/api/pythonnative.md index 744d7a4..0233735 100644 --- a/docs/api/pythonnative.md +++ b/docs/api/pythonnative.md @@ -2,8 +2,10 @@ API reference will be generated here via mkdocstrings. -Key flags and helpers (0.2.0): +Key flags and helpers: - `pythonnative.utils.IS_ANDROID`: platform flag with robust detection for Chaquopy/Android. - `pythonnative.utils.get_android_context()`: returns the current Android Activity/Context when running on Android. - `pythonnative.utils.set_android_context(ctx)`: set by `pythonnative.Page` on Android; you generally don’t call this directly. +- `pythonnative.utils.get_android_fragment_container()`: returns the current Fragment container `ViewGroup` used for page rendering. +- `pythonnative.utils.set_android_fragment_container(viewGroup)`: set by the host `PageFragment`; you generally don’t call this directly. diff --git a/docs/concepts/architecture.md b/docs/concepts/architecture.md new file mode 100644 index 0000000..c7726dc --- /dev/null +++ b/docs/concepts/architecture.md @@ -0,0 +1,63 @@ +# Architecture + +PythonNative maps Python directly to native platform APIs. Conceptually, it is closer to NativeScript's dynamic bindings than to React Native's bridge-and-module approach. + +## High-level model + +- Direct bindings: call native APIs synchronously from Python. + - iOS: rubicon-objc exposes Objective-C/Swift classes (e.g., UIViewController, UIButton, WKWebView) and lets you create dynamic Objective-C subclasses and selectors. + - Android: Chaquopy exposes Java classes (e.g., android.widget.Button, android.webkit.WebView) via the java bridge so you can construct and call methods directly. +- Shared Python API: components like Page, StackView, Label, Button, and WebView have a small, consistent surface. Platform-specific behavior is chosen at import time using pythonnative.utils.IS_ANDROID. +- Thin native bootstrap: the host app remains native (Android Activity or iOS UIViewController). It passes a live instance/pointer into Python, and Python drives the UI from there. + +## Comparison + +- Versus React Native: RN typically exposes capabilities via native modules/TurboModules and a bridge. PythonNative does not require authoring such modules for most APIs; you can access platform classes directly from Python. +- Versus NativeScript: similar philosophy—dynamic, synchronous access to Obj-C/Java from the scripting runtime. + +## iOS flow (Rubicon-ObjC) + +- The iOS template (Swift + PythonKit) boots Python and instantiates your `MainPage` with the current `UIViewController` pointer. +- In Python, Rubicon wraps the pointer; you then interact with UIKit classes directly. + +```python +from rubicon.objc import ObjCClass, ObjCInstance + +UIButton = ObjCClass("UIButton") +vc = ObjCInstance(native_ptr) # passed from Swift template +button = UIButton.alloc().init() +# Configure target/action via a dynamic Objective-C subclass (see Button implementation) +``` + +## Android flow (Chaquopy) + +- The Android template (Kotlin + Chaquopy) initializes Python in MainActivity and provides the current Activity/Context to Python. +- Components acquire the Context implicitly and construct real Android views. + +```python +from java import jclass +from pythonnative.utils import get_android_context + +WebViewClass = jclass("android.webkit.WebView") +context = get_android_context() +webview = WebViewClass(context) +webview.loadUrl("https://example.com") +``` + +## Key implications + +- Synchronous native calls: no JS bridge; Python calls are direct. +- Lifecycle rules remain native: Activities/ViewControllers are created by the OS. Python receives and controls them; it does not instantiate Android Activities directly. +- Small, growing surface: the shared Python API favors clarity and consistency, expanding progressively. + +## Navigation model overview + +- See the Navigation guide for full details and comparisons with other frameworks. + - iOS: one host `UIViewController` class, many instances pushed on a `UINavigationController`. + - Android: single host `Activity` with a `NavHostFragment` and a stack of generic `PageFragment`s driven by a navigation graph. + +## Related docs + +- Guides / Android: guides/android.md +- Guides / iOS: guides/ios.md +- Concepts / Components: concepts/components.md diff --git a/docs/concepts/components.md b/docs/concepts/components.md index e1e33aa..e9d12ca 100644 --- a/docs/concepts/components.md +++ b/docs/concepts/components.md @@ -2,7 +2,7 @@ High-level overview of PythonNative components and how they map to native UI. -## Constructor pattern (0.2.0) +## Constructor pattern - All core components share a consistent, contextless constructor on both platforms. - On Android, a `Context` is acquired implicitly from the current `Activity` set by `pn.Page`. @@ -30,7 +30,7 @@ Notes: - `pn.Page` stores the Android `Activity` so components like `pn.Button()` and `pn.Label()` can construct their native counterparts. - If you construct views before the `Page` is created on Android, a runtime error will be raised because no `Context` is available. -## Core components (0.2.0) +## Core components Stabilized with contextless constructors on both platforms: diff --git a/docs/getting-started.md b/docs/getting-started.md index bd5fb67..f35ff23 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -18,7 +18,7 @@ This scaffolds: - `requirements.txt` - `.gitignore` -A minimal `app/main_page.py` looks like: +A minimal `app/main_page.py` looks like (no bootstrap needed): ```python import pythonnative as pn @@ -36,13 +36,6 @@ class MainPage(pn.Page): button.set_on_click(lambda: print("Button clicked")) stack.add_view(button) self.set_root_view(stack) - - -def bootstrap(native_instance): - """Entry point called by the host app (Activity or ViewController).""" - page = MainPage(native_instance) - page.on_create() - return page ``` ## Run on a platform diff --git a/docs/guides/navigation.md b/docs/guides/navigation.md new file mode 100644 index 0000000..7ae0f4c --- /dev/null +++ b/docs/guides/navigation.md @@ -0,0 +1,95 @@ +# Navigation + +This guide shows how to navigate between pages and handle lifecycle events. + +## Push / Pop + +Use `push` and `pop` on your `Page` to change screens. You can pass a dotted path string or a class reference. + +```python +import pythonnative as pn + +class MainPage(pn.Page): + def on_create(self): + stack = pn.StackView() + btn = pn.Button("Go next") + btn.set_on_click(lambda: self.push("app.second_page.SecondPage", args={"message": "Hello"})) + stack.add_view(btn) + self.set_root_view(stack) +``` + +On the target page: + +```python +class SecondPage(pn.Page): + def on_create(self): + args = self.get_args() + message = args.get("message", "Second") + stack = pn.StackView() + stack.add_view(pn.Label(message)) + back = pn.Button("Back") + back.set_on_click(lambda: self.pop()) + stack.add_view(back) + self.set_root_view(stack) +``` + +## Lifecycle + +PythonNative forwards lifecycle events from the host: + +- `on_create` +- `on_start` +- `on_resume` +- `on_pause` +- `on_stop` +- `on_destroy` +- `on_restart` (Android only) +- `on_save_instance_state` +- `on_restore_instance_state` + +Android uses a single `MainActivity` hosting a `NavHostFragment` and a generic `PageFragment` per page. iOS forwards `viewWillAppear`/`viewWillDisappear` via an internal registry. + +## Notes + +- On Android, `push` navigates via `NavController` to a `PageFragment` and passes `page_path` and optional JSON `args`. +- On iOS, `push` uses the root `UINavigationController` to push a new `ViewController` and passes page info via KVC. + +## Platform specifics + +### iOS (UIViewController per page) +- Each PythonNative page is hosted by a Swift `ViewController` instance. +- Pages are pushed and popped on a root `UINavigationController`. +- Lifecycle is forwarded from Swift to the registered Python page instance. +- Root view wiring: `Page.set_root_view` sizes and inserts the Python-native view into the controller’s view. + +Why this matches iOS conventions +- iOS apps commonly model screens as `UIViewController`s and use `UINavigationController` for hierarchical navigation. +- The approach integrates cleanly with add-to-app and system behaviors (e.g., state restoration). + +### Android (single Activity, Fragment stack) +- Single host `MainActivity` sets a `NavHostFragment` containing a navigation graph. +- Each PythonNative page is represented by a generic `PageFragment` which instantiates the Python page and attaches its root view. +- `push`/`pop` delegate to `NavController` (via a small `Navigator` helper). +- Arguments (`page_path`, `args_json`) live in Fragment arguments and restore across configuration changes and process death. + +Why this matches Android conventions +- Modern Android apps favor one Activity with many Fragments, using Jetpack Navigation for back stack, transitions, and deep links. +- It simplifies lifecycle, back handling, and state compared to one-Activity-per-screen. + +## Comparison to other frameworks +- React Native + - Android: single `Activity`, screens managed via `Fragment`s (e.g., `react-native-screens`). + - iOS: screens map to `UIViewController`s pushed on `UINavigationController`. +- .NET MAUI / Xamarin.Forms + - Android: single `Activity`, pages via Fragments/Navigation. + - iOS: pages map to `UIViewController`s on a `UINavigationController`. +- NativeScript + - Android: single `Activity`, pages as `Fragment`s. + - iOS: pages as `UIViewController`s on `UINavigationController`. +- Flutter (special case) + - Android: single `Activity` (`FlutterActivity`/`FlutterFragmentActivity`). + - iOS: `FlutterViewController` hosts Flutter’s internal navigator; add-to-app can push multiple `FlutterViewController`s. + +Bottom line +- iOS: one host VC class, many instances on a `UINavigationController`. +- Android: one host `Activity`, many `Fragment`s with Jetpack Navigation. diff --git a/examples/hello-world/app/main_page.py b/examples/hello-world/app/main_page.py index 8a36892..032ef3b 100644 --- a/examples/hello-world/app/main_page.py +++ b/examples/hello-world/app/main_page.py @@ -22,8 +22,20 @@ def on_create(self): except Exception: pass stack.add_view(pn.Label("Hello from PythonNative Demo!")) - button = pn.Button("Tap me") - button.set_on_click(lambda: print("Demo button clicked")) + button = pn.Button("Go to Second Page") + + def on_next(): + # Visual confirmation that tap worked (iOS only) + try: + if UIColor is not None: + button.native_instance.setBackgroundColor_(UIColor.systemGreenColor()) + button.native_instance.setTitleColor_forState_(UIColor.whiteColor(), 0) + except Exception: + pass + # Demonstrate passing args + self.push("app.second_page.SecondPage", args={"message": "Greetings from MainPage"}) + + button.set_on_click(on_next) # Make the button visually obvious try: if UIColor is not None: @@ -57,9 +69,3 @@ def on_save_instance_state(self): def on_restore_instance_state(self): super().on_restore_instance_state() - - -def bootstrap(native_instance): - page = MainPage(native_instance) - page.on_create() - return page diff --git a/examples/hello-world/app/second_page.py b/examples/hello-world/app/second_page.py index 9be9495..99af521 100644 --- a/examples/hello-world/app/second_page.py +++ b/examples/hello-world/app/second_page.py @@ -1,5 +1,13 @@ import pythonnative as pn +try: + # Optional: iOS styling support (safe if rubicon isn't available) + from rubicon.objc import ObjCClass + + UIColor = ObjCClass("UIColor") +except Exception: # pragma: no cover + UIColor = None + class SecondPage(pn.Page): def __init__(self, native_instance): @@ -8,8 +16,35 @@ def __init__(self, native_instance): def on_create(self): super().on_create() stack_view = pn.StackView() - label = pn.Label("Second page!") - stack_view.add_view(label) + # Read args passed from MainPage + args = self.get_args() + message = args.get("message", "Second page!") + stack_view.add_view(pn.Label(message)) + # Navigate to Third Page + to_third_btn = pn.Button("Go to Third Page") + # Style button on iOS similar to MainPage + try: + if UIColor is not None: + to_third_btn.native_instance.setBackgroundColor_(UIColor.systemBlueColor()) + to_third_btn.native_instance.setTitleColor_forState_(UIColor.whiteColor(), 0) + except Exception: + pass + + def on_next(): + # Visual confirmation that tap worked (iOS only) + try: + if UIColor is not None: + to_third_btn.native_instance.setBackgroundColor_(UIColor.systemGreenColor()) + to_third_btn.native_instance.setTitleColor_forState_(UIColor.whiteColor(), 0) + except Exception: + pass + self.push("app.third_page.ThirdPage", args={"from": "Second"}) + + to_third_btn.set_on_click(on_next) + stack_view.add_view(to_third_btn) + back_btn = pn.Button("Back") + back_btn.set_on_click(lambda: self.pop()) + stack_view.add_view(back_btn) self.set_root_view(stack_view) def on_start(self): diff --git a/examples/hello-world/app/third_page.py b/examples/hello-world/app/third_page.py new file mode 100644 index 0000000..6c06594 --- /dev/null +++ b/examples/hello-world/app/third_page.py @@ -0,0 +1,30 @@ +import pythonnative as pn + +try: + # Optional: iOS styling support (safe if rubicon isn't available) + from rubicon.objc import ObjCClass + + UIColor = ObjCClass("UIColor") +except Exception: # pragma: no cover + UIColor = None + + +class ThirdPage(pn.Page): + def __init__(self, native_instance): + super().__init__(native_instance) + + def on_create(self): + super().on_create() + stack = pn.StackView() + stack.add_view(pn.Label("This is the Third Page")) + back_btn = pn.Button("Back") + # Style button on iOS similar to MainPage + try: + if UIColor is not None: + back_btn.native_instance.setBackgroundColor_(UIColor.systemBlueColor()) + back_btn.native_instance.setTitleColor_forState_(UIColor.whiteColor(), 0) + except Exception: + pass + back_btn.set_on_click(lambda: self.pop()) + stack.add_view(back_btn) + self.set_root_view(stack) diff --git a/experiments/android_pythonnative_3/.gitignore b/experiments/android_pythonnative_3/.gitignore deleted file mode 100644 index aa724b7..0000000 --- a/experiments/android_pythonnative_3/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -*.iml -.gradle -/local.properties -/.idea/caches -/.idea/libraries -/.idea/modules.xml -/.idea/workspace.xml -/.idea/navEditor.xml -/.idea/assetWizardSettings.xml -.DS_Store -/build -/captures -.externalNativeBuild -.cxx -local.properties diff --git a/experiments/android_pythonnative_3/app/.gitignore b/experiments/android_pythonnative_3/app/.gitignore deleted file mode 100644 index 42afabf..0000000 --- a/experiments/android_pythonnative_3/app/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/experiments/android_pythonnative_3/app/build.gradle b/experiments/android_pythonnative_3/app/build.gradle deleted file mode 100644 index 50bbbfe..0000000 --- a/experiments/android_pythonnative_3/app/build.gradle +++ /dev/null @@ -1,59 +0,0 @@ -plugins { - id 'com.android.application' - id 'org.jetbrains.kotlin.android' - id 'com.chaquo.python' -} - -android { - namespace 'com.pythonnative.pythonnative' - compileSdk 33 - - defaultConfig { - applicationId "com.pythonnative.pythonnative" - minSdk 24 - targetSdk 33 - versionCode 1 - versionName "1.0" - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - ndk { - abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64" - } - python { - pip { - // https://chaquo.com/chaquopy/doc/current/android.html#android-requirements -// install "matplotlib" -// install "pythonnative" - - // A directory containing a setup.py, relative to the project - // directory (must contain at least one slash): - install "/Users/owenthcarey/Documents/pythonnative-workspace/libs/pythonnative" - } - } - } - - buildTypes { - release { - minifyEnabled 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 'androidx.core:core-ktx:1.8.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.5.0' - implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.5' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' -} \ No newline at end of file diff --git a/experiments/android_pythonnative_3/app/proguard-rules.pro b/experiments/android_pythonnative_3/app/proguard-rules.pro deleted file mode 100644 index 481bb43..0000000 --- a/experiments/android_pythonnative_3/app/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# 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 \ No newline at end of file diff --git a/experiments/android_pythonnative_3/app/src/androidTest/java/com/pythonnative/pythonnative/ExampleInstrumentedTest.kt b/experiments/android_pythonnative_3/app/src/androidTest/java/com/pythonnative/pythonnative/ExampleInstrumentedTest.kt deleted file mode 100644 index e2269ba..0000000 --- a/experiments/android_pythonnative_3/app/src/androidTest/java/com/pythonnative/pythonnative/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.pythonnative.pythonnative - -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.pythonnative.pythonnative", appContext.packageName) - } -} \ No newline at end of file diff --git a/experiments/android_pythonnative_3/app/src/main/AndroidManifest.xml b/experiments/android_pythonnative_3/app/src/main/AndroidManifest.xml deleted file mode 100644 index 411d3d1..0000000 --- a/experiments/android_pythonnative_3/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/experiments/android_pythonnative_3/app/src/main/java/com/pythonnative/pythonnative/MainActivity.kt b/experiments/android_pythonnative_3/app/src/main/java/com/pythonnative/pythonnative/MainActivity.kt deleted file mode 100644 index b29e93e..0000000 --- a/experiments/android_pythonnative_3/app/src/main/java/com/pythonnative/pythonnative/MainActivity.kt +++ /dev/null @@ -1,144 +0,0 @@ -package com.pythonnative.pythonnative - -import android.graphics.BitmapFactory -import androidx.appcompat.app.AppCompatActivity -import android.os.Bundle -import android.util.Log -import android.widget.Button -import android.widget.ImageView -import android.widget.TextView -import android.graphics.Color -import android.view.View -import android.widget.LinearLayout -import androidx.constraintlayout.widget.ConstraintLayout -import androidx.recyclerview.widget.RecyclerView -import com.chaquo.python.PyException -import com.chaquo.python.PyObject -import com.chaquo.python.Python -import com.chaquo.python.android.AndroidPlatform -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import org.json.JSONObject - -class MainActivity : AppCompatActivity() { - private val TAG = javaClass.simpleName - private lateinit var page: PyObject - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - Log.d(TAG, "onCreate() called") - -// setContentView(R.layout.activity_main) -// val layoutMain = findViewById(R.id.layout_main) - - // Initialize Chaquopy - if (!Python.isStarted()) { - Python.start(AndroidPlatform(this)) - } - val py = Python.getInstance() - - // Create an instance of the Page class -// val pyModule = py.getModule("app/main_2") -// page = pyModule.callAttr("Page", this) -// val pyLayout = page.callAttr("on_create").toJava(View::class.java) -// setContentView(pyLayout) - - // Create an instance of the Page class - val pyModule = py.getModule("app/main_3") - page = pyModule.callAttr("MainPage", this) - page.callAttr("on_create") - -// val pyModule = py.getModule("app/main") -// val pyLayout = pyModule.callAttr("on_create", this).toJava(View::class.java) -// setContentView(pyLayout) - -// val createButtonModule = py.getModule("create_button") -// val pyButton = createButtonModule.callAttr("create_button", this).toJava(Button::class.java) -// layoutMain.addView(pyButton) - -// val createWidgetsModule = py.getModule("create_widgets") -// val pyLayout = createWidgetsModule.callAttr("create_widgets", this).toJava(LinearLayout::class.java) -// layoutMain.addView(pyLayout) - -// val createConstraintLayoutModule = py.getModule("create_constraint_layout") -// val pyLayout = createConstraintLayoutModule.callAttr("create_constraint_layout", this).toJava(ConstraintLayout::class.java) -// layoutMain.addView(pyLayout) - -// val createRecyclerViewModule = py.getModule("create_recycler_view") -// val pyRecyclerView = createRecyclerViewModule.callAttr("create_recycler_view", this).toJava(RecyclerView::class.java) -// layoutMain.addView(pyRecyclerView) - - // Existing code for displaying plot -// val imageView = findViewById(R.id.image_home) -// val plotModule = py.getModule("plot") -// val xInput = "1 2 3 4 5" -// val yInput = "1 4 9 16 25" -// CoroutineScope(Dispatchers.Main).launch { -// try { -// val bytes = plotModule.callAttr( -// "plot", -// xInput, -// yInput -// ).toJava(ByteArray::class.java) -// withContext(Dispatchers.IO) { -// val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size) -// withContext(Dispatchers.Main) { -// imageView.setImageBitmap(bitmap) -// } -// } -// } catch (e: PyException) { -// Log.e("Python Error", "Error executing Python code", e) -// } -// } - } - - override fun onStart() { - super.onStart() - Log.d(TAG, "onStart() called") - page.callAttr("on_start") - } - - override fun onResume() { - super.onResume() - Log.d(TAG, "onResume() called") - page.callAttr("on_resume") - } - - override fun onPause() { - super.onPause() - Log.d(TAG, "onPause() called") - page.callAttr("on_pause") - } - - override fun onStop() { - super.onStop() - Log.d(TAG, "onStop() called") - page.callAttr("on_stop") - } - - override fun onDestroy() { - super.onDestroy() - Log.d(TAG, "onDestroy() called") - page.callAttr("on_destroy") - } - - override fun onRestart() { - super.onRestart() - Log.d(TAG, "onRestart() called") - page.callAttr("on_restart") - } - - override fun onSaveInstanceState(outState: Bundle) { - super.onSaveInstanceState(outState) - Log.d(TAG, "onSaveInstanceState() called") - page.callAttr("on_save_instance_state") - } - - override fun onRestoreInstanceState(savedInstanceState: Bundle) { - super.onRestoreInstanceState(savedInstanceState) - Log.d(TAG, "onRestoreInstanceState() called") - page.callAttr("on_restore_instance_state") - } -} diff --git a/experiments/android_pythonnative_3/app/src/main/java/com/pythonnative/pythonnative/SecondActivity.kt b/experiments/android_pythonnative_3/app/src/main/java/com/pythonnative/pythonnative/SecondActivity.kt deleted file mode 100644 index e377e5e..0000000 --- a/experiments/android_pythonnative_3/app/src/main/java/com/pythonnative/pythonnative/SecondActivity.kt +++ /dev/null @@ -1,73 +0,0 @@ -package com.pythonnative.pythonnative - -import androidx.appcompat.app.AppCompatActivity -import android.os.Bundle -import android.util.Log -import com.chaquo.python.PyObject -import com.chaquo.python.Python -import com.chaquo.python.android.AndroidPlatform - -class SecondActivity : AppCompatActivity() { - private val TAG = javaClass.simpleName - private lateinit var page: PyObject - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - Log.d(TAG, "onCreate() called") - if (!Python.isStarted()) { - Python.start(AndroidPlatform(this)) - } - val py = Python.getInstance() - val pyModule = py.getModule("app/second_page") - page = pyModule.callAttr("SecondPage", this) - page.callAttr("on_create") - } - - override fun onStart() { - super.onStart() - Log.d(TAG, "onStart() called") - page.callAttr("on_start") - } - - override fun onResume() { - super.onResume() - Log.d(TAG, "onResume() called") - page.callAttr("on_resume") - } - - override fun onPause() { - super.onPause() - Log.d(TAG, "onPause() called") - page.callAttr("on_pause") - } - - override fun onStop() { - super.onStop() - Log.d(TAG, "onStop() called") - page.callAttr("on_stop") - } - - override fun onDestroy() { - super.onDestroy() - Log.d(TAG, "onDestroy() called") - page.callAttr("on_destroy") - } - - override fun onRestart() { - super.onRestart() - Log.d(TAG, "onRestart() called") - page.callAttr("on_restart") - } - - override fun onSaveInstanceState(outState: Bundle) { - super.onSaveInstanceState(outState) - Log.d(TAG, "onSaveInstanceState() called") - page.callAttr("on_save_instance_state") - } - - override fun onRestoreInstanceState(savedInstanceState: Bundle) { - super.onRestoreInstanceState(savedInstanceState) - Log.d(TAG, "onRestoreInstanceState() called") - page.callAttr("on_restore_instance_state") - } -} \ No newline at end of file diff --git a/experiments/android_pythonnative_3/app/src/main/python/app/__init__.py b/experiments/android_pythonnative_3/app/src/main/python/app/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/experiments/android_pythonnative_3/app/src/main/python/app/main.py b/experiments/android_pythonnative_3/app/src/main/python/app/main.py deleted file mode 100644 index 2eab767..0000000 --- a/experiments/android_pythonnative_3/app/src/main/python/app/main.py +++ /dev/null @@ -1,109 +0,0 @@ -import pythonnative as pn - - -def on_create(context): - stack_view = pn.StackView(context) - - # label = pn.Label(context, "This is a PythonNative label") - # stack_view.add_view(label) - # - # switch = pn.Switch(context) - # stack_view.add_view(switch) - # - # text_field = pn.TextField(context) - # stack_view.add_view(text_field) - # - # text_view = pn.TextView(context) - # stack_view.add_view(text_view) - - activity_indicator_view = pn.ActivityIndicatorView(context) - activity_indicator_view.start_animating() - stack_view.add_view(activity_indicator_view) - - material_activity_indicator_view = pn.MaterialActivityIndicatorView(context) - material_activity_indicator_view.start_animating() - stack_view.add_view(material_activity_indicator_view) - - progress_view = pn.ProgressView(context) - progress_view.set_progress(0.5) - stack_view.add_view(progress_view) - - material_progress_view = pn.MaterialProgressView(context) - material_progress_view.set_progress(0.5) - stack_view.add_view(material_progress_view) - - material_button = pn.MaterialButton(context, "MaterialButton") - stack_view.add_view(material_button) - - search_bar = pn.SearchBar(context) - stack_view.add_view(search_bar) - - image_view = pn.ImageView(context) - stack_view.add_view(image_view) - - picker_view = pn.PickerView(context) - stack_view.add_view(picker_view) - - # date_picker = pn.DatePicker(context) - # stack_view.add_view(date_picker) - - # time_picker = pn.TimePicker(context) - # stack_view.add_view(time_picker) - - # TODO: fix - # material_time_picker = pn.MaterialTimePicker(context) - # stack_view.add_view(material_time_picker) - - # TODO: fix - # material_date_picker = pn.MaterialDatePicker(context) - # stack_view.add_view(material_date_picker) - - # TODO: fix - # material_switch = pn.MaterialSwitch(context) - # stack_view.add_view(material_switch) - - # TODO: fix - # material_search_bar = pn.MaterialSearchBar(context) - # stack_view.add_view(material_search_bar) - - # web_view = pn.WebView(context) - # web_view.load_url("https://www.djangoproject.com/") - # stack_view.add_view(web_view) - # - # for i in range(100): - # button = pn.Button(context, "Click me") - # stack_view.add_view(button) - - return stack_view.native_instance - - -def on_start(): - print("on_start() called") - - -def on_resume(): - print("on_resume() called") - - -def on_pause(): - print("on_pause() called") - - -def on_stop(): - print("on_stop() called") - - -def on_destroy(): - print("on_destroy() called") - - -def on_restart(): - print("on_restart() called") - - -def on_save_instance_state(): - print("on_save_instance_state() called") - - -def on_restore_instance_state(): - print("on_restore_instance_state() called") diff --git a/experiments/android_pythonnative_3/app/src/main/python/app/main_2.py b/experiments/android_pythonnative_3/app/src/main/python/app/main_2.py deleted file mode 100644 index 1dba4ee..0000000 --- a/experiments/android_pythonnative_3/app/src/main/python/app/main_2.py +++ /dev/null @@ -1,38 +0,0 @@ -import pythonnative as pn - - -class Page: - def __init__(self, context): - self.context = context - - def on_create(self): - print("on_create() called") - stack_view = pn.StackView(self.context) - material_button = pn.MaterialButton(self.context, "MaterialButton") - stack_view.add_view(material_button) - # Create and add other views to the stack_view here - return stack_view.native_instance - - def on_start(self): - print("on_start() called") - - def on_resume(self): - print("on_resume() called") - - def on_pause(self): - print("on_pause() called") - - def on_stop(self): - print("on_stop() called") - - def on_destroy(self): - print("on_destroy() called") - - def on_restart(self): - print("on_restart() called") - - def on_save_instance_state(self): - print("on_save_instance_state() called") - - def on_restore_instance_state(self): - print("on_restore_instance_state() called") diff --git a/experiments/android_pythonnative_3/app/src/main/python/app/main_3.py b/experiments/android_pythonnative_3/app/src/main/python/app/main_3.py deleted file mode 100644 index 6c24d43..0000000 --- a/experiments/android_pythonnative_3/app/src/main/python/app/main_3.py +++ /dev/null @@ -1,42 +0,0 @@ -import pythonnative as pn - - -class MainPage(pn.Page): - def __init__(self, native_instance): - super().__init__(native_instance) - - def on_create(self): - super().on_create() - stack_view = pn.StackView(self.native_instance) - # list_data = ["item_{}".format(i) for i in range(100)] - # list_view = pn.ListView(self.native_instance, list_data) - # stack_view.add_view(list_view) - button = pn.Button(self.native_instance, "Button") - button.set_on_click(lambda: self.navigate_to("")) - # button.set_on_click(lambda: print("Button was clicked!")) - stack_view.add_view(button) - self.set_root_view(stack_view) - - def on_start(self): - super().on_start() - - def on_resume(self): - super().on_resume() - - def on_pause(self): - super().on_pause() - - def on_stop(self): - super().on_stop() - - def on_destroy(self): - super().on_destroy() - - def on_restart(self): - super().on_restart() - - def on_save_instance_state(self): - super().on_save_instance_state() - - def on_restore_instance_state(self): - super().on_restore_instance_state() diff --git a/experiments/android_pythonnative_3/app/src/main/python/app/second_page.py b/experiments/android_pythonnative_3/app/src/main/python/app/second_page.py deleted file mode 100644 index 442fb53..0000000 --- a/experiments/android_pythonnative_3/app/src/main/python/app/second_page.py +++ /dev/null @@ -1,37 +0,0 @@ -import pythonnative as pn - - -class SecondPage(pn.Page): - def __init__(self, native_instance): - super().__init__(native_instance) - - def on_create(self): - super().on_create() - stack_view = pn.StackView(self.native_instance) - label = pn.Label(self.native_instance, "Second page!") - stack_view.add_view(label) - self.set_root_view(stack_view) - - def on_start(self): - super().on_start() - - def on_resume(self): - super().on_resume() - - def on_pause(self): - super().on_pause() - - def on_stop(self): - super().on_stop() - - def on_destroy(self): - super().on_destroy() - - def on_restart(self): - super().on_restart() - - def on_save_instance_state(self): - super().on_save_instance_state() - - def on_restore_instance_state(self): - super().on_restore_instance_state() diff --git a/experiments/android_pythonnative_3/app/src/main/python/create_button.py b/experiments/android_pythonnative_3/app/src/main/python/create_button.py deleted file mode 100644 index 1924e4a..0000000 --- a/experiments/android_pythonnative_3/app/src/main/python/create_button.py +++ /dev/null @@ -1,8 +0,0 @@ -from java import cast, chaquopy, dynamic_proxy, jarray, jclass - - -def create_button(context): - Button = jclass("android.widget.Button") - button = Button(context) - button.setText("Button created in Python") - return button diff --git a/experiments/android_pythonnative_3/app/src/main/python/create_constraint_layout.py b/experiments/android_pythonnative_3/app/src/main/python/create_constraint_layout.py deleted file mode 100644 index 9d295bd..0000000 --- a/experiments/android_pythonnative_3/app/src/main/python/create_constraint_layout.py +++ /dev/null @@ -1,46 +0,0 @@ -from java import jclass - - -BottomNavigationView = jclass( - "com.google.android.material.bottomnavigation.BottomNavigationView" -) -ConstraintLayout = jclass("androidx.constraintlayout.widget.ConstraintLayout") -View = jclass("android.view.View") -ViewGroup = jclass("android.view.ViewGroup") - - -def create_constraint_layout(context): - # Create ConstraintLayout - layout = ConstraintLayout(context) - layout_params = ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT - ) - layout.setLayoutParams(layout_params) - - # Create BottomNavigationView - bottom_nav = BottomNavigationView(context) - bottom_nav.setId( - View.generateViewId() - ) # Add this line to generate unique id for the view - - # Create Menu for BottomNavigationView - menu = bottom_nav.getMenu() - - # Add items to the menu - menu.add(0, 0, 0, "Home") - menu.add(0, 1, 0, "Search") - menu.add(0, 2, 0, "Notifications") - menu.add(0, 3, 0, "Messages") - menu.add(0, 4, 0, "Profile") - - # Add BottomNavigationView to ConstraintLayout - nav_layout_params = ConstraintLayout.LayoutParams( - ConstraintLayout.LayoutParams.MATCH_PARENT, - ConstraintLayout.LayoutParams.WRAP_CONTENT, - ) - # Set the constraints here - nav_layout_params.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID - bottom_nav.setLayoutParams(nav_layout_params) - layout.addView(bottom_nav) - - return layout diff --git a/experiments/android_pythonnative_3/app/src/main/python/create_pn_layout.py b/experiments/android_pythonnative_3/app/src/main/python/create_pn_layout.py deleted file mode 100644 index b4a7fde..0000000 --- a/experiments/android_pythonnative_3/app/src/main/python/create_pn_layout.py +++ /dev/null @@ -1,13 +0,0 @@ -import pythonnative as pn - - -def create_pn_layout(context): - layout = pn.StackView(context) - - label = pn.Label(context, "This is a PythonNative label") - layout.add_view(label) - - button = pn.Button(context, "Click me") - layout.add_view(button) - - return layout.native_instance diff --git a/experiments/android_pythonnative_3/app/src/main/python/create_recycler_view.py b/experiments/android_pythonnative_3/app/src/main/python/create_recycler_view.py deleted file mode 100644 index 973c75a..0000000 --- a/experiments/android_pythonnative_3/app/src/main/python/create_recycler_view.py +++ /dev/null @@ -1,42 +0,0 @@ -from java import jclass, static_proxy, Override - -LinearLayoutManager = jclass("androidx.recyclerview.widget.LinearLayoutManager") -RecyclerView = jclass("androidx.recyclerview.widget.RecyclerView") -TextView = jclass("android.widget.TextView") - - -# RecyclerView ViewHolder -class MyViewHolder(static_proxy(RecyclerView.ViewHolder)): - def __init__(self, item_view): - super(MyViewHolder, self).__init__(item_view) - self.my_text_view = TextView(item_view.getContext()) - - -# RecyclerView Adapter -class MyAdapter(static_proxy(RecyclerView.Adapter)): - def __init__(self, my_dataset): - self.my_dataset = my_dataset - - @Override(RecyclerView.Adapter) - def onCreateViewHolder(self, parent, viewType): - text_view = TextView(parent.getContext()) - return MyViewHolder(text_view) - - @Override(RecyclerView.Adapter) - def onBindViewHolder(self, holder, position): - holder.my_text_view.setText(self.my_dataset[position]) - - @Override(RecyclerView.Adapter) - def getItemCount(self): - return len(self.my_dataset) - - -# Create the RecyclerView -def create_recycler_view(context): - my_recycler_view = RecyclerView(context) - my_layout_manager = LinearLayoutManager(context) - my_recycler_view.setLayoutManager(my_layout_manager) - my_dataset = ["Data 1", "Data 2", "Data 3"] - my_adapter = MyAdapter(my_dataset) - my_recycler_view.setAdapter(my_adapter) - return my_recycler_view diff --git a/experiments/android_pythonnative_3/app/src/main/python/create_widgets.py b/experiments/android_pythonnative_3/app/src/main/python/create_widgets.py deleted file mode 100644 index 22668b3..0000000 --- a/experiments/android_pythonnative_3/app/src/main/python/create_widgets.py +++ /dev/null @@ -1,162 +0,0 @@ -from java import dynamic_proxy, jclass, static_proxy -import random - -# Import View class which contains OnClickListener -View = jclass('android.view.View') -Color = jclass('android.graphics.Color') - - -class ButtonClickListener(dynamic_proxy(View.OnClickListener)): - def __init__(self, button): - super().__init__() - self.button = button - - def onClick(self, view): - # Generate a random hex color. - color = "#" + "".join( - [random.choice("0123456789ABCDEF") for _ in range(6)]) - - # Set the button's background color. - self.button.setBackgroundColor(Color.parseColor(color)) - - # Print something to the console. - print("Button clicked! New color is " + color) - - -def create_widgets(context): - # Java Classes - RelativeLayout = jclass("android.widget.RelativeLayout") - FrameLayout = jclass("android.widget.FrameLayout") - GridLayout = jclass("android.widget.GridLayout") - LinearLayout = jclass("android.widget.LinearLayout") - Button = jclass("android.widget.Button") - TextView = jclass("android.widget.TextView") - EditText = jclass("android.widget.EditText") - CheckBox = jclass("android.widget.CheckBox") - RadioButton = jclass("android.widget.RadioButton") - ImageView = jclass("android.widget.ImageView") - ProgressBar = jclass("android.widget.ProgressBar") - Switch = jclass("android.widget.Switch") - ToggleButton = jclass("android.widget.ToggleButton") - SeekBar = jclass("android.widget.SeekBar") - CardView = jclass("androidx.cardview.widget.CardView") - ViewPager = jclass("androidx.viewpager.widget.ViewPager") - DatePicker = jclass("android.widget.DatePicker") - TimePicker = jclass("android.widget.TimePicker") - Spinner = jclass("android.widget.Spinner") - AutoCompleteTextView = jclass("android.widget.AutoCompleteTextView") - RatingBar = jclass("android.widget.RatingBar") - AbsoluteLayout = jclass("android.widget.AbsoluteLayout") - ScrollView = jclass("android.widget.ScrollView") - HorizontalScrollView = jclass("android.widget.HorizontalScrollView") - TableLayout = jclass("android.widget.TableLayout") - TableRow = jclass("android.widget.TableRow") - ViewFlipper = jclass("android.widget.ViewFlipper") - ViewSwitcher = jclass("android.widget.ViewSwitcher") - WebView = jclass("android.webkit.WebView") - RecyclerView = jclass("androidx.recyclerview.widget.RecyclerView") - DrawerLayout = jclass("androidx.drawerlayout.widget.DrawerLayout") - CoordinatorLayout = jclass("androidx.coordinatorlayout.widget.CoordinatorLayout") - BottomNavigationView = jclass( - "com.google.android.material.bottomnavigation.BottomNavigationView" - ) - Chip = jclass("com.google.android.material.chip.Chip") - FloatingActionButton = jclass( - "com.google.android.material.floatingactionbutton.FloatingActionButton" - ) - Snackbar = jclass("com.google.android.material.snackbar.Snackbar") - NavigationView = jclass("com.google.android.material.navigation.NavigationView") - ConstraintLayout = jclass("androidx.constraintlayout.widget.ConstraintLayout") - TextInputLayout = jclass("com.google.android.material.textfield.TextInputLayout") - MaterialCardView = jclass("com.google.android.material.card.MaterialCardView") - BottomSheetDialogFragment = jclass( - "com.google.android.material.bottomsheet.BottomSheetDialogFragment" - ) - - # Create LinearLayout - layout = LinearLayout(context) - layout_params = LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT - ) - layout.setLayoutParams(layout_params) - layout.setOrientation(LinearLayout.VERTICAL) - - # Create Button - button = Button(context) - button.setText("Button created in Python") - button.setOnClickListener(ButtonClickListener(button)) - layout.addView(button) - - # Create TextView - text_view = TextView(context) - text_view.setText("TextView created in Python") - layout.addView(text_view) - - # Create EditText - edit_text = EditText(context) - edit_text.setHint("EditText created in Python") - layout.addView(edit_text) - - # Create CheckBox - check_box = CheckBox(context) - check_box.setText("CheckBox created in Python") - layout.addView(check_box) - - # Create RadioButton - radio_button = RadioButton(context) - radio_button.setText("RadioButton created in Python") - layout.addView(radio_button) - - # Create ImageView (X) - image_view = ImageView(context) - layout.addView(image_view) - - # Create ProgressBar - progress_bar = ProgressBar(context) - layout.addView(progress_bar) - - # Create Switch - switch = Switch(context) - switch.setText("Switch created in Python") - layout.addView(switch) - - # Create ToggleButton - toggle_button = ToggleButton(context) - toggle_button.setTextOn("On") - toggle_button.setTextOff("Off") - layout.addView(toggle_button) - - # Create SeekBar (X) - seek_bar = SeekBar(context) - layout.addView(seek_bar) - - # Create CardView (X) - card_view = CardView(context) - layout.addView(card_view) - - # Create ViewPager (X) - view_pager = ViewPager(context) - layout.addView(view_pager) - - # Create DatePicker (X) - date_picker = DatePicker(context) - layout.addView(date_picker) - - # Create TimePicker (X) - time_picker = TimePicker(context) - layout.addView(time_picker) - - # Create Spinner (X) - spinner = Spinner(context) - layout.addView(spinner) - - # Create AutoCompleteTextView (X) - auto_complete_text_view = AutoCompleteTextView(context) - layout.addView(auto_complete_text_view) - - # Create RatingBar (X) - rating_bar = RatingBar(context) - layout.addView(rating_bar) - - # Return layout - return layout diff --git a/experiments/android_pythonnative_3/app/src/main/python/plot.py b/experiments/android_pythonnative_3/app/src/main/python/plot.py deleted file mode 100644 index fdfdf94..0000000 --- a/experiments/android_pythonnative_3/app/src/main/python/plot.py +++ /dev/null @@ -1,14 +0,0 @@ -import io -import matplotlib.pyplot as plt - - -def plot(x, y): - xa = [float(word) for word in x.split()] - ya = [float(word) for word in y.split()] - - fig, ax = plt.subplots() - ax.plot(xa, ya) - - f = io.BytesIO() - plt.savefig(f, format="png") - return f.getvalue() diff --git a/experiments/android_pythonnative_3/app/src/main/python/ui_layout.py b/experiments/android_pythonnative_3/app/src/main/python/ui_layout.py deleted file mode 100644 index 4dd882c..0000000 --- a/experiments/android_pythonnative_3/app/src/main/python/ui_layout.py +++ /dev/null @@ -1,24 +0,0 @@ -import json - - -def on_button_click(): - print("Button clicked!") - - -def generate_layout(): - layout = { - "widgets": [ - { - "type": "Button", - "properties": { - "text": "Click me!", - "textColor": "#FFFFFF", - "backgroundColor": "#DB4437", - }, - "eventHandlers": { - "onClick": "on_button_click", - }, - }, - ] - } - return json.dumps(layout) diff --git a/experiments/android_pythonnative_3/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/experiments/android_pythonnative_3/app/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index 2b068d1..0000000 --- a/experiments/android_pythonnative_3/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/experiments/android_pythonnative_3/app/src/main/res/drawable/ic_launcher_background.xml b/experiments/android_pythonnative_3/app/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 07d5da9..0000000 --- a/experiments/android_pythonnative_3/app/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/experiments/android_pythonnative_3/app/src/main/res/layout/activity_main.xml b/experiments/android_pythonnative_3/app/src/main/res/layout/activity_main.xml deleted file mode 100644 index 0e81562..0000000 --- a/experiments/android_pythonnative_3/app/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/experiments/android_pythonnative_3/app/src/main/res/layout/activity_second.xml b/experiments/android_pythonnative_3/app/src/main/res/layout/activity_second.xml deleted file mode 100644 index 9569f77..0000000 --- a/experiments/android_pythonnative_3/app/src/main/res/layout/activity_second.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - \ No newline at end of file diff --git a/experiments/android_pythonnative_3/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/experiments/android_pythonnative_3/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6f3b755..0000000 --- a/experiments/android_pythonnative_3/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/experiments/android_pythonnative_3/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/experiments/android_pythonnative_3/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6f3b755..0000000 --- a/experiments/android_pythonnative_3/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/experiments/android_pythonnative_3/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/experiments/android_pythonnative_3/app/src/main/res/mipmap-hdpi/ic_launcher.webp deleted file mode 100644 index c209e78..0000000 Binary files a/experiments/android_pythonnative_3/app/src/main/res/mipmap-hdpi/ic_launcher.webp and /dev/null differ diff --git a/experiments/android_pythonnative_3/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/experiments/android_pythonnative_3/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp deleted file mode 100644 index b2dfe3d..0000000 Binary files a/experiments/android_pythonnative_3/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp and /dev/null differ diff --git a/experiments/android_pythonnative_3/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/experiments/android_pythonnative_3/app/src/main/res/mipmap-mdpi/ic_launcher.webp deleted file mode 100644 index 4f0f1d6..0000000 Binary files a/experiments/android_pythonnative_3/app/src/main/res/mipmap-mdpi/ic_launcher.webp and /dev/null differ diff --git a/experiments/android_pythonnative_3/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/experiments/android_pythonnative_3/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp deleted file mode 100644 index 62b611d..0000000 Binary files a/experiments/android_pythonnative_3/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp and /dev/null differ diff --git a/experiments/android_pythonnative_3/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/experiments/android_pythonnative_3/app/src/main/res/mipmap-xhdpi/ic_launcher.webp deleted file mode 100644 index 948a307..0000000 Binary files a/experiments/android_pythonnative_3/app/src/main/res/mipmap-xhdpi/ic_launcher.webp and /dev/null differ diff --git a/experiments/android_pythonnative_3/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/experiments/android_pythonnative_3/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp deleted file mode 100644 index 1b9a695..0000000 Binary files a/experiments/android_pythonnative_3/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/experiments/android_pythonnative_3/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/experiments/android_pythonnative_3/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp deleted file mode 100644 index 28d4b77..0000000 Binary files a/experiments/android_pythonnative_3/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp and /dev/null differ diff --git a/experiments/android_pythonnative_3/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/experiments/android_pythonnative_3/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp deleted file mode 100644 index 9287f50..0000000 Binary files a/experiments/android_pythonnative_3/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/experiments/android_pythonnative_3/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/experiments/android_pythonnative_3/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp deleted file mode 100644 index aa7d642..0000000 Binary files a/experiments/android_pythonnative_3/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp and /dev/null differ diff --git a/experiments/android_pythonnative_3/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/experiments/android_pythonnative_3/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp deleted file mode 100644 index 9126ae3..0000000 Binary files a/experiments/android_pythonnative_3/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/experiments/android_pythonnative_3/app/src/main/res/values-night/themes.xml b/experiments/android_pythonnative_3/app/src/main/res/values-night/themes.xml deleted file mode 100644 index c128015..0000000 --- a/experiments/android_pythonnative_3/app/src/main/res/values-night/themes.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/experiments/android_pythonnative_3/app/src/main/res/values/colors.xml b/experiments/android_pythonnative_3/app/src/main/res/values/colors.xml deleted file mode 100644 index c8524cd..0000000 --- a/experiments/android_pythonnative_3/app/src/main/res/values/colors.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - #FF000000 - #FFFFFFFF - \ No newline at end of file diff --git a/experiments/android_pythonnative_3/app/src/main/res/values/strings.xml b/experiments/android_pythonnative_3/app/src/main/res/values/strings.xml deleted file mode 100644 index 115bda4..0000000 --- a/experiments/android_pythonnative_3/app/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - pythonnative - \ No newline at end of file diff --git a/experiments/android_pythonnative_3/app/src/main/res/values/themes.xml b/experiments/android_pythonnative_3/app/src/main/res/values/themes.xml deleted file mode 100644 index 80a3862..0000000 --- a/experiments/android_pythonnative_3/app/src/main/res/values/themes.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - -