Merge changes from topic "egg-finally" into sc-dev

* changes:
  Do you need paint chips?
  icon++
This commit is contained in:
Daniel Sandler
2021-07-26 19:01:53 +00:00
committed by Android (Google) Code Review
24 changed files with 781 additions and 113 deletions

View File

@@ -1,26 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.egg"
android:versionCode="1"
android:versionCode="12"
android:versionName="1.0">
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<!-- used for cat notifications -->
<uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
<!-- used to save cat images -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- controls -->
<uses-permission android:name="android.permission.BIND_CONTROLS" />
<application
android:icon="@drawable/icon"
android:label="@string/app_name">
<activity android:name=".quares.QuaresActivity"
<activity
android:name=".quares.QuaresActivity"
android:exported="true"
android:icon="@drawable/q_icon"
android:label="@string/q_egg_name"
android:exported="true"
android:theme="@style/QuaresTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -29,9 +31,9 @@
<activity
android:name=".paint.PaintActivity"
android:configChanges="orientation|keyboardHidden|screenSize|uiMode"
android:exported="true"
android:icon="@drawable/p_icon"
android:label="@string/p_egg_name"
android:exported="true"
android:theme="@style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -39,13 +41,15 @@
</activity>
<!-- Android N easter egg bits -->
<activity android:name=".neko.NekoLand"
android:theme="@android:style/Theme.Material.NoActionBar"
<activity
android:name=".neko.NekoLand"
android:exported="true"
android:label="@string/app_name">
android:label="@string/app_name"
android:theme="@android:style/Theme.Material.NoActionBar">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
@@ -54,25 +58,24 @@
<service
android:name=".neko.NekoService"
android:enabled="true"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true" >
</service>
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE" />
<!-- Used to show over lock screen -->
<activity android:name=".neko.NekoLockedActivity"
<activity
android:name=".neko.NekoLockedActivity"
android:excludeFromRecents="true"
android:exported="true"
android:theme="@android:style/Theme.Material.Light.Dialog.NoActionBar"
android:showOnLockScreen="true" />
android:showOnLockScreen="true"
android:theme="@android:style/Theme.Material.Light.Dialog.NoActionBar" />
<!-- Used to enable easter egg -->
<activity android:name=".neko.NekoActivationActivity"
<activity
android:name=".ComponentActivationActivity"
android:excludeFromRecents="true"
android:exported="true"
android:theme="@android:style/Theme.NoDisplay"
>
android:theme="@android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.android.internal.category.PLATLOGO" />
</intent-filter>
@@ -81,37 +84,65 @@
<!-- The quick settings tile, disabled by default -->
<service
android:name=".neko.NekoTile"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
android:icon="@drawable/stat_icon"
android:enabled="false"
android:exported="true"
android:label="@string/default_tile_name">
android:icon="@drawable/stat_icon"
android:label="@string/default_tile_name"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
</service>
<service android:name=".neko.NekoControlsService"
android:permission="android.permission.BIND_CONTROLS"
android:label="@string/r_egg_name"
android:icon="@drawable/ic_fullcat_icon"
<service
android:name=".neko.NekoControlsService"
android:enabled="false"
android:exported="true">
android:exported="true"
android:icon="@drawable/ic_fullcat_icon"
android:label="@string/r_egg_name"
android:permission="android.permission.BIND_CONTROLS">
<intent-filter>
<action android:name="android.service.controls.ControlsProviderService" />
</intent-filter>
</service>
<!-- FileProvider for sending pictures -->
</service> <!-- FileProvider for sending pictures -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.android.egg.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
<!-- Android S easter egg bits -->
<!-- List of all system theme colors on the device. -->
<activity
android:name=".widget.PaintChipsActivity"
android:theme="@android:style/Theme.Material.Wallpaper.NoTitleBar"
android:configChanges="orientation|keyboardHidden|screenSize|uiMode"
android:label="@string/s_egg_name"
android:enabled="false"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<!-- Homescreen widget also showing paint chips (may be affected by the exact position in
the workspace) -->
<receiver
android:name=".widget.PaintChipsWidget"
android:label="@string/s_egg_name"
android:enabled="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/paint_chips_widget_info" />
</receiver>
</application>
</manifest>
</manifest>

View File

@@ -7,8 +7,8 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.android.tools.build:gradle:7.0.0-alpha08'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.30"
}
}
@@ -62,6 +62,9 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
buildFeatures {
viewBinding true
}
}
@@ -74,6 +77,7 @@ dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.6'
implementation "androidx.recyclerview:recyclerview:${ANDROID_X_VERSION}"
implementation "androidx.dynamicanimation:dynamicanimation:${ANDROID_X_VERSION}"
implementation 'com.google.android.material:material:1.3.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

View File

@@ -19,5 +19,5 @@ android.enableJetifier=true
kotlin.code.style=official
ANDROID_X_VERSION=1+
COMPILE_SDK=android-30
COMPILE_SDK=android-S
BUILD_TOOLS_VERSION=28.0.3

View File

@@ -0,0 +1,23 @@
<vector android:height="108dp" android:viewportHeight="48"
android:viewportWidth="48" android:width="108dp" xmlns:android="http://schemas.android.com/apk/res/android">
<group>
<clip-path android:pathData="M17,14h14v20h-14z"/>
<path android:fillColor="#00000000"
android:pathData="M18,21C18,21.7956 18.3161,22.5587 18.8787,23.1213C19.4413,23.6839 20.2044,24 21,24H27C27.7956,24 28.5587,24.3161 29.1213,24.8787C29.6839,25.4413 30,26.2044 30,27"
android:strokeColor="#ffffff" android:strokeWidth="2"/>
<path android:fillColor="#ffffff" android:pathData="M22,21C22.5523,21 23,20.5523 23,20C23,19.4477 22.5523,19 22,19C21.4477,19 21,19.4477 21,20C21,20.5523 21.4477,21 22,21Z"/>
<path android:fillColor="#ffffff" android:pathData="M26,21C26.5523,21 27,20.5523 27,20C27,19.4477 26.5523,19 26,19C25.4477,19 25,19.4477 25,20C25,20.5523 25.4477,21 26,21Z"/>
<path android:fillColor="#00000000"
android:pathData="M19.5,16.5L18,15"
android:strokeColor="#ffffff" android:strokeLineCap="round" android:strokeWidth="2"/>
<path android:fillColor="#00000000"
android:pathData="M28.5,16.5L30,15"
android:strokeColor="#ffffff" android:strokeLineCap="round" android:strokeWidth="2"/>
<path android:fillColor="#00000000"
android:pathData="M29.92,20C29.8637,19.6605 29.7801,19.3261 29.67,19C29.205,17.6561 28.2777,16.5211 27.0536,15.7973C25.8294,15.0735 24.388,14.8081 22.9864,15.0483C21.5847,15.2885 20.314,16.0188 19.4007,17.1088C18.4874,18.1989 17.991,19.5779 18,21"
android:strokeColor="#ffffff" android:strokeLineCap="round" android:strokeWidth="2"/>
<path android:fillColor="#00000000"
android:pathData="M18.08,28C18.1363,28.3395 18.2199,28.6739 18.33,29C18.795,30.3439 19.7223,31.4789 20.9464,32.2027C22.1705,32.9265 23.612,33.1919 25.0136,32.9517C26.4153,32.7115 27.686,31.9812 28.5993,30.8912C29.5126,29.8011 30.009,28.4221 30,27"
android:strokeColor="#ffffff" android:strokeLineCap="round" android:strokeWidth="2"/>
</group>
</vector>

View File

@@ -15,5 +15,5 @@ Copyright (C) 2018 The Android Open Source Project
-->
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/icon_bg"/>
<foreground android:drawable="@drawable/android_11_dial"/>
<foreground android:drawable="@drawable/android_s"/>
</adaptive-icon>

View File

@@ -14,5 +14,5 @@ Copyright (C) 2018 The Android Open Source Project
limitations under the License.
-->
<color xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#073042" />
android:color="@android:color/system_accent2_500" />

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FF000000" />
<corners
android:radius="12dp" />
</shape>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2021 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
http://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.
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/chip"
android:layout_width="10dp" android:layout_height="10dp"
android:layout_gravity="fill" android:layout_columnWeight="1" android:layout_rowWeight="1"
android:text="A1-500"
android:backgroundTint="@android:color/system_accent1_500"
android:background="@drawable/roundrect"
android:gravity="center"
android:textColor="?android:attr/textColorPrimary"
android:fontFamily="?android:attr/textAppearanceLarge"
android:layout_margin="2dp"
android:singleLine="true"
/>

View File

@@ -0,0 +1,25 @@
<!--
Copyright (C) 2021 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
http://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.
-->
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/paint_grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="0dp"
android:orientation="vertical"
android:alignmentMode="alignBounds"
android:rowOrderPreserved="false"
>
</GridLayout>

View File

@@ -0,0 +1,79 @@
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="300dp"
android:layout_height="50dp"
android:alignmentMode="alignBounds"
android:columnCount="5"
android:padding="0dp"
android:rowCount="1"
android:rowOrderPreserved="false">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_gravity="fill"
android:layout_margin="2dp"
android:background="@drawable/roundrect"
android:backgroundTint="@android:color/system_neutral1_500"
android:fontFamily="?android:attr/textAppearanceLarge"
android:gravity="center"
android:text="N1-500"
android:textColor="?android:attr/textColorPrimary" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_gravity="fill"
android:layout_margin="2dp"
android:background="@drawable/roundrect"
android:backgroundTint="@android:color/system_neutral2_500"
android:fontFamily="?android:attr/textAppearanceLarge"
android:gravity="center"
android:text="N2-500"
android:textColor="?android:attr/textColorPrimary" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_gravity="fill"
android:layout_margin="2dp"
android:background="@drawable/roundrect"
android:backgroundTint="@android:color/system_accent1_500"
android:fontFamily="?android:attr/textAppearanceLarge"
android:gravity="center"
android:text="A1-500"
android:textColor="?android:attr/textColorPrimary" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_gravity="fill"
android:layout_margin="2dp"
android:background="@drawable/roundrect"
android:backgroundTint="@android:color/system_accent2_500"
android:fontFamily="?android:attr/textAppearanceLarge"
android:gravity="center"
android:text="A2-500"
android:textColor="?android:attr/textColorPrimary" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_gravity="fill"
android:layout_margin="2dp"
android:background="@drawable/roundrect"
android:backgroundTint="@android:color/system_accent3_500"
android:fontFamily="?android:attr/textAppearanceLarge"
android:gravity="center"
android:text="A3-500"
android:textColor="?android:attr/textColorPrimary" />
</GridLayout>

View File

@@ -0,0 +1,7 @@
<resources>
<style name="ThemeOverlay.EasterEgg.AppWidgetContainer" parent="">
<item name="appWidgetBackgroundColor">@color/light_blue_900</item>
<item name="appWidgetTextColor">@color/light_blue_200</item>
</style>
</resources>

View File

@@ -0,0 +1,6 @@
<resources>
<declare-styleable name="AppWidgetAttrs">
<attr name="appWidgetBackgroundColor" format="color" />
<attr name="appWidgetTextColor" format="color" />
</declare-styleable>
</resources>

View File

@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
<?xml version="1.0" encoding="utf-8"?><!--
Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,4 +17,8 @@
<color name="toolbar_bg_color">#FFDDDDDD</color>
<color name="paper_color">#FFFFFFFF</color>
<color name="paint_color">#FF000000</color>
<color name="light_blue_50">#FFE1F5FE</color>
<color name="light_blue_200">#FF81D4FA</color>
<color name="light_blue_600">#FF039BE5</color>
<color name="light_blue_900">#FF01579B</color>
</resources>

View File

@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
<?xml version="1.0" encoding="utf-8"?><!--
Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,4 +15,10 @@ Copyright (C) 2016 The Android Open Source Project
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<dimen name="neko_display_size">64dp</dimen>
<!--
Refer to App Widget Documentation for margin information
http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout
-->
<dimen name="widget_margin">0dp</dimen>
</resources>

View File

@@ -14,7 +14,7 @@ Copyright (C) 2018 The Android Open Source Project
limitations under the License.
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<string name="app_name" translatable="false">Android R Easter Egg</string>
<string name="app_name" translatable="false">Android S Easter Egg</string>
<!-- name of the Q easter egg, a nonogram-style icon puzzle -->
<string name="q_egg_name" translatable="false">Icon Quiz</string>
@@ -23,4 +23,8 @@ Copyright (C) 2018 The Android Open Source Project
<string name="p_egg_name" translatable="false">PAINT.APK</string>
<string name="r_egg_name" translatable="false">Cat Controls</string>
<!-- name of the S easter egg, a widget that displays the system color palette
in a manner similar to a set of paint samples from a hardware store -->
<string name="s_egg_name" translatable="false">Paint Chips</string>
</resources>

View File

@@ -0,0 +1,7 @@
<resources>
<style name="ThemeOverlay.EasterEgg.AppWidgetContainer" parent="">
<item name="appWidgetBackgroundColor">@color/light_blue_600</item>
<item name="appWidgetTextColor">@color/light_blue_50</item>
</style>
</resources>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2021 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
http://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.
-->
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/paint_chip"
android:previewLayout="@layout/paint_chips_widget_preview"
android:minWidth="50dp"
android:minHeight="50dp"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="86400000"
android:widgetCategory="home_screen"></appwidget-provider>

View File

@@ -0,0 +1,83 @@
/*
* Copyright (C) 2021 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
*
* http://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.android.egg;
import android.app.Activity;
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;
import com.android.egg.neko.NekoControlsService;
import com.android.egg.widget.PaintChipsActivity;
import com.android.egg.widget.PaintChipsWidget;
/**
* Launched from the PlatLogoActivity. Enables everything else in this easter egg.
*/
public class ComponentActivationActivity extends Activity {
private static final String TAG = "EasterEgg";
private static final String S_EGG_UNLOCK_SETTING = "egg_mode_s";
private void toastUp(String s) {
Toast toast = Toast.makeText(this, s, Toast.LENGTH_SHORT);
toast.show();
}
@Override
public void onStart() {
super.onStart();
final PackageManager pm = getPackageManager();
final ComponentName[] cns = new ComponentName[] {
new ComponentName(this, NekoControlsService.class),
new ComponentName(this, PaintChipsActivity.class),
new ComponentName(this, PaintChipsWidget.class)
};
final long unlockValue = Settings.System.getLong(getContentResolver(),
S_EGG_UNLOCK_SETTING, 0);
for (ComponentName cn : cns) {
final boolean componentEnabled = pm.getComponentEnabledSetting(cn)
== PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
if (unlockValue == 0) {
if (componentEnabled) {
Log.v(TAG, "Disabling component: " + cn);
pm.setComponentEnabledSetting(cn,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
//toastUp("\uD83D\uDEAB");
} else {
Log.v(TAG, "Already disabled: " + cn);
}
} else {
if (!componentEnabled) {
Log.v(TAG, "Enabling component: " + cn);
pm.setComponentEnabledSetting(cn,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
//toastUp("\uD83D\uDC31");
} else {
Log.v(TAG, "Already enabled: " + cn);
}
}
}
finish();
}
}

View File

@@ -1,66 +0,0 @@
/*
* Copyright (C) 2016 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
*
* http://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.android.egg.neko;
import android.app.Activity;
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;
import com.android.internal.logging.MetricsLogger;
public class NekoActivationActivity extends Activity {
private static final String R_EGG_UNLOCK_SETTING = "egg_mode_r";
private void toastUp(String s) {
Toast toast = Toast.makeText(this, s, Toast.LENGTH_SHORT);
toast.show();
}
@Override
public void onStart() {
super.onStart();
final PackageManager pm = getPackageManager();
final ComponentName cn = new ComponentName(this, NekoControlsService.class);
final boolean componentEnabled = pm.getComponentEnabledSetting(cn)
== PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
if (Settings.System.getLong(getContentResolver(),
R_EGG_UNLOCK_SETTING, 0) == 0) {
if (componentEnabled) {
Log.v("Neko", "Disabling controls.");
pm.setComponentEnabledSetting(cn, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
MetricsLogger.histogram(this, "egg_neko_enable", 0);
toastUp("\uD83D\uDEAB");
} else {
Log.v("Neko", "Controls already disabled.");
}
} else {
if (!componentEnabled) {
Log.v("Neko", "Enabling controls.");
pm.setComponentEnabledSetting(cn, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
MetricsLogger.histogram(this, "egg_neko_enable", 1);
toastUp("\uD83D\uDC31");
} else {
Log.v("Neko", "Controls already enabled.");
}
}
finish();
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2021 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
*
* http://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.android.egg.widget
import android.app.Activity
import android.content.res.Configuration
import android.os.Bundle
import android.widget.FrameLayout
/**
* Activity to show off the current dynamic system theme in all its glory.
*/
class PaintChipsActivity : Activity() {
private lateinit var layout: FrameLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
window.navigationBarColor = 0
window.statusBarColor = 0
actionBar?.hide()
layout = FrameLayout(this)
layout.setPadding(dp2px(8f), dp2px(8f), dp2px(8f), dp2px(8f))
rebuildGrid()
setContentView(layout)
}
fun dp2px(dp: Float): Int {
return (dp * resources.displayMetrics.density).toInt()
}
override fun onResume() {
super.onResume()
rebuildGrid()
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
rebuildGrid()
}
private fun rebuildGrid() {
layout.removeAllViews()
val grid = buildFullWidget(this, ClickBehavior.SHARE)
val asView = grid.apply(this, layout)
layout.addView(asView, FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT))
}
}

View File

@@ -0,0 +1,293 @@
/*
* Copyright (C) 2021 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
*
* http://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.android.egg.widget
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.util.SizeF
import android.widget.RemoteViews
import com.android.egg.R
/**
* A homescreen widget to explore the current dynamic system theme.
*/
class PaintChipsWidget : AppWidgetProvider() {
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray
) {
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
override fun onAppWidgetOptionsChanged(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetId: Int,
newOptions: Bundle?
) {
// Log.v(TAG, "onAppWidgetOptionsChanged: id=${appWidgetId}")
updateAppWidget(context, appWidgetManager, appWidgetId)
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions)
}
}
const val TAG = "PaintChips"
val SHADE_NUMBERS = intArrayOf(0, 10, 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000)
val COLORS_NEUTRAL1 = intArrayOf(
android.R.color.system_neutral1_0,
android.R.color.system_neutral1_10,
android.R.color.system_neutral1_50,
android.R.color.system_neutral1_100,
android.R.color.system_neutral1_200,
android.R.color.system_neutral1_300,
android.R.color.system_neutral1_400,
android.R.color.system_neutral1_500,
android.R.color.system_neutral1_600,
android.R.color.system_neutral1_700,
android.R.color.system_neutral1_800,
android.R.color.system_neutral1_900,
android.R.color.system_neutral1_1000
)
val COLORS_NEUTRAL2 = intArrayOf(
android.R.color.system_neutral2_0,
android.R.color.system_neutral2_10,
android.R.color.system_neutral2_50,
android.R.color.system_neutral2_100,
android.R.color.system_neutral2_200,
android.R.color.system_neutral2_300,
android.R.color.system_neutral2_400,
android.R.color.system_neutral2_500,
android.R.color.system_neutral2_600,
android.R.color.system_neutral2_700,
android.R.color.system_neutral2_800,
android.R.color.system_neutral2_900,
android.R.color.system_neutral2_1000
)
var COLORS_ACCENT1 = intArrayOf(
android.R.color.system_accent1_0,
android.R.color.system_accent1_10,
android.R.color.system_accent1_50,
android.R.color.system_accent1_100,
android.R.color.system_accent1_200,
android.R.color.system_accent1_300,
android.R.color.system_accent1_400,
android.R.color.system_accent1_500,
android.R.color.system_accent1_600,
android.R.color.system_accent1_700,
android.R.color.system_accent1_800,
android.R.color.system_accent1_900,
android.R.color.system_accent1_1000
)
var COLORS_ACCENT2 = intArrayOf(
android.R.color.system_accent2_0,
android.R.color.system_accent2_10,
android.R.color.system_accent2_50,
android.R.color.system_accent2_100,
android.R.color.system_accent2_200,
android.R.color.system_accent2_300,
android.R.color.system_accent2_400,
android.R.color.system_accent2_500,
android.R.color.system_accent2_600,
android.R.color.system_accent2_700,
android.R.color.system_accent2_800,
android.R.color.system_accent2_900,
android.R.color.system_accent2_1000
)
var COLORS_ACCENT3 = intArrayOf(
android.R.color.system_accent3_0,
android.R.color.system_accent3_10,
android.R.color.system_accent3_50,
android.R.color.system_accent3_100,
android.R.color.system_accent3_200,
android.R.color.system_accent3_300,
android.R.color.system_accent3_400,
android.R.color.system_accent3_500,
android.R.color.system_accent3_600,
android.R.color.system_accent3_700,
android.R.color.system_accent3_800,
android.R.color.system_accent3_900,
android.R.color.system_accent3_1000
)
var COLOR_NAMES = arrayOf(
"N1", "N2", "A1", "A2", "A3"
)
var COLORS = arrayOf(
COLORS_NEUTRAL1,
COLORS_NEUTRAL2,
COLORS_ACCENT1,
COLORS_ACCENT2,
COLORS_ACCENT3
)
internal fun updateAppWidget(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetId: Int
) {
// val opts = appWidgetManager.getAppWidgetOptions(appWidgetId)
// Log.v(TAG, "requested sizes=${opts[OPTION_APPWIDGET_SIZES]}")
val allSizes = mapOf(
SizeF(50f, 50f)
to buildWidget(context, 1, 1, ClickBehavior.LAUNCH),
SizeF(100f, 50f)
to buildWidget(context, 1, 2, ClickBehavior.LAUNCH),
SizeF(150f, 50f)
to buildWidget(context, 1, 3, ClickBehavior.LAUNCH),
SizeF(200f, 50f)
to buildWidget(context, 1, 4, ClickBehavior.LAUNCH),
SizeF(250f, 50f)
to buildWidget(context, 1, 5, ClickBehavior.LAUNCH),
SizeF(50f, 120f)
to buildWidget(context, 3, 1, ClickBehavior.LAUNCH),
SizeF(100f, 120f)
to buildWidget(context, 3, 2, ClickBehavior.LAUNCH),
SizeF(150f, 120f)
to buildWidget(context, 3, 3, ClickBehavior.LAUNCH),
SizeF(200f, 120f)
to buildWidget(context, 3, 4, ClickBehavior.LAUNCH),
SizeF(250f, 120f)
to buildWidget(context, 3, 5, ClickBehavior.LAUNCH),
SizeF(50f, 250f)
to buildWidget(context, 5, 1, ClickBehavior.LAUNCH),
SizeF(100f, 250f)
to buildWidget(context, 5, 2, ClickBehavior.LAUNCH),
SizeF(150f, 250f)
to buildWidget(context, 5, 3, ClickBehavior.LAUNCH),
SizeF(200f, 250f)
to buildWidget(context, 5, 4, ClickBehavior.LAUNCH),
SizeF(250f, 250f)
to buildWidget(context, 5, 5, ClickBehavior.LAUNCH),
SizeF(300f, 300f)
to buildWidget(context, SHADE_NUMBERS.size, COLORS.size, ClickBehavior.LAUNCH)
)
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, RemoteViews(allSizes))
}
fun buildFullWidget(context: Context, clickable: ClickBehavior): RemoteViews {
return buildWidget(context, SHADE_NUMBERS.size, COLORS.size, clickable)
}
fun buildWidget(context: Context, numShades: Int, numColors: Int, clickable: ClickBehavior):
RemoteViews {
val grid = RemoteViews(context.packageName, R.layout.paint_chips_grid)
// shouldn't be necessary but sometimes the RV instructions get played twice in launcher.
grid.removeAllViews(R.id.paint_grid)
grid.setInt(R.id.paint_grid, "setRowCount", numShades)
grid.setInt(R.id.paint_grid, "setColumnCount", numColors)
Log.v(TAG, "building widget: shade rows=$numShades, color columns=$numColors")
COLORS.forEachIndexed colorLoop@{ i, colorlist ->
when (colorlist) {
COLORS_NEUTRAL1 -> if (numColors < 2) return@colorLoop
COLORS_NEUTRAL2 -> if (numColors < 4) return@colorLoop
COLORS_ACCENT2 -> if (numColors < 3) return@colorLoop
COLORS_ACCENT3 -> if (numColors < 5) return@colorLoop
else -> {} // always do ACCENT1
}
colorlist.forEachIndexed shadeLoop@{ j, resId ->
when (SHADE_NUMBERS[j]) {
500 -> {}
300, 700 -> if (numShades < 3) return@shadeLoop
100, 900 -> if (numShades < 5) return@shadeLoop
else -> if (numShades < SHADE_NUMBERS.size) return@shadeLoop
}
val cell = RemoteViews(context.packageName, R.layout.paint_chip)
cell.setTextViewText(R.id.chip, "${COLOR_NAMES[i]}-${SHADE_NUMBERS[j]}")
val textColor = if (SHADE_NUMBERS[j] > 500)
colorlist[0]
else colorlist[colorlist.size - 1]
cell.setTextColor(R.id.chip, context.getColor(textColor))
cell.setColorStateList(R.id.chip, "setBackgroundTintList", resId)
val text = """
${COLOR_NAMES[i]}-${SHADE_NUMBERS[j]} (@${
context.resources.getResourceName(resId) })
currently: #${ String.format("%06x", context.getColor(resId) and 0xFFFFFF) }
""".trimIndent()
when (clickable) {
ClickBehavior.SHARE -> cell.setOnClickPendingIntent(
R.id.chip,
makeTextSharePendingIntent(context, text)
)
ClickBehavior.LAUNCH -> cell.setOnClickPendingIntent(
R.id.chip,
makeActivityLaunchPendingIntent(context)
)
ClickBehavior.NONE -> { }
}
grid.addView(R.id.paint_grid, cell)
}
}
return grid
}
enum class ClickBehavior {
NONE,
SHARE,
LAUNCH
}
fun makeTextSharePendingIntent(context: Context, text: String): PendingIntent {
val shareIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, text)
type = "text/plain"
}
val chooserIntent = Intent.createChooser(shareIntent, null).apply {
identifier = text // incredible quality-of-life improvement, thanks framework team
}
return PendingIntent.getActivity(context, 0, chooserIntent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
}
fun makeActivityLaunchPendingIntent(context: Context): PendingIntent {
return PendingIntent.getActivity(context, 0,
Intent().apply {
component = ComponentName(context, PaintChipsActivity::class.java)
action = Intent.ACTION_MAIN
},
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
}

View File

@@ -0,0 +1,37 @@
<!--
Copyright (C) 2021 The Android Open Source Project
Licensed under the Apache License, Version 2 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48">
<group>
<clip-path
android:pathData="M14,14h21v20h-21z"/>
<path
android:pathData="M15,15C15.7956,15 16.5587,15.3161 17.1213,15.8787C17.6839,16.4413 18,17.2044 18,18V33"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#ffffff"
android:strokeLineCap="round"/>
<path
android:pathData="M34,33H22V30C22,28.4087 22.6321,26.8826 23.7574,25.7574C24.8826,24.6321 26.4087,24 28,24H31C31.7956,24 32.5587,23.6839 33.1213,23.1213C33.6839,22.5587 34,21.7957 34,21C34.009,19.5779 33.5126,18.1989 32.5993,17.1088C31.686,16.0188 30.4153,15.2885 29.0136,15.0483C27.612,14.8081 26.1706,15.0735 24.9464,15.7973C23.7223,16.5211 22.795,17.6561 22.33,19C22.2199,19.3261 22.1363,19.6605 22.08,20"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#ffffff"
android:strokeLineCap="round"/>
</group>
</vector>

View File

@@ -15,5 +15,5 @@ Copyright (C) 2018 The Android Open Source Project
-->
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/icon_bg"/>
<foreground android:drawable="@drawable/android_11_dial"/>
<foreground android:drawable="@drawable/android_12"/>
</adaptive-icon>

View File

@@ -14,5 +14,5 @@ Copyright (C) 2018 The Android Open Source Project
limitations under the License.
-->
<color xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#073042" />
android:color="@android:color/system_accent1_500" />