android壁纸软件代码,Flutter开源项目——Android免费壁纸应用

简介

free_wallpaper是一款基于flutter的免费Android壁纸应用

项目明细

开发环境:

android studio 3.5

Flutter 1.12.13+hotfix.7 • channel stable

Framework • revision 9f5ff2306b

Engine • revision a67792536c

Tools • Dart 2.7.0

主要功能

1.分端浏览

2.筛选功能

3.搜索功能

4.搜索历史记录

5.下载壁纸和设置壁纸

6.下载管理

(更多功能还在陆续填坑中...)

项目特点

本项目采用Serverless模式,使用dio网络请求库和jsoup获取数据。使用百度图片接口实现搜索功能;使用CachedNetworkImage加载网络图片;使用Android插件的形式实现了部分Android原生功能,如设置壁纸和更新MediaStore等。

部分代码

1.WallpaperPlugin(修改自wallpaper插件,解决了dio库版本不兼容的问题,添加了设置本地图片的功能)

import android.Manifest

import android.annotation.TargetApi

import android.app.Activity

import android.app.WallpaperManager

import android.content.ActivityNotFoundException

import android.content.ContentValues

import android.content.Context

import android.content.Intent

import android.content.pm.PackageManager

import android.graphics.BitmapFactory

import android.net.Uri

import android.os.Build

import android.provider.MediaStore

import io.flutter.Log

import io.flutter.embedding.android.FlutterActivity

import io.flutter.embedding.engine.plugins.FlutterPlugin

import io.flutter.plugin.common.MethodCall

import io.flutter.plugin.common.MethodChannel

import io.flutter.plugin.common.MethodChannel.MethodCallHandler

import java.io.File

import java.io.IOException

/** WallpaperPlugin */

class WallpaperPlugin constructor(var mContext: Context): FlutterActivity(), FlutterPlugin, MethodCallHandler {

private var id = 0

private var res = ""

private var channel: MethodChannel?=null

@TargetApi(Build.VERSION_CODES.FROYO)

private fun setWallpaper(i: Int, imagePath: String): String {

id = i

val wallpaperManager = WallpaperManager.getInstance(mContext)

val file = File(imagePath)

// set bitmap to wallpaper

val bitmap = BitmapFactory.decodeFile(file.absolutePath)

if (id == 1) {

try {

res = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

wallpaperManager.setBitmap(bitmap, null, true, WallpaperManager.FLAG_SYSTEM)

"Home Screen Set Successfully"

} else {

"To Set Home Screen Requires Api Level 24"

}

} catch (ex: IOException) {

ex.printStackTrace()

}

} else if (id == 2) try {

res = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

wallpaperManager.setBitmap(bitmap, null, true, WallpaperManager.FLAG_LOCK)

"Lock Screen Set Successfully"

} else {

"To Set Lock Screen Requires Api Level 24"

}

} catch (e: IOException) {

res = e.toString()

e.printStackTrace()

} else if (id == 3) {

try {

wallpaperManager.setBitmap(bitmap)

res = "Home And Lock Screen Set Successfully"

} catch (e: IOException) {

res = e.toString()

e.printStackTrace()

}

} else if (id == 4) {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

if (activity.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)

!= PackageManager.PERMISSION_GRANTED &&

activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)

!= PackageManager.PERMISSION_GRANTED) {

activity.requestPermissions(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE,

Manifest.permission.WRITE_EXTERNAL_STORAGE), 1)

} else {

Uri.fromFile(file)

val contentURI = getImageContentUri(this, file)

val intent = Intent(wallpaperManager.getCropAndSetWallpaperIntent(contentURI))

val mime = "image/*"

intent.setDataAndType(contentURI, mime)

try {

startActivityForResult(intent, 2)

} catch (e: ActivityNotFoundException) { //handle error

res = "Error To Set Wallpaer"

}

}

}

}

return res

}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {

Log.d("Tag", "resultcode=" + resultCode + "requestcode=" + requestCode)

res = when (resultCode) {

Activity.RESULT_OK -> {

"System Screen Set Successfully"

}

Activity.RESULT_CANCELED -> {

"setting Wallpaper Cancelled"

}

else -> {

"Something Went Wrong"

}

}

super.onActivityResult(requestCode, resultCode, data)

}

override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {

when (call.method) {

"getPlatformVersion" -> result.success("" + Build.VERSION.RELEASE)

"HomeScreen" -> result.success(setWallpaper(1, call.arguments as String))

"LockScreen" -> result.success(setWallpaper(2, call.arguments as String))

"Both" -> result.success(setWallpaper(3, call.arguments as String))

"SystemWallpaer" -> result.success(setWallpaper(4, call.arguments as String))

else -> result.notImplemented()

}

}

override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {

channel = MethodChannel(binding.binaryMessenger, "WallpaperPlugin")

channel!!.setMethodCallHandler(WallpaperPlugin(mContext))

}

override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {

channel!!.setMethodCallHandler(null)

channel=null

}

companion object {

fun getImageContentUri(context: Context, imageFile: File): Uri? {

val filePath = imageFile.absolutePath

Log.d("Tag", filePath)

val cursor = context.contentResolver.query(

MediaStore.Images.Media.EXTERNAL_CONTENT_URI, arrayOf(MediaStore.Images.Media._ID),

MediaStore.Images.Media.DATA + "=? ", arrayOf(filePath), null)

return if (cursor != null && cursor.moveToFirst()) {

val id = cursor.getInt(cursor

.getColumnIndex(MediaStore.MediaColumns._ID))

val baseUri = Uri.parse("content://media/external/images/media")

Uri.withAppendedPath(baseUri, "" + id)

} else {

if (imageFile.exists()) {

val values = ContentValues()

values.put(MediaStore.Images.Media.DATA, filePath)

context.contentResolver.insert(

MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)

} else {

null

}

}

}

}

}

2.MediaStorePlugin(更新本机媒体库)

import android.content.Context

import android.content.Intent

import android.graphics.BitmapFactory

import android.net.Uri

import android.provider.MediaStore

import io.flutter.embedding.engine.plugins.FlutterPlugin

import io.flutter.plugin.common.MethodCall

import io.flutter.plugin.common.MethodChannel

import java.io.File

/**

* description:

* author:luoxingyuan

*/

class MediaStorePlugin constructor(var mContext: Context) : FlutterPlugin, MethodChannel.MethodCallHandler {

private var channel: MethodChannel?=null

override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {

channel = MethodChannel(binding.binaryMessenger, "MediaStorePlugin")

channel!!.setMethodCallHandler(MediaStorePlugin(mContext))

}

override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {

channel!!.setMethodCallHandler(null)

channel=null

}

override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {

when (call.method) {

"refreshMediaStore" -> result.success(sendMediaBroadcast(call.arguments as String))

else -> result.notImplemented()

}

}

private fun sendMediaBroadcast(filePath: String) {

val file = File(filePath)

//通知相册更新

MediaStore.Images.Media.insertImage(mContext.contentResolver, BitmapFactory.decodeFile(file.absolutePath), file.name, null)

val intent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)

val uri: Uri = Uri.fromFile(file)

intent.data = uri

mContext.sendBroadcast(intent)

}

}

3.PC端壁纸分类列表

import 'package:cached_network_image/cached_network_image.dart';

import 'package:flutter/material.dart';

import 'package:free_wallpaper/model/category_model.dart';

import 'package:free_wallpaper/net/address.dart';

import 'package:free_wallpaper/net/http_callback.dart';

import 'package:free_wallpaper/net/http_manager.dart';

import 'package:free_wallpaper/net/result_data.dart';

import 'package:free_wallpaper/utils/toast.dart';

import 'package:free_wallpaper/widget/error_placeholder.dart';

import 'package:free_wallpaper/widget/loading_dialog.dart';

import 'package:html/parser.dart' show parse;

import 'page_albums.dart';

/*

description:

author:59432

create_time:2020/1/22 12:59

*/

class CategoriesPage extends StatefulWidget {

@override

State createState() => CategoriesPageState();

}

class CategoriesPageState extends State {

var categories = List();

@override

void initState() {

// TODO: implement initState

super.initState();

_requestData(showLoading: true);

}

@override

Widget build(BuildContext context) {

return Scaffold(

body: RefreshIndicator(

color: Colors.pinkAccent,

backgroundColor: Colors.white,

child: Container(

margin: const EdgeInsets.only(left: 8.0, right: 8, top: 8),

child: GridView.count(

// Create a grid with 2 columns. If you change the scrollDirection to

// horizontal, this produces 2 rows.

crossAxisCount: 3,

crossAxisSpacing: 8.0,

mainAxisSpacing: 8,

// Generate 100 widgets that display their index in the List.

children: List.generate(categories.length, (index) {

return _buildItem(context, categories[index]);

}),

),

), onRefresh: _refreshData),

);

}

_requestData({showLoading = false}) {

HttpManager.getInstance(baseUrl: Address.MEI_ZHUO)

.getHtml("/zt/index.html", HttpCallback(

onStart: () {

if (showLoading) {

LoadingDialog.showProgress(context);

}

},

onSuccess: (ResultData data) {

if (showLoading) {

LoadingDialog.dismiss(context);

}

var doc = parse(data.data);

var aTags = doc.body

.getElementsByClassName("nr_zt w1180")

.first

.getElementsByTagName("a");

categories.clear();

aTags.forEach((a) {

var href = a.attributes["href"];

var src = a

.querySelector("img")

.attributes["src"];

var category = a

.querySelector("p")

.text;

categories.add(CategoryModel(name: category, href: href, src: src));

});

setState(() {

});

},

onError: (ResultData error) {

if (showLoading) {

LoadingDialog.dismiss(context);

}

ToastUtil.showToast(error.data);

}

));

}

Widget _buildItem(BuildContext context, CategoryModel category) {

return GestureDetector(

onTap: () => _onItemClick(category),

child: ClipOval(

child: Stack(

alignment: const Alignment(0.0, 1.0),

children: [

CachedNetworkImage(

imageUrl: category.src,

placeholder: (context, url) => Center(child: CircularProgressIndicator()),

errorWidget: (context, url, error) => ErrorPlaceHolder(),

fit: BoxFit.fill,

height: (MediaQuery

.of(context)

.size

.width) / 3,

),

Container( //分析 4

width: (MediaQuery

.of(context)

.size

.width) / 3,

decoration: BoxDecoration(

color: Colors.black45,

),

child: Text(

category.name,

textAlign: TextAlign.center,

style: TextStyle(

fontSize: 16.0,

color: Colors.white,

),

),

),

],

),

),

);

}

_onItemClick(CategoryModel category) {

Navigator.push(

context,

MaterialPageRoute(builder: (context) => AlbumsPage(category, false)),

);

}

Future _refreshData() async {

_requestData();

}

}

预览

e400d5caffc7

Screenshot_2020-02-11-18-09-59-827_wallpaper.cn.mewlxy.free_wallpaper.jpg

e400d5caffc7

Screenshot_2020-02-11-18-10-13-965_wallpaper.cn.mewlxy.free_wallpaper.jpg

e400d5caffc7

Screenshot_2020-02-11-18-11-12-049_wallpaper.cn.mewlxy.free_wallpaper.jpg

e400d5caffc7

Screenshot_2020-02-11-18-11-48-216_wallpaper.cn.mewlxy.free_wallpaper.jpg

项目地址

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值