Compare commits

..

26 Commits

Author SHA1 Message Date
ZhanGSKen
c7177f5fa5 <timestamp>APK 15.0.16 release Publish. 2025-05-07 14:44:06 +08:00
ZhanGSKen
9e8263ae8f 分开应用图标和调试图标 2025-05-07 14:43:20 +08:00
ZhanGSKen
5ee9da1982 <timestamp>APK 15.0.15 release Publish. 2025-05-07 14:05:50 +08:00
ZhanGSKen
f59f7676b7 调整通知栏显示信息 2025-05-07 14:05:12 +08:00
ZhanGSKen
19b8251182 <timestamp>APK 15.0.14 release Publish. 2025-05-07 13:59:51 +08:00
ZhanGSKen
4dadb15c0c <timestamp>APK 15.0.13 release Publish. 2025-05-07 13:59:38 +08:00
ZhanGSKen
21b5487513 设置时间戳初始数据 2025-05-07 13:58:56 +08:00
ZhanGSKen
f49c8141a8 <timestamp>APK 15.0.12 release Publish. 2025-05-07 13:48:06 +08:00
ZhanGSKen
6f3ce092ca 调整调试版与阶段版的消息发送 2025-05-07 13:47:26 +08:00
ZhanGSKen
29785be88d 修复信息显示 2025-05-07 13:46:21 +08:00
ZhanGSKen
3f809e4c7a <timestamp>APK 15.0.11 release Publish. 2025-05-07 13:33:12 +08:00
ZhanGSKen
9c3c485ecd 更新Maven库地址 2025-05-07 13:32:10 +08:00
ZhanGSKen
336511931d <timestamp>APK 15.0.10 release Publish. 2025-05-07 12:09:48 +08:00
ZhanGSKen
d3da3304ee 统一时间戳数据生成方法 2025-05-07 11:58:48 +08:00
ZhanGSKen
a5295a0744 更新Maven库地址 2025-05-07 11:58:14 +08:00
ZhanGSKen
9b761b35ce <timestamp>APK 15.0.9 release Publish. 2025-05-07 10:56:24 +08:00
ZhanGSKen
5206f8781e 初始数据 BugFix. 2025-05-07 10:55:46 +08:00
ZhanGSKen
2c0a5bfe65 更新默认时间戳显示格式 2025-05-07 10:51:48 +08:00
ZhanGSKen
49bce0f773 <timestamp>APK 15.0.8 release Publish. 2025-05-07 10:48:11 +08:00
ZhanGSKen
07c6778212 优化UI显示 2025-05-07 10:47:19 +08:00
ZhanGSKen
1cdad9ac7d <timestamp>APK 15.0.7 release Publish. 2025-05-07 02:58:13 +08:00
ZhanGSKen
986922c1fa 添加自定义应用内铃声 2025-05-07 02:57:08 +08:00
ZhanGSKen
bff40d2a64 重构通知栏消息,添加铃声。 2025-05-07 02:35:51 +08:00
ZhanGSKen
13e0ad3f03 <timestamp>APK 15.0.6 release Publish. 2025-05-06 20:37:48 +08:00
ZhanGSKen
be85ef923e 更新应用图标,优化状态栏UI。 2025-05-06 20:36:51 +08:00
ZhanGSKen
9a3383a43b <timestamp>APK 15.0.5 release Publish. 2025-05-06 18:33:59 +08:00
34 changed files with 434 additions and 421 deletions

View File

@@ -1,11 +1,8 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
repositories { repositories {
// 本地 Maven 仓库(默认路径为 ~/.m2/repository //本地 maven
//mavenLocal() maven { url "file:///sdcard/.aide/maven/" }
// 或自定义本地仓库路径
maven { url "file:///sdcard/.m2/repository" }
// Nexus Maven 库地址 // Nexus Maven 库地址
// "WinBoLL Release" // "WinBoLL Release"
maven { url "https://nexus.winboll.cc/repository/maven-public/" } maven { url "https://nexus.winboll.cc/repository/maven-public/" }
@@ -31,11 +28,8 @@ buildscript {
allprojects { allprojects {
repositories { repositories {
// 本地 Maven 仓库(默认路径为 ~/.m2/repository //本地 maven
//mavenLocal() maven { url "file:///sdcard/.aide/maven/" }
// 或自定义本地仓库路径
maven { url "file:///sdcard/.m2/repository" }
// Nexus Maven 库地址 // Nexus Maven 库地址
// "WinBoLL Release" // "WinBoLL Release"
maven { url "https://nexus.winboll.cc/repository/maven-public/" } maven { url "https://nexus.winboll.cc/repository/maven-public/" }

View File

@@ -24,7 +24,7 @@ android {
defaultConfig { defaultConfig {
applicationId "cc.winboll.studio.timestamp" applicationId "cc.winboll.studio.timestamp"
minSdkVersion 24 minSdkVersion 24
targetSdkVersion 30 targetSdkVersion 29
versionCode 1 versionCode 1
// versionName 更新后需要手动设置 // versionName 更新后需要手动设置
// .winboll/winbollBuildProps.properties 文件的 stageCount=0 // .winboll/winbollBuildProps.properties 文件的 stageCount=0

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle #Created by .winboll/winboll_app_build.gradle
#Tue May 06 18:33:32 HKT 2025 #Wed May 07 14:44:06 HKT 2025
stageCount=5 stageCount=17
libraryProject= libraryProject=
baseVersion=15.0 baseVersion=15.0
publishVersion=15.0.4 publishVersion=15.0.16
buildCount=0 buildCount=0
baseBetaVersion=15.0.5 baseBetaVersion=15.0.17

View File

@@ -2,7 +2,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" > xmlns:tools="http://schemas.android.com/tools" >
<application> <application
tools:replace="android:icon,android:roundIcon"
android:icon="@drawable/ic_launcher_beta"
android:roundIcon="@drawable/ic_launcher_beta">
<!-- Put flavor specific code here --> <!-- Put flavor specific code here -->

View File

@@ -14,8 +14,8 @@
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@drawable/ic_launcher_stage"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@drawable/ic_launcher_stage"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/MyAppTheme" android:theme="@style/MyAppTheme"
android:resizeableActivity="true" android:resizeableActivity="true"

View File

@@ -60,6 +60,10 @@ public class App extends GlobalApplication {
//CrashHandler.getInstance().registerGlobal(this); //CrashHandler.getInstance().registerGlobal(this);
//CrashHandler.getInstance().registerPart(this); //CrashHandler.getInstance().registerPart(this);
} }
public static int getAPPIcon() {
return BuildConfig.DEBUG?R.drawable.ic_launcher_beta:R.drawable.ic_launcher_stage;
}
public static void write(InputStream input, OutputStream output) throws IOException { public static void write(InputStream input, OutputStream output) throws IOException {
byte[] buf = new byte[1024 * 8]; byte[] buf = new byte[1024 * 8];

View File

@@ -26,11 +26,7 @@ import cc.winboll.studio.timestamp.receivers.ButtonClickReceiver;
import cc.winboll.studio.timestamp.utils.AppConfigsUtil; import cc.winboll.studio.timestamp.utils.AppConfigsUtil;
import cc.winboll.studio.timestamp.utils.NotificationHelper; import cc.winboll.studio.timestamp.utils.NotificationHelper;
import cc.winboll.studio.timestamp.utils.ServiceUtil; import cc.winboll.studio.timestamp.utils.ServiceUtil;
import cc.winboll.studio.timestamp.utils.TimeStampRemoteViewsUtil; import cc.winboll.studio.timestamp.utils.TimeStampUtil;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
public class MainService extends Service { public class MainService extends Service {
@@ -59,10 +55,9 @@ public class MainService extends Service {
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
// 创建 RemoteViews 对象,并使用包含自定义 View 的布局 mNotificationHelper = new NotificationHelper();
//mRemoteViews = new RemoteViews(getPackageName(), R.layout.remoteviews_timestamp); mNotificationHelper.createServiceNotificationChannel(this);
// 创建广播接收器实例 // 创建广播接收器实例
mButtonClickReceiver = new ButtonClickReceiver(); mButtonClickReceiver = new ButtonClickReceiver();
@@ -213,15 +208,10 @@ public class MainService extends Service {
switch (message.what) { switch (message.what) {
case MSG_UPDATE_TIMESTAMP: case MSG_UPDATE_TIMESTAMP:
{ {
long currentMillis = System.currentTimeMillis(); String szTimeStampShowString = TimeStampUtil.getInstance(MainService.this).getTimeStampShowString();
Instant instant = Instant.ofEpochMilli(currentMillis); mNotificationHelper.sendForegroundNotification(MainService.this, "时间戳:\n" + szTimeStampShowString + "\n已截取。");
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
String szTimeStampFormatString = AppConfigsUtil.getInstance(MainService.this).getAppConfigsModel().getTimeStampFormatString();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(szTimeStampFormatString);
String formattedDateTime = ldt.format(formatter);
TimeStampRemoteViewsUtil.getInstance(MainService.this).showNotification(formattedDateTime + " 已复制");
LogUtils.d(TAG, "Hello, World! " + formattedDateTime); LogUtils.d(TAG, "Hello, World! " + szTimeStampShowString);
break; break;
} }
default: default:

View File

@@ -25,8 +25,8 @@ public class AppConfigsModel extends BaseBean {
public AppConfigsModel() { public AppConfigsModel() {
this.isEnableService = false; this.isEnableService = false;
this.timeStampFormatString = "yyyy-MM-dd HH:mm:ss"; this.timeStampFormatString = "yyyy-MM-dd HH:mm:ss SSS";
this.timeStampCopyFormatString = "yyyy_MM_dd-HH_mm_ss"; this.timeStampCopyFormatString = "yyyy_MM_dd-HH_mm_ss-SSS";
} }
public void setTimeStampCopyFormatString(String timeStampCopyFormatString) { public void setTimeStampCopyFormatString(String timeStampCopyFormatString) {

View File

@@ -10,36 +10,27 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.widget.Toast; import android.widget.Toast;
import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.timestamp.BuildConfig;
import cc.winboll.studio.timestamp.MainService; import cc.winboll.studio.timestamp.MainService;
import cc.winboll.studio.timestamp.utils.AppConfigsUtil;
import cc.winboll.studio.timestamp.utils.ClipboardUtil; import cc.winboll.studio.timestamp.utils.ClipboardUtil;
import java.time.Instant; import cc.winboll.studio.timestamp.utils.TimeStampUtil;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
public class ButtonClickReceiver extends BroadcastReceiver { public class ButtonClickReceiver extends BroadcastReceiver {
public static final String TAG = "ButtonClickReceiver"; public static final String TAG = "ButtonClickReceiver";
public static final String BUTTON_COPYTIMESTAMP_ACTION = "cc.winboll.studio.timestamp.receivers.ButtonClickReceiver.BUTTON_COPYTIMESTAMP_ACTION"; public static final String BUTTON_COPYTIMESTAMP_ACTION = ButtonClickReceiver.class.getName() + (BuildConfig.DEBUG ?".DEBUG_": ".") + "BUTTON_COPYTIMESTAMP_ACTION";
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
LogUtils.d(TAG, "onReceive"); LogUtils.d(TAG, "onReceive");
if (intent.getAction().equals(BUTTON_COPYTIMESTAMP_ACTION)) { if (intent.getAction().equals(BUTTON_COPYTIMESTAMP_ACTION)) {
// 在这里编写按钮点击后要执行的代码 // 在这里编写按钮点击后要执行的代码
long currentMillis = System.currentTimeMillis(); TimeStampUtil.getInstance(context).genTimeStamp();
Instant instant = Instant.ofEpochMilli(currentMillis); ClipboardUtil.copyTextToClipboard(context, TimeStampUtil.getInstance(context).getTimeStampCopyString());
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
String szTimeStampFormatString = AppConfigsUtil.getInstance(context).getAppConfigsModel().getTimeStampCopyFormatString();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(szTimeStampFormatString);
String formattedDateTime = ldt.format(formatter);
ClipboardUtil.copyTextToClipboard(context, formattedDateTime);
// 比如显示一个Toast // 比如显示一个Toast
Toast.makeText(context, formattedDateTime + " 已复制", Toast.LENGTH_SHORT).show(); Toast.makeText(context, "时间戳:\n" + TimeStampUtil.getInstance(context).getTimeStampCopyString() + "\n已拷贝到剪贴板。", Toast.LENGTH_SHORT).show();
MainService.updateCopiedTimeStamp(); MainService.updateCopiedTimeStamp();
} }
} }

View File

@@ -22,12 +22,12 @@ public class AppConfigsUtil {
AppConfigsUtil(Context context) { AppConfigsUtil(Context context) {
this.mContext = context; this.mContext = context;
loadAppConfigs();
} }
public synchronized static AppConfigsUtil getInstance(Context context){ public synchronized static AppConfigsUtil getInstance(Context context){
if(_AppConfigsUtil == null) { if(_AppConfigsUtil == null) {
_AppConfigsUtil = new AppConfigsUtil(context); _AppConfigsUtil = new AppConfigsUtil(context);
_AppConfigsUtil.loadAppConfigs();
} }
return _AppConfigsUtil; return _AppConfigsUtil;
} }
@@ -42,8 +42,8 @@ public class AppConfigsUtil {
if (appConfigsModel != null) { if (appConfigsModel != null) {
mAppConfigsModel = appConfigsModel; mAppConfigsModel = appConfigsModel;
} else { } else {
saveAppConfigs(new AppConfigsModel()); mAppConfigsModel = new AppConfigsModel();
_AppConfigsUtil = this; saveAppConfigs(mAppConfigsModel);
} }
return mAppConfigsModel; return mAppConfigsModel;
} }

View File

@@ -0,0 +1,71 @@
package cc.winboll.studio.timestamp.utils;
/**
* @Author ZhanGSKen
* @Date 2025/05/07 02:38
* @Describe AudioPlayer
*/
import android.content.Context;
import android.media.MediaPlayer;
import android.net.Uri;
import android.util.Log;
public class AudioPlayerMP3Util {
public static final String TAG = "AudioPlayer";
private static MediaPlayer mediaPlayer;
/**
* 播放指定的 MP3 文件
*
* @param context 上下文
* @param mp3FilePath MP3 文件的路径,例如:"/storage/emulated/0/Music/song.mp3"
*/
public static void playMp3(Context context, String mp3FilePath) {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
try {
mediaPlayer = new MediaPlayer();
Uri uri = Uri.parse(mp3FilePath);
mediaPlayer.setDataSource(context, uri);
mediaPlayer.prepare();
mediaPlayer.start();
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
releaseMediaPlayer();
}
});
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.e("AudioPlayer", "播放音频时出错: what=" + what + ", extra=" + extra);
releaseMediaPlayer();
return true;
}
});
} catch (Exception e) {
e.printStackTrace();
releaseMediaPlayer();
}
}
/**
* 释放 MediaPlayer 资源
*/
private static void releaseMediaPlayer() {
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
}
}

View File

@@ -0,0 +1,69 @@
package cc.winboll.studio.timestamp.utils;
/**
* @Author ZhanGSKen
* @Date 2025/05/07 02:31
* @Describe AudioPlayerUtil
*/
import android.content.Context;
import android.media.MediaPlayer;
import android.net.Uri;
import android.util.Log;
public class AudioPlayerUriUtil {
public static final String TAG = "AudioPlayerUtil";
private static MediaPlayer mediaPlayer;
/**
* 播放指定Uri的音频
* @param context 上下文
* @param audioUri 音频的Uri
*/
public static void playAudio(Context context, Uri audioUri) {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(context, audioUri);
mediaPlayer.prepare();
mediaPlayer.start();
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
releaseMediaPlayer();
}
});
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.e("AudioPlayer", "播放音频时出错: what=" + what + ", extra=" + extra);
releaseMediaPlayer();
return true;
}
});
} catch (Exception e) {
e.printStackTrace();
releaseMediaPlayer();
}
}
/**
* 释放MediaPlayer资源
*/
private static void releaseMediaPlayer() {
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
}
}

View File

@@ -12,212 +12,195 @@ import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.os.Build; import android.graphics.Color;
import android.media.RingtoneManager;
import android.net.Uri;
import android.widget.RemoteViews; import android.widget.RemoteViews;
import androidx.annotation.RequiresApi; import cc.winboll.studio.timestamp.App;
import androidx.core.app.NotificationCompat; import cc.winboll.studio.timestamp.MainActivity;
import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.timestamp.MainService;
import cc.winboll.studio.timestamp.R; import cc.winboll.studio.timestamp.R;
import java.util.HashMap; import cc.winboll.studio.timestamp.receivers.ButtonClickReceiver;
import java.util.List;
import java.util.Map;
public class NotificationHelper { public class NotificationHelper {
public static final String TAG = "NotificationHelper";
// 渠道ID和名称 public static final String TAG = "NotificationUtil";
private static final String CHANNEL_ID_FOREGROUND = "foreground_channel"; public static final int ID_MSG_SERVICE = 10000;
private static final String CHANNEL_NAME_FOREGROUND = "Foreground Service";
private static final String CHANNEL_ID_TEMPORARY = "temporary_channel";
private static final String CHANNEL_NAME_TEMPORARY = "Temporary Notifications";
// 通知ID static final String szSMSChannelID = "1";
public static final int FOREGROUND_NOTIFICATION_ID = 1001;
public static final int TEMPORARY_NOTIFICATION_ID = 2001;
private final Context mContext; static final String szServiceChannelID = "0";
private final NotificationManager mNotificationManager;
// 示例维护当前使用的渠道ID列表
// 键渠道ID渠道重要性级别
Map<String, Integer> activeChannelConfigs = new HashMap<>();
public NotificationHelper(Context context) { //static int mNumSendForegroundNotification = 10000;
//static int mNumSendSMSNotification = 20000;
Context mContext;
public NotificationManager createServiceNotificationChannel(Context context) {
mContext = context; mContext = context;
mNotificationManager = context.getSystemService(NotificationManager.class); //创建通知渠道ID
String channelId = szServiceChannelID;
// 初始化配置 //创建通知渠道名称
activeChannelConfigs.put( String channelName = "Service Message";
CHANNEL_ID_FOREGROUND, //创建通知渠道重要性
NotificationManager.IMPORTANCE_HIGH int importance = NotificationManager.IMPORTANCE_MIN;
); NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
activeChannelConfigs.put(
CHANNEL_ID_TEMPORARY,
NotificationManager.IMPORTANCE_DEFAULT
);
createNotificationChannels();
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void createNotificationChannels() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createForegroundChannel();
createTemporaryChannel();
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void createForegroundChannel() {
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID_FOREGROUND,
CHANNEL_NAME_FOREGROUND,
NotificationManager.IMPORTANCE_LOW
);
channel.setDescription("Persistent service notifications");
channel.setSound(null, null); channel.setSound(null, null);
channel.enableVibration(false); NotificationManager notificationManager = (NotificationManager) context.getSystemService(
mNotificationManager.createNotificationChannel(channel); Context.NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
return notificationManager;
} }
@RequiresApi(api = Build.VERSION_CODES.O) public NotificationManager createSMSNotificationChannel(Context context) {
private void createTemporaryChannel() { //创建通知渠道ID
NotificationChannel channel = new NotificationChannel( String channelId = szSMSChannelID;
CHANNEL_ID_TEMPORARY, //创建通知渠道名称
CHANNEL_NAME_TEMPORARY, String channelName = "SMS Message";
NotificationManager.IMPORTANCE_HIGH //创建通知渠道重要性
); int importance = NotificationManager.IMPORTANCE_HIGH;
channel.setDescription("Temporary alert notifications"); NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
channel.setSound(null, null); channel.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE), Notification.AUDIO_ATTRIBUTES_DEFAULT);
channel.enableVibration(true); NotificationManager notificationManager = (NotificationManager) context.getSystemService(
channel.setVibrationPattern(new long[]{100, 200, 300, 400}); Context.NOTIFICATION_SERVICE);
channel.setBypassDnd(true); notificationManager.createNotificationChannel(channel);
mNotificationManager.createNotificationChannel(channel); return notificationManager;
} }
// 显示常驻通知(通常用于前台服务) // 创建通知
public Notification showForegroundNotification(Intent intent, String title, String content) { //
PendingIntent pendingIntent = createPendingIntent(intent); public void sendForegroundNotification(MainService service, String message) {
//创建Notification传入Context和channelId
Intent intent = new Intent();//这个intent会传给目标,可以使用getIntent来获取
intent.setClass(mContext, MainActivity.class);
Notification notification = new NotificationCompat.Builder(mContext, CHANNEL_ID_FOREGROUND) //这里放一个count用来区分每一个通知
.setSmallIcon(R.drawable.ic_launcher) //intent.putExtra("intent", "intent--->" + count);//这里设置一个数据,带过去
.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_launcher))
//.setContentTitle(title)
.setContentTitle(content)
//.setContentText(content)
.setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_LOW)
.setOngoing(true)
.build();
mNotificationManager.notify(FOREGROUND_NOTIFICATION_ID, notification); //参数1:context 上下文对象
return notification; //参数2:发送者私有的请求码(Private request code for the sender)
} //参数3:intent 意图对象
//参数4:必须为FLAG_ONE_SHOT,FLAG_NO_CREATE,FLAG_CANCEL_CURRENT,FLAG_UPDATE_CURRENT,中的一个
PendingIntent mForegroundPendingIntent = PendingIntent.getActivity(service, ID_MSG_SERVICE, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT);
// 显示常驻通知(通常用于前台服务) Notification mForegroundNotification = new Notification.Builder(service, szServiceChannelID)
public Notification showCustomForegroundNotification(Intent intent, RemoteViews contentView, RemoteViews bigContentView) {
PendingIntent pendingIntent = createPendingIntent(intent);
Notification notification = new NotificationCompat.Builder(mContext, CHANNEL_ID_FOREGROUND)
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_launcher))
//.setContentTitle(title)
.setContentIntent(pendingIntent)
.setContent(contentView)
.setCustomBigContentView(bigContentView)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true) .setAutoCancel(true)
.setOngoing(true) //.setContentTitle(nessageNotificationBean.getTitle())
//.setContentText(nessageNotificationBean.getContent())
//.setContent(remoteviews)
.setWhen(System.currentTimeMillis())
.setSmallIcon(App.getAPPIcon())
//设置红色
.setColor(Color.parseColor("#F00606"))
.setLargeIcon(BitmapFactory.decodeResource(service.getResources(), App.getAPPIcon()))
.setContentIntent(mForegroundPendingIntent)
.build(); .build();
mNotificationManager.notify(FOREGROUND_NOTIFICATION_ID, notification); // 创建 RemoteViews 对象,加载布局
return notification; RemoteViews remoteViews = new RemoteViews(mContext.getPackageName(), R.layout.custom_notification_layout);
}
// 显示临时通知(自动消失) // 自定义 TextView 的文本
public void showTemporaryNotification(Intent intent, String title, String content) { remoteViews.setTextViewText(R.id.tv_timestamp, message);
showTemporaryNotification(intent, TEMPORARY_NOTIFICATION_ID, title, content); // 自定义 TextView 的文本颜色
} remoteViews.setTextColor(R.id.tv_timestamp, mContext.getResources().getColor(R.color.colorAccent, null));
// 这里虽然不能直接设置字体大小,但可以通过反射等方式尝试(不推荐,且有兼容性问题)
// 显示临时通知(自动消失) // 设置按钮图片
public void showTemporaryNotification(Intent intent, int notificationID, String title, String content) { remoteViews.setImageViewResource(R.id.iv_copytimestamp, App.getAPPIcon());
PendingIntent pendingIntent = createPendingIntent(intent); // 创建点击通知后的意图
Intent intentMain = new Intent(mContext, MainActivity.class);
PendingIntent pendingMainIntent = PendingIntent.getActivity(mContext, 0, intentMain, PendingIntent.FLAG_UPDATE_CURRENT);
// 设置通知的点击事件
remoteViews.setOnClickPendingIntent(R.id.tv_timestamp, pendingMainIntent);
Notification notification = new NotificationCompat.Builder(mContext, CHANNEL_ID_TEMPORARY) // 创建点击按钮后要发送的广播 Intent
.setSmallIcon(R.drawable.ic_launcher) Intent broadcastIntent = new Intent(ButtonClickReceiver.BUTTON_COPYTIMESTAMP_ACTION);
.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_launcher)) android.app.PendingIntent pendingIntent = android.app.PendingIntent.getBroadcast(
.setContentTitle(title)
.setContentText(content)
.setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
.setVibrate(new long[]{100, 200, 300, 400})
.build();
mNotificationManager.notify(notificationID, notification);
}
// 创建自定义布局通知(可扩展)
public void showCustomNotification(Intent intent, RemoteViews contentView, RemoteViews bigContentView) {
PendingIntent pendingIntent = createPendingIntent(intent);
Notification notification = new NotificationCompat.Builder(mContext, CHANNEL_ID_TEMPORARY)
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pendingIntent)
.setContent(contentView)
.setCustomBigContentView(bigContentView)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
.build();
mNotificationManager.notify(TEMPORARY_NOTIFICATION_ID + 1, notification);
}
// 取消所有通知
public void cancelAllNotifications() {
mNotificationManager.cancelAll();
}
// 取消指定通知
public void cancelNotification(int notificationID) {
mNotificationManager.cancel(notificationID);
}
// 创建PendingIntent兼容不同API版本
private PendingIntent createPendingIntent(Intent intent) {
int flags = PendingIntent.FLAG_UPDATE_CURRENT;
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
// flags |= PendingIntent.FLAG_IMMUTABLE;
// }
return PendingIntent.getActivity(
mContext, mContext,
0, 0,
intent, broadcastIntent,
flags android.app.PendingIntent.FLAG_UPDATE_CURRENT
); );
}
// public void sendSMSReceivedMessage(int notificationID, String szPhone, String szBody) { // 为按钮设置点击事件
// Intent intent = new Intent(mContext, SMSActivity.class); remoteViews.setOnClickPendingIntent(R.id.iv_copytimestamp, pendingIntent);
// intent.putExtra(SMSActivity.EXTRA_PHONE, szPhone);
// String szTitle = mContext.getString(R.string.text_smsfrom) + "<" + szPhone + ">"; mForegroundNotification.contentView = remoteViews;
// String szContent = "[ " + szBody + " ]"; mForegroundNotification.bigContentView = remoteViews;
// showTemporaryNotification(intent, notificationID, szTitle, szContent);
service.startForeground(ID_MSG_SERVICE, mForegroundNotification);
// 播放默认短信铃声
Uri defaultSmsRingtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
AudioPlayerUriUtil.playAudio(service, defaultSmsRingtoneUri);
// 播放应用铃声
// 获取MP3文件的Uri
Uri soundUri = Uri.parse("android.resource://" + service.getPackageName() + "/" + R.raw.diweiyi);
AudioPlayerUriUtil.playAudio(service, soundUri);
}
// public void sendSMSNotification(Context context, MessageNotificationBean messageNotificationBean) {
// NotificationManager notificationManager = (NotificationManager) context.getSystemService(
// Context.NOTIFICATION_SERVICE);
// /*NotificationManager notificationManager = createSMSNotificationChannel(context);
// if (notificationManager == null) {
// LogUtils.d(TAG, "createSMSNotificationChannel failed.");
// return;
// }*/
//
// //创建Notification传入Context和channelId
// Intent intent = new Intent(context, SMSActivity.class);
// intent.putExtra(SMSActivity.EXTRA_PHONE, messageNotificationBean.getPhone());
// LogUtils.d(TAG, "sendSMSNotification(...) message.getPhone() is : " + messageNotificationBean.getPhone());
// //Intent intent = new Intent();//这个intent会传给目标,可以使用getIntent来获取
// //intent.setClass(context, MainActivity.class);
// //这里放一个count用来区分每一个通知
// //intent.putExtra("intent", "intent--->" + count);//这里设置一个数据,带过去
//
// //参数1:context 上下文对象
// //参数2:发送者私有的请求码(Private request code for the sender)
// //参数3:intent 意图对象
// //参数4:必须为FLAG_ONE_SHOT,FLAG_NO_CREATE,FLAG_CANCEL_CURRENT,FLAG_UPDATE_CURRENT,中的一个
// PendingIntent mRemindPendingIntent = PendingIntent.getActivity(context, messageNotificationBean.getMessageId(), intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT);
// Notification mSMSNotification = new Notification.Builder(context, szSMSChannelID)
// .setAutoCancel(true)
// .setContentTitle(messageNotificationBean.getTitle())
// .setContentText(messageNotificationBean.getContent())
// .setWhen(System.currentTimeMillis())
// .setSmallIcon(R.drawable.ic_launcher)
// //设置红色
// .setColor(Color.parseColor("#F00606"))
// .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher))
// .setContentIntent(mRemindPendingIntent)
// .build();
//
// RemoteViews mrvSMSNotificationView = new RemoteViews(context.getPackageName(), R.layout.remoteview);
// mrvSMSNotificationView.setTextViewText(R.id.remoteviewTextView1, messageNotificationBean.getTitle());
// mrvSMSNotificationView.setTextViewText(R.id.remoteviewTextView2, messageNotificationBean.getContent());
// mrvSMSNotificationView.setImageViewResource(R.id.remoteviewImageView1, R.drawable.ic_launcher);
// mSMSNotification.contentView = mrvSMSNotificationView;
// mSMSNotification.bigContentView = mrvSMSNotificationView;
// notificationManager.notify(messageNotificationBean.getMessageId(), mSMSNotification);
// LogUtils.d(TAG, "getMessageId is : " + Integer.toString(messageNotificationBean.getMessageId()));
//
// } // }
public void cleanOldChannels() { // public void sendSMSReceivedMessage(Context context, int nMessageId, String szPhone, String szBody) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // String szTitle = context.getString(R.string.text_smsfrom) + "<" + szPhone + ">";
List<NotificationChannel> allChannels = mNotificationManager.getNotificationChannels(); // String szContent = "[ " + szBody + " ]";
for (NotificationChannel channel : allChannels) { // sendSMSNotification(context, new MessageNotificationBean(nMessageId, szPhone, szTitle, szContent));
LogUtils.d(TAG, "Clean channel : " + channel.getId()); // }
if (!activeChannelConfigs.containsKey(channel.getId())) {
// 安全删除渠道 // public static void cancelNotification(Context context, int notificationId) {
mNotificationManager.deleteNotificationChannel(channel.getId()); // // 获取 NotificationManager 实例
LogUtils.d(TAG, String.format("Deleted Channel %s", channel.getId())); // NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
} // // 撤回指定 ID 的通知栏消息
} // notificationManager.cancel(notificationId);
} // }
}
} }

View File

@@ -1,132 +0,0 @@
package cc.winboll.studio.timestamp.utils;
/**
* @Author ZhanGSKen
* @Date 2025/05/05 21:10
* @Describe TimeStampRemoteViewsUtil
*/
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.widget.RemoteViews;
import cc.winboll.studio.timestamp.MainActivity;
import cc.winboll.studio.timestamp.R;
import cc.winboll.studio.timestamp.receivers.ButtonClickReceiver;
public class TimeStampRemoteViewsUtil {
public static final String TAG = "TimeStampRemoteViewsUtil";
public static final String CHANNEL_ID = "TimeStampChannel";
static volatile TimeStampRemoteViewsUtil _TimeStampRemoteViewsUtil;
Context mContext;
NotificationHelper mNotificationHelper;
RemoteViews mRemoteViews;
Intent mIntentMain;
TimeStampRemoteViewsUtil(Context context) {
mContext = context;
mNotificationHelper = new NotificationHelper(context);
//createNotificationChannel();
}
public static synchronized TimeStampRemoteViewsUtil getInstance(Context context) {
if (_TimeStampRemoteViewsUtil == null) {
_TimeStampRemoteViewsUtil = new TimeStampRemoteViewsUtil(context);
}
return _TimeStampRemoteViewsUtil;
}
// private void createNotificationChannel() {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// CharSequence name = "自定义视图通知通道";
// String description = "用于展示自定义视图的通知通道";
// int importance = NotificationManager.IMPORTANCE_HIGH;
// NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
// channel.setDescription(description);
// NotificationManager notificationManager = mContext.getSystemService(NotificationManager.class);
// notificationManager.createNotificationChannel(channel);
// }
// }
// public void showNotification(String msg) {
// if (mRemoteViews == null) {
// // 创建 RemoteViews 对象,加载布局
// mRemoteViews = new RemoteViews(mContext.getPackageName(), R.layout.custom_notification_layout);
//
// }
// // 自定义 TextView 的文本
// mRemoteViews.setTextViewText(R.id.tv_timestamp, msg);
// // 自定义 TextView 的文本颜色
// mRemoteViews.setTextColor(R.id.tv_timestamp, mContext.getResources().getColor(R.color.colorAccent, null));
// // 这里虽然不能直接设置字体大小,但可以通过反射等方式尝试(不推荐,且有兼容性问题)
//
// // 创建点击通知后的意图
// Intent intent = new Intent(mContext, MainActivity.class);
// PendingIntent pendingMainIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// // 设置通知的点击事件
// mRemoteViews.setOnClickPendingIntent(R.id.tv_timestamp, pendingMainIntent);
//
// // 创建点击按钮后要发送的广播 Intent
// Intent broadcastIntent = new Intent(ButtonClickReceiver.BUTTON_COPYTIMESTAMP_ACTION);
// android.app.PendingIntent pendingIntent = android.app.PendingIntent.getBroadcast(
// mContext,
// 0,
// broadcastIntent,
// android.app.PendingIntent.FLAG_UPDATE_CURRENT
// );
//
// // 为按钮设置点击事件
// mRemoteViews.setOnClickPendingIntent(R.id.btn_copytimestamp, pendingIntent);
//
// // 构建通知
// NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext, CHANNEL_ID)
// .setSmallIcon(android.R.drawable.ic_dialog_info)
// .setContent(mRemoteViews)
// .setPriority(NotificationCompat.PRIORITY_HIGH)
// .setOngoing(true)
// .setAutoCancel(true);
//
// // 显示通知
// NotificationManager notificationManager = mContext.getSystemService(NotificationManager.class);
// mNotification = builder.build();
// notificationManager.notify(1, mNotification);
// }
public void showNotification(String msg) {
if (mRemoteViews == null) {
// 创建 RemoteViews 对象,加载布局
mRemoteViews = new RemoteViews(mContext.getPackageName(), R.layout.custom_notification_layout);
}
// 自定义 TextView 的文本
mRemoteViews.setTextViewText(R.id.tv_timestamp, msg);
// 自定义 TextView 的文本颜色
mRemoteViews.setTextColor(R.id.tv_timestamp, mContext.getResources().getColor(R.color.colorAccent, null));
// 这里虽然不能直接设置字体大小,但可以通过反射等方式尝试(不推荐,且有兼容性问题)
// 创建点击通知后的意图
mIntentMain = new Intent(mContext, MainActivity.class);
PendingIntent pendingMainIntent = PendingIntent.getActivity(mContext, 0, mIntentMain, PendingIntent.FLAG_UPDATE_CURRENT);
// 设置通知的点击事件
mRemoteViews.setOnClickPendingIntent(R.id.tv_timestamp, pendingMainIntent);
// 创建点击按钮后要发送的广播 Intent
Intent broadcastIntent = new Intent(ButtonClickReceiver.BUTTON_COPYTIMESTAMP_ACTION);
android.app.PendingIntent pendingIntent = android.app.PendingIntent.getBroadcast(
mContext,
0,
broadcastIntent,
android.app.PendingIntent.FLAG_UPDATE_CURRENT
);
// 为按钮设置点击事件
mRemoteViews.setOnClickPendingIntent(R.id.btn_copytimestamp, pendingIntent);
mNotificationHelper.showCustomForegroundNotification(mIntentMain, mRemoteViews, mRemoteViews);
}
}

View File

@@ -0,0 +1,58 @@
package cc.winboll.studio.timestamp.utils;
/**
* @Author ZhanGSKen
* @Date 2025/05/07 11:03
* @Describe TimeStampUtil
*/
import android.content.Context;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
public class TimeStampUtil {
public static final String TAG = "TimeStampUtil";
volatile static TimeStampUtil _TimeStampUtil;
Context mContext;
long mTimeStamp;
TimeStampUtil(Context context) {
mContext = context;
mTimeStamp = System.currentTimeMillis();
}
public synchronized static TimeStampUtil getInstance(Context context) {
if (_TimeStampUtil == null) {
_TimeStampUtil = new TimeStampUtil(context);
}
return _TimeStampUtil;
}
public void genTimeStamp() {
mTimeStamp = System.currentTimeMillis();
}
public String getTimeStampShowString() {
long currentMillis = mTimeStamp;
Instant instant = Instant.ofEpochMilli(currentMillis);
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
String szTimeStampFormatString = AppConfigsUtil.getInstance(mContext).getAppConfigsModel().getTimeStampFormatString();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(szTimeStampFormatString);
String formattedDateTime = ldt.format(formatter);
return formattedDateTime;
}
public String getTimeStampCopyString() {
long currentMillis = mTimeStamp;
Instant instant = Instant.ofEpochMilli(currentMillis);
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
String szTimeStampFormatString = AppConfigsUtil.getInstance(mContext).getAppConfigsModel().getTimeStampCopyFormatString();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(szTimeStampFormatString);
String formattedDateTime = ldt.format(formatter);
return formattedDateTime;
}
}

View File

@@ -1,34 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeColor="#00000000"
android:strokeWidth="1">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeColor="#00000000"
android:strokeWidth="1" />
</vector>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:clickable="true">
<item
android:left="1dp"
android:top="1dp"
android:right="1dp"
android:bottom="1dp"
android:drawable="@drawable/ic_launcher_background"/>
<item
android:left="1dp"
android:top="1dp"
android:right="1dp"
android:bottom="1dp"
android:drawable="@drawable/ic_launcher_foreground"/>
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:clickable="true">
<!--<item android:drawable="@drawable/ic_launcher_background"/>-->
<item
android:left="1dp"
android:top="1dp"
android:right="1dp"
android:bottom="1dp"
android:drawable="@drawable/ic_launcher_foreground"/>
</layer-list>

View File

@@ -28,21 +28,21 @@
<Switch <Switch
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="启用通知栏计时器" android:text="启用时间戳常驻通知栏"
android:id="@+id/activitymainSwitch1" android:id="@+id/activitymainSwitch1"
android:onClick="onSetMainServiceStatus"/> android:onClick="onSetMainServiceStatus"/>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Show Format :" android:text="Show Format Preview:"
android:paddingRight="10dp"/> android:paddingRight="10dp"/>
<TextView <TextView
@@ -69,7 +69,7 @@
<Button <Button
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="ApplySave" android:text="ApplyShow"
android:id="@+id/btn_saveformatstring" android:id="@+id/btn_saveformatstring"
android:textAllCaps="false" android:textAllCaps="false"
android:onClick="onSaveFormatString"/> android:onClick="onSaveFormatString"/>
@@ -77,14 +77,14 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Copy Format :" android:text="Copy Format Preview:"
android:paddingRight="10dp"/> android:paddingRight="10dp"/>
<TextView <TextView

View File

@@ -13,14 +13,13 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Text" android:text="Text"
android:textColor="#000000" android:textColor="#000000"
android:textSize="18sp" android:textSize="14sp"
android:layout_weight="1.0"/> android:layout_weight="1.0"/>
<Button <ImageView
android:layout_width="wrap_content" android:layout_width="60dp"
android:layout_height="wrap_content" android:layout_height="60dp"
android:text="复制时间戳" android:id="@+id/iv_copytimestamp"/>
android:id="@+id/btn_copytimestamp"/>
</LinearLayout> </LinearLayout>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.