commit 80e07cefef6de0e7c085a784e4433eb7508a3502 Author: Alex Abudaev Date: Fri Apr 3 18:28:13 2026 +0800 Initial commit: DuckAI Android app with WebView and search widget diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d542bcc --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +# Default ignore patterns +.DS_Store +/build/ +/.gradle/ +/local.properties +*.log + +# Android +bin/ +gen/ +out/ + +# IDE +.idea/ +*.iml +*.ipr +*.iws + +# Gradle +gradle-app.setting \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..1631f76 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,39 @@ +plugins { + id 'com.android.application' + id 'org.jetbrains.kotlin.android' +} + +android { + namespace 'com.duckai.app' + compileSdk 34 + + defaultConfig { + applicationId "com.duckai.app" + minSdk 31 + targetSdk 34 + versionCode 1 + versionName "1.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = '17' + } +} + +dependencies { + implementation 'androidx.core:core-ktx:1.12.0' + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'com.google.android.material:material:1.11.0' +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..abb1621 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/duckai/app/web/MainActivity.kt b/app/src/main/java/com/duckai/app/web/MainActivity.kt new file mode 100644 index 0000000..d462144 --- /dev/null +++ b/app/src/main/java/com/duckai/app/web/MainActivity.kt @@ -0,0 +1,43 @@ +package com.duckai.app.web + +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import android.webkit.WebView +import android.webkit.WebViewClient +import androidx.appcompat.app.AppCompatActivity +import com.duckai.app.R + +class MainActivity : AppCompatActivity() { + + private lateinit var webView: WebView + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + webView = findViewById(R.id.webView) + webView.settings.javaScriptEnabled = true + webView.webViewClient = WebViewClient() + + val query = intent?.data?.getQueryParameter("q") + val url = if (query != null) { + "https://duck.ai/?q=${Uri.encode(query)}" + } else { + "https://duck.ai/" + } + + webView.loadUrl(url) + } + + override fun onNewIntent(intent: Intent?) { + super.onNewIntent(intent) + this.intent = intent + + val query = intent?.data?.getQueryParameter("q") + if (query != null) { + val url = "https://duck.ai/?q=${Uri.encode(query)}" + webView.loadUrl(url) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/duckai/app/widget/SearchWidgetProvider.kt b/app/src/main/java/com/duckai/app/widget/SearchWidgetProvider.kt new file mode 100644 index 0000000..54a4dc7 --- /dev/null +++ b/app/src/main/java/com/duckai/app/widget/SearchWidgetProvider.kt @@ -0,0 +1,38 @@ +package com.duckai.app.widget + +import android.app.PendingIntent +import android.appwidget.AppWidgetManager +import android.appwidget.AppWidgetProvider +import android.content.Context +import android.content.Intent +import android.widget.RemoteViews +import com.duckai.app.R +import com.duckai.app.web.MainActivity + +class SearchWidgetProvider : AppWidgetProvider() { + + override fun onUpdate( + context: Context, + appWidgetManager: AppWidgetManager, + appWidgetIds: IntArray + ) { + for (appWidgetId in appWidgetIds) { + val intent = Intent(context, MainActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP + } + + val pendingIntent = PendingIntent.getActivity( + context, + 0, + intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) + + val views = RemoteViews(context.packageName, R.layout.widget_search).apply { + setOnClickPendingIntent(R.id.widget_container, pendingIntent) + } + + appWidgetManager.updateAppWidget(appWidgetId, views) + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_search.xml b/app/src/main/res/drawable/ic_search.xml new file mode 100644 index 0000000..d42d391 --- /dev/null +++ b/app/src/main/res/drawable/ic_search.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/widget_background.xml b/app/src/main/res/drawable/widget_background.xml new file mode 100644 index 0000000..ce46e64 --- /dev/null +++ b/app/src/main/res/drawable/widget_background.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..2b7402b --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/widget_search.xml b/app/src/main/res/layout/widget_search.xml new file mode 100644 index 0000000..05945c8 --- /dev/null +++ b/app/src/main/res/layout/widget_search.xml @@ -0,0 +1,25 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..5c6ead8 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,6 @@ + + + DuckAI + Search + Search DuckAI + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..640ca07 --- /dev/null +++ b/app/src/main/res/values/themes.xml @@ -0,0 +1,4 @@ + + +