适配android 6

This commit is contained in:
fengshengxiong 2024-05-27 11:09:01 +08:00
parent 59d4e1e73d
commit f271d47c86
17 changed files with 221 additions and 100 deletions

View File

@ -101,4 +101,7 @@ flutter {
source '../..' source '../..'
} }
dependencies {} dependencies {
implementation 'androidx.work:work-runtime-ktx:2.9.0'
implementation 'com.github.bumptech.glide:glide:4.16.0'
}

View File

@ -0,0 +1,95 @@
package com.hello.wallpaper
import android.app.Activity
import android.app.WallpaperManager
import android.content.Context
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.os.Build
import android.util.Size
import androidx.window.layout.WindowMetricsCalculator
import androidx.work.*
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import java.io.File
import java.io.IOException
class GlideWallpaperWorker(
context: Context,
params: WorkerParameters
) : Worker(context, params) {
override fun doWork(): Result {
val imagePath = inputData.getString("imagePath") ?: return Result.failure()
val wallpaperType = inputData.getInt("wallpaperType", 0)
val desiredWidth = inputData.getInt("desiredWidth", 0)
val desiredHeight = inputData.getInt("desiredHeight", 0)
return try {
Glide.with(applicationContext)
.asBitmap()
.load(File(imagePath))
.apply(RequestOptions().override(desiredWidth, desiredHeight))
.into(object : CustomTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
val wallpaperManager = WallpaperManager.getInstance(applicationContext)
try {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
wallpaperManager.setBitmap(resource)
} else {
when (wallpaperType) {
0 -> wallpaperManager.setBitmap(resource, null, true, WallpaperManager.FLAG_SYSTEM)
1 -> wallpaperManager.setBitmap(resource, null, true, WallpaperManager.FLAG_LOCK)
2 -> {
wallpaperManager.setBitmap(resource, null, true, WallpaperManager.FLAG_SYSTEM)
wallpaperManager.setBitmap(resource, null, true, WallpaperManager.FLAG_LOCK)
}
}
}
} catch (e: IOException) {
e.printStackTrace()
}
}
override fun onLoadCleared(placeholder: Drawable?) {
// Handle cleanup if needed
}
})
Result.success()
} catch (e: Exception) {
e.printStackTrace()
Result.retry()
}
}
}
// Trigger the WorkManager task
fun setWallpaperWithGlide(context: Context, activity: Activity, imagePath: String, wallpaperType: Int) {
val screenSize: Size = getScreenDimensions(activity)
val desiredWidth = screenSize.width * 2 // 适应横向滚动
val desiredHeight = screenSize.height
val inputData = Data.Builder()
.putString("imagePath", imagePath)
.putInt("wallpaperType", wallpaperType)
.putInt("desiredWidth", desiredWidth)
.putInt("desiredHeight", desiredHeight)
.build()
val setWallpaperRequest = OneTimeWorkRequest.Builder(GlideWallpaperWorker::class.java)
.setInputData(inputData)
.build()
WorkManager.getInstance(context).enqueue(setWallpaperRequest)
}
// Modern method to get screen dimensions
private fun getScreenDimensions(activity: Activity): Size {
val windowMetrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(activity)
val bounds = windowMetrics.bounds
val width = bounds.width()
val height = bounds.height()
return Size(width, height)
}

View File

@ -1,22 +1,27 @@
package com.hello.wallpaper package com.hello.wallpaper
import android.app.Activity
import android.app.WallpaperManager import android.app.WallpaperManager
import android.content.Context import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.os.Build import android.os.Build
import androidx.annotation.RequiresApi import android.util.Size
import androidx.window.layout.WindowMetricsCalculator
import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class SetWallpaperPlugin : FlutterPlugin, MethodChannel.MethodCallHandler { class SetWallpaperPlugin : FlutterPlugin, ActivityAware, MethodChannel.MethodCallHandler {
private lateinit var context: Context private lateinit var context: Context
private lateinit var channel: MethodChannel private lateinit var channel: MethodChannel
private lateinit var activity: Activity
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "set_wallpaper") channel = MethodChannel(flutterPluginBinding.binaryMessenger, "set_wallpaper")
@ -24,31 +29,13 @@ class SetWallpaperPlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
channel.setMethodCallHandler(this) channel.setMethodCallHandler(this)
} }
@RequiresApi(Build.VERSION_CODES.N)
@OptIn(DelicateCoroutinesApi::class)
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
if (call.method == "setWallpaper") { if (call.method == "setWallpaper") {
val path = call.argument<String>("path") val path = call.argument<String>("path")
val wallpaperType = call.argument<Int>("wallpaperType") // 0 for home screen, 1 for lock screen, 2 for both val wallpaperType = call.argument<Int>("wallpaperType") // 0 for home screen, 1 for lock screen, 2 for both
GlobalScope.launch(Dispatchers.IO) { if (path != null && wallpaperType != null) {
val bitmap = BitmapFactory.decodeFile(path) setWallpaper(path, wallpaperType, result)
withContext(Dispatchers.Main) {
try {
val wallpaperManager = WallpaperManager.getInstance(context)
when (wallpaperType) {
0 -> wallpaperManager.setBitmap(bitmap, null, true, WallpaperManager.FLAG_SYSTEM)
1 -> wallpaperManager.setBitmap(bitmap, null, true, WallpaperManager.FLAG_LOCK)
2 -> {
wallpaperManager.setBitmap(bitmap, null, true, WallpaperManager.FLAG_SYSTEM)
wallpaperManager.setBitmap(bitmap, null, true, WallpaperManager.FLAG_LOCK)
}
}
result.success("Wallpaper applied successfully")
} catch (e: Exception) {
result.error("ERROR", "Failed to set wallpaper: ${e.message}", null)
}
}
} }
} else { } else {
result.notImplemented() result.notImplemented()
@ -58,4 +45,59 @@ class SetWallpaperPlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null) channel.setMethodCallHandler(null)
} }
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
activity = binding.activity
}
override fun onDetachedFromActivityForConfigChanges() {
}
override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
activity = binding.activity
}
override fun onDetachedFromActivity() {
}
@OptIn(DelicateCoroutinesApi::class)
fun setWallpaper(path: String, wallpaperType: Int, result: MethodChannel.Result) {
val screenSize: Size = getScreenDimensions()
val desiredWidth = screenSize.width * 2 // 适应横向滚动
val desiredHeight = screenSize.height
GlobalScope.launch(Dispatchers.IO) {
val wallpaperManager = WallpaperManager.getInstance(context)
try {
val largeBitmap = BitmapFactory.decodeFile(path)
val scaledBitmap = Bitmap.createScaledBitmap(largeBitmap, desiredWidth, desiredHeight, true)
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
wallpaperManager.setBitmap(scaledBitmap)
} else {
when (wallpaperType) {
0 -> wallpaperManager.setBitmap(largeBitmap, null, true, WallpaperManager.FLAG_SYSTEM)
1 -> wallpaperManager.setBitmap(largeBitmap, null, true, WallpaperManager.FLAG_LOCK)
2 -> {
wallpaperManager.setBitmap(largeBitmap, null, true, WallpaperManager.FLAG_SYSTEM)
wallpaperManager.setBitmap(largeBitmap, null, true, WallpaperManager.FLAG_LOCK)
}
}
}
largeBitmap.recycle()
scaledBitmap.recycle()
result.success("Wallpaper applied successfully")
} catch (e: Exception) {
result.error("ERROR", "Failed to set wallpaper: ${e.message}", null)
}
}
}
// Modern method to get screen dimensions
private fun getScreenDimensions(): Size {
val windowMetrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(activity)
val bounds = windowMetrics.bounds
val width = bounds.width()
val height = bounds.height()
return Size(width, height)
}
} }

View File

@ -21,41 +21,44 @@ class TitleBarWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SizedBox( return Padding(
height: titleBarHeight, padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
child: Row( child: SizedBox(
children: [ height: titleBarHeight,
SizedBox(width: 20.w), child: Row(
Expanded( children: [
child: Text( SizedBox(width: 20.w),
title, Expanded(
style: TextStyle( child: Text(
color: Colors.white, title,
fontSize: 32.sp, style: TextStyle(
fontWeight: FontWeight.w600, color: Colors.white,
fontSize: 32.sp,
fontWeight: FontWeight.w600,
),
), ),
), ),
), if (showSettingsBtn!) ...[
if (showSettingsBtn!) ...[ ClipOval(
ClipOval( child: Material(
child: Material( color: Colors.transparent,
color: Colors.transparent, child: InkWell(
child: InkWell( onTap: settingsOnTap,
onTap: settingsOnTap, child: Padding(
child: Padding( padding: const EdgeInsets.all(10).w,
padding: const EdgeInsets.all(10).w, child: Image.asset(
child: Image.asset( Assets.imagesIcSettings,
Assets.imagesIcSettings, width: 20.w,
width: 20.w, height: 20.w,
height: 20.w, ),
), ),
), ),
), ),
), ),
), SizedBox(width: 10.w),
SizedBox(width: 10.w), ],
], ],
], ),
), ),
); );
} }

View File

@ -51,7 +51,6 @@ class CatalogController extends GetxController {
Get.toNamed(AppPages.wallpaperDet, arguments: { Get.toNamed(AppPages.wallpaperDet, arguments: {
'position': index, 'position': index,
'wallpaperList': wallpaperList, 'wallpaperList': wallpaperList,
'heroTag': 'Catalog-$clsName-$index',
}); });
} }
} }

View File

@ -107,15 +107,12 @@ class CatalogView extends GetView<CatalogController> {
Widget _buildWallpaperItem(String clsName, List<WallpaperData> wallpaperList, WallpaperData item, int index) { Widget _buildWallpaperItem(String clsName, List<WallpaperData> wallpaperList, WallpaperData item, int index) {
return GestureDetector( return GestureDetector(
onTap: () => controller.onTapItem(clsName, wallpaperList, index), onTap: () => controller.onTapItem(clsName, wallpaperList, index),
child: Hero( child: KeepAliveWrapper(
tag: 'Catalog-$clsName-$index', child: ImageNetworkWidget(
child: KeepAliveWrapper( url: item.previewThumb,
child: ImageNetworkWidget( width: 136.w,
url: item.previewThumb, height: double.infinity,
width: 136.w, radius: 8.r,
height: double.infinity,
radius: 8.r,
),
), ),
), ),
); );

View File

@ -19,7 +19,6 @@ class ClsDetController extends GetxController {
Get.toNamed(AppPages.wallpaperDet, arguments: { Get.toNamed(AppPages.wallpaperDet, arguments: {
'position': index, 'position': index,
'wallpaperList': wallpaperDataList, 'wallpaperList': wallpaperDataList,
'heroTag': 'ClsDet-$index',
}); });
} }
} }

View File

@ -35,12 +35,9 @@ class ClsDetView extends StatelessWidget {
Widget _buildDiscoverItem(WallpaperData item, int index) { Widget _buildDiscoverItem(WallpaperData item, int index) {
return GestureDetector( return GestureDetector(
onTap: () => controller.onTapItem(index), onTap: () => controller.onTapItem(index),
child: Hero( child: ImageNetworkWidget(
tag: 'ClsDet-$index', url: item.previewThumb,
child: ImageNetworkWidget( radius: 8.r,
url: item.previewThumb,
radius: 8.r,
),
), ),
); );
} }

View File

@ -80,7 +80,6 @@ class DiscoverController extends GetxController {
Get.toNamed(AppPages.wallpaperDet, arguments: { Get.toNamed(AppPages.wallpaperDet, arguments: {
'position': index, 'position': index,
'wallpaperList': wallpaperDataList, 'wallpaperList': wallpaperDataList,
'heroTag': 'Discover-$index',
}); });
} }
} }

View File

@ -18,7 +18,6 @@ class DiscoverView extends GetView<DiscoverController> {
builder: (controller) { builder: (controller) {
return Column( return Column(
children: [ children: [
SizedBox(height: 7.h),
if (controller.todayNewestList.isNotEmpty) ...[ if (controller.todayNewestList.isNotEmpty) ...[
_buildTodayNewest(), _buildTodayNewest(),
SizedBox(height: 7.h), SizedBox(height: 7.h),
@ -56,12 +55,9 @@ class DiscoverView extends GetView<DiscoverController> {
Widget _buildDiscoverItem(WallpaperData item, int index) { Widget _buildDiscoverItem(WallpaperData item, int index) {
return GestureDetector( return GestureDetector(
onTap: () => controller.onTapItem(index), onTap: () => controller.onTapItem(index),
child: Hero( child: ImageNetworkWidget(
tag: 'Discover-$index', url: item.previewThumb,
child: ImageNetworkWidget( radius: 8.r,
url: item.previewThumb,
radius: 8.r,
),
), ),
); );
} }

View File

@ -54,7 +54,6 @@ class FavoriteController extends GetxController {
Get.toNamed(AppPages.wallpaperDet, arguments: { Get.toNamed(AppPages.wallpaperDet, arguments: {
'position': index, 'position': index,
'wallpaperList': isFavorite ? favoriteList : todayHottestList, 'wallpaperList': isFavorite ? favoriteList : todayHottestList,
'heroTag': '${isFavorite ? 'Favorite' : 'TodayHottest'}-$index',
}); });
} }

View File

@ -55,12 +55,9 @@ class FavoriteView extends GetView<FavoriteController> {
return GestureDetector( return GestureDetector(
onTap: () => controller.onTapItem(index, true), onTap: () => controller.onTapItem(index, true),
onLongPress: () => controller.onLongPress(index), onLongPress: () => controller.onLongPress(index),
child: Hero( child: ImageNetworkWidget(
tag: 'Favorite-$index', url: item.previewThumb,
child: ImageNetworkWidget( radius: 8.r,
url: item.previewThumb,
radius: 8.r,
),
), ),
); );
} }
@ -87,13 +84,10 @@ class FavoriteView extends GetView<FavoriteController> {
padding: const EdgeInsets.symmetric(horizontal: 3.5).w, padding: const EdgeInsets.symmetric(horizontal: 3.5).w,
child: GestureDetector( child: GestureDetector(
onTap: () => controller.onTapItem(e.key, false), onTap: () => controller.onTapItem(e.key, false),
child: Hero( child: ImageNetworkWidget(
tag: 'TodayHottest-${e.key}', url: e.value.previewThumb,
child: ImageNetworkWidget( height: 183.h,
url: e.value.previewThumb, radius: 8.r,
height: 183.h,
radius: 8.r,
),
), ),
), ),
), ),

View File

@ -15,13 +15,13 @@ class HomeView extends StatelessWidget {
return Scaffold( return Scaffold(
body: Column( body: Column(
children: [ children: [
SizedBox(height: ScreenUtil().statusBarHeight),
Obx(() { Obx(() {
return TitleBarWidget( return TitleBarWidget(
controller.pages[controller.currentIndex.value].label, controller.pages[controller.currentIndex.value].label,
settingsOnTap: controller.onTapSettings, settingsOnTap: controller.onTapSettings,
); );
}), }),
SizedBox(height: 7.h),
Expanded( Expanded(
child: PageView( child: PageView(
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),

View File

@ -23,7 +23,6 @@ class WallpaperDetController extends GetxController {
late final List<GlobalKey> globalKey; late final List<GlobalKey> globalKey;
late final List<WallpaperData> wallpaperList; late final List<WallpaperData> wallpaperList;
late final PageController pageController; late final PageController pageController;
late final String heroTag;
var blurs = <bool>[].obs; var blurs = <bool>[].obs;
var position = 0; var position = 0;
var filePath = ''; var filePath = '';
@ -34,7 +33,6 @@ class WallpaperDetController extends GetxController {
Map<String, dynamic> arguments = Get.arguments ?? {}; Map<String, dynamic> arguments = Get.arguments ?? {};
position = arguments['position'] ?? 0; position = arguments['position'] ?? 0;
wallpaperList = arguments['wallpaperList'] ?? <WallpaperData>[]; wallpaperList = arguments['wallpaperList'] ?? <WallpaperData>[];
heroTag = arguments['heroTag'] ?? '';
globalKey = List.generate(wallpaperList.length, (index) => GlobalKey()); globalKey = List.generate(wallpaperList.length, (index) => GlobalKey());
blurs.value = List.generate(wallpaperList.length, (index) => false); blurs.value = List.generate(wallpaperList.length, (index) => false);
pageController = PageController(initialPage: position); pageController = PageController(initialPage: position);

View File

@ -87,7 +87,6 @@ class WallpaperDetView extends StatelessWidget {
maxScale: PhotoViewComputedScale.covered * 3, maxScale: PhotoViewComputedScale.covered * 3,
loadingBuilder: (context, event) => loadingView(), loadingBuilder: (context, event) => loadingView(),
errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) => errorView, errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) => errorView,
heroAttributes: PhotoViewHeroAttributes(tag: controller.heroTag),
), ),
); );
}), }),

View File

@ -4,6 +4,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
/// ///
double titleBarHeight = 45.h; double titleBarHeight = 45.h;
@ -13,9 +14,9 @@ double todayNewestHeight = 64.h;
/// discover列表高度 /// discover列表高度
double discoverListHeight = 1.sh - double discoverListHeight = 1.sh -
ScreenUtil().statusBarHeight - MediaQuery.of(Get.context!).padding.top -
titleBarHeight - titleBarHeight -
todayNewestHeight - todayNewestHeight -
7.h - 14.h -
kBottomNavigationBarHeight - kBottomNavigationBarHeight -
ScreenUtil().bottomBarHeight; MediaQuery.of(Get.context!).padding.bottom;

View File

@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts # In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix. # of the product and file versions while build-number is used as the build suffix.
version: 1.0.1+2 version: 1.0.2+3
environment: environment:
sdk: '>=3.3.4 <4.0.0' sdk: '>=3.3.4 <4.0.0'