Compare commits

..

3 Commits

Author SHA1 Message Date
ZhanGSKen
3e7722e2c0 <numtable>APK 15.1.1 release Publish. 2025-07-24 10:16:27 +08:00
ZhanGSKen
a1707e73b5 添加页面方向指示图标创建功能 2025-07-24 10:12:30 +08:00
ZhanGSKen
9dcbaa0d75 添加桌面快捷方式创建功能 2025-07-24 09:00:19 +08:00
14 changed files with 331 additions and 286 deletions

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Sun Jun 08 21:21:11 HKT 2025
stageCount=1
#Thu Jul 24 10:16:27 HKT 2025
stageCount=2
libraryProject=
baseVersion=15.1
publishVersion=15.1.0
publishVersion=15.1.1
buildCount=0
baseBetaVersion=15.1.1
baseBetaVersion=15.1.2

View File

@@ -3,6 +3,11 @@
xmlns:android="http://schemas.android.com/apk/res/android"
package="cc.winboll.studio.numtable">
<!-- Android 13及以下需要的权限 -->
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<!-- 可选:查询快捷方式是否存在(部分机型需要) -->
<uses-permission android:name="com.android.launcher.permission.QUERY_ALL_PACKAGES" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
@@ -29,9 +34,7 @@
<meta-data
android:name="android.max_aspect"
android:value="4.0"/>
<activity android:name=".GlobalApplication$CrashActivity"/>
</application>
</manifest>

View File

@@ -1,10 +1,20 @@
package cc.winboll.studio.numtable;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.graphics.drawable.Icon;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import cc.winboll.studio.libappbase.LogView;
import cc.winboll.studio.numtable.R;
import com.hjq.toast.ToastUtils;
import java.util.UUID;
public class MainActivity extends AppCompatActivity {
@@ -19,10 +29,99 @@ public class MainActivity extends AppCompatActivity {
setSupportActionBar(toolbar);
mLogView = findViewById(R.id.logview);
ToastUtils.show("onCreate");
// 初始化创建快捷方式按钮
Button btnCreateShortcut = findViewById(R.id.btn_create_shortcut);
btnCreateShortcut.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
createDesktopShortcut();
}
});
((RadioButton)findViewById(R.id.rb_right)).setChecked(true);
((RadioButton)findViewById(R.id.rb_left)).setChecked(false);
}
public void onDirectionClick(View view) {
switch (view.getId()) {
case R.id.rb_right:
{
((RadioButton)findViewById(R.id.rb_left)).setChecked(false);
break;
}
case R.id.rb_left:
{
((RadioButton)findViewById(R.id.rb_right)).setChecked(false);
break;
}
}
}
/**
* 创建桌面快捷方式
*/
private void createDesktopShortcut() {
// 1. 创建启动目标Activity的Intent通常是你的主Activity
Intent targetIntent = new Intent(this, MainActivity.class); // 替换为你的主Activity
targetIntent.setAction(Intent.ACTION_MAIN);
targetIntent.addCategory(Intent.CATEGORY_LAUNCHER);
targetIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
// 2. 创建快捷方式的Intent
Intent shortcutIntent = new Intent();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// 生成随机UUID
UUID uuid = UUID.randomUUID();
// 转换为字符串
String uuidStr = uuid.toString();
// Android 8.0及以上使用ShortcutManager
ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
if (shortcutManager.isRequestPinShortcutSupported()) {
if (((RadioButton)findViewById(R.id.rb_right)).isChecked()) {
// 创建快捷方式信息
ShortcutInfo shortcutInfo = new ShortcutInfo.Builder(this, uuidStr) // 唯一ID
.setShortLabel(">>") // 短标签(显示在桌面)
.setLongLabel("在右边 >>") // 长标签(长按显示)
.setIcon(Icon.createWithResource(this, R.drawable.ic_point_right)) // 图标
.setIntent(targetIntent)
.build();
// 发送创建请求
shortcutManager.requestPinShortcut(shortcutInfo, null);
} else {
ShortcutInfo shortcutInfo = new ShortcutInfo.Builder(this, uuidStr) // 唯一ID
.setShortLabel("<<") // 短标签(显示在桌面)
.setLongLabel("在左边 <<") // 长标签(长按显示)
.setIcon(Icon.createWithResource(this, R.drawable.ic_point_left)) // 图标
.setIntent(targetIntent)
.build();
// 发送创建请求
shortcutManager.requestPinShortcut(shortcutInfo, null);
}
ToastUtils.show("已请求创建快捷方式");
} else {
ToastUtils.show("当前设备不支持创建快捷方式");
}
} else {
// Android 7.1及以下:使用旧版广播方式
shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, targetIntent);
shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "应用快捷方式"); // 快捷方式名称
// 设置图标(使用应用图标)
shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
Intent.ShortcutIconResource.fromContext(this, R.mipmap.ic_launcher));
// 标记为创建快捷方式
shortcutIntent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
// 防止重复创建
shortcutIntent.putExtra("duplicate", false);
// 发送广播创建快捷方式
sendBroadcast(shortcutIntent);
ToastUtils.show("快捷方式已创建");
}
}
@Override
protected void onResume() {
super.onResume();

View File

@@ -0,0 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="512dp"
android:viewportWidth="512"
android:viewportHeight="512">
<path
android:fillColor="#FF3D8A1C"
android:strokeColor="#FFF5DD00"
android:strokeWidth="5.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M401.84 141.95C361.52 236.12 354.86 278.98 399.2 382.12 359.53 383.01 245.24 289.83 245.38 265.73 247.41 236.75 361.69 143.4 401.84 141.95Z"/>
<path
android:fillColor="#FF3D8A1C"
android:strokeColor="#FFF5DD00"
android:strokeWidth="5.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M276.81 141.95C236.49 236.12 229.83 278.98 274.17 382.12 234.5 383.01 120.2 289.83 120.35 265.73 122.37 236.75 236.66 143.4 276.81 141.95Z"/>
</vector>

View File

@@ -0,0 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="512dp"
android:viewportWidth="512"
android:viewportHeight="512">
<path
android:fillColor="#FF3D8A1C"
android:strokeColor="#FFF5DD00"
android:strokeWidth="5.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M103.57 145.68C143.89 239.85 150.55 282.71 106.21 385.85 145.88 386.74 260.17 293.56 260.03 269.46 258 240.48 143.72 147.13 103.57 145.68Z"/>
<path
android:fillColor="#FF3D8A1C"
android:strokeColor="#FFF5DD00"
android:strokeWidth="5.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M228.6 145.68C268.92 239.85 275.58 282.71 231.24 385.85 270.91 386.74 385.21 293.56 385.06 269.46 383.04 240.48 268.75 147.13 228.6 145.68Z"/>
</vector>

View File

@@ -23,14 +23,44 @@
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.0"
android:gravity="center_vertical|center_horizontal">
android:layout_weight="1.0">
<TextView
android:layout_width="wrap_content"
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="NumTable"
android:textAppearance="?android:attr/textAppearanceLarge"/>
android:gravity="right|center_vertical"
android:layout_gravity="center_vertical">
<ImageView
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@drawable/ic_point_right"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/rb_right"
android:onClick="onDirectionClick"/>
<ImageView
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@drawable/ic_point_left"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/rb_left"
android:onClick="onDirectionClick"/>
<Button
android:id="@+id/btn_create_shortcut"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="创建桌面快捷方式"/>
</LinearLayout>
</LinearLayout>

View File

@@ -1,7 +1,5 @@
## TimpStamp
#### 介绍
时间戳工具集。常驻工具栏快捷拷贝一份时间戳到剪贴板的工具。
## 时间戳工具集
## 使用要点:
1。常驻通知栏按钮的正常使用

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Mon Jul 28 11:36:51 HKT 2025
stageCount=4
#Wed May 07 15:07:02 HKT 2025
stageCount=2
libraryProject=
baseVersion=15.1
publishVersion=15.1.3
publishVersion=15.1.1
buildCount=0
baseBetaVersion=15.1.4
baseBetaVersion=15.1.2

View File

@@ -3,9 +3,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
package="cc.winboll.studio.timestamp">
<!-- 开机启动 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<!-- 运行前台服务 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
@@ -48,20 +45,6 @@
<service android:name=".AssistantService"/>
<receiver
android:name=".receivers.MainReceiver"
android:enabled="true"
android:exported="false"
android:directBootAware="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
</application>
</manifest>

View File

@@ -5,7 +5,6 @@ import android.view.View;
import android.widget.EditText;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import cc.winboll.studio.libappbase.LogUtils;
@@ -13,8 +12,6 @@ import cc.winboll.studio.libappbase.LogView;
import cc.winboll.studio.timestamp.MainService;
import cc.winboll.studio.timestamp.R;
import cc.winboll.studio.timestamp.utils.AppConfigsUtil;
import cc.winboll.studio.timestamp.utils.ClipboardUtil;
import cc.winboll.studio.timestamp.utils.TimeStampUtil;
import com.hjq.toast.ToastUtils;
import java.time.Instant;
import java.time.LocalDateTime;
@@ -100,22 +97,4 @@ public class MainActivity extends AppCompatActivity {
}
return false;
}
public void onTimeStamp(View view) {
// 在这里编写按钮点击后要执行的代码
TimeStampUtil.getInstance(this).genTimeStamp();
String formattedDateTime = TimeStampUtil.getInstance(this).getTimeStampCopyString();
ClipboardUtil.copyTextToClipboard(this, formattedDateTime);
// 更新时间戳文本框显示内容
EditText etTimeStamp = findViewById(R.id.et_timestamp);
etTimeStamp.setText(formattedDateTime);
// 输出一个提示音
TimeStampUtil.getInstance(this).playNotifyMusic(this);
// 比如显示一个 Toast
Toast.makeText(this, "时间戳:\n" + TimeStampUtil.getInstance(this).getTimeStampCopyString() + "\n已拷贝到剪贴板。", Toast.LENGTH_SHORT).show();
MainService.updateCopiedTimeStamp();
}
}

View File

@@ -1,40 +0,0 @@
package cc.winboll.studio.timestamp.receivers;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.timestamp.MainService;
import cc.winboll.studio.timestamp.models.AppConfigsModel;
import cc.winboll.studio.timestamp.utils.AppConfigsUtil;
/**
* @Author ZhanGSKen&豆包大模型<zhangsken@188.com>
* @Date 2025/07/28 11:15
* @Describe MainReceiver
*/
public class MainReceiver extends BroadcastReceiver {
public static final String TAG = "MainReceiver";
static final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
AppConfigsUtil mAppConfigsUtil;
@Override
public void onReceive(Context context, Intent intent) {
String szAction = intent.getAction();
if (szAction.equals(ACTION_BOOT_COMPLETED)) {
AppConfigsModel appConfigs = AppConfigsUtil.getInstance(context).loadAppConfigs();
boolean isEnable = appConfigs.isEnableService();
AppConfigsUtil.getInstance(context).saveAppConfigs();
Intent intentMainService = new Intent(context, MainService.class);
if (isEnable) {
context.startService(intentMainService);
}
LogUtils.i(TAG, "System Boot And Start ManagerService Completed!");
}
}
}

View File

@@ -130,10 +130,16 @@ public class NotificationHelper {
mForegroundNotification.bigContentView = remoteViews;
service.startForeground(ID_MSG_SERVICE, mForegroundNotification);
TimeStampUtil.getInstance(service).playNotifyMusic(service);
// 播放默认短信铃声
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);
}

View File

@@ -6,8 +6,6 @@ package cc.winboll.studio.timestamp.utils;
* @Describe TimeStampUtil
*/
import android.content.Context;
import android.net.Uri;
import cc.winboll.studio.timestamp.R;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
@@ -57,19 +55,4 @@ public class TimeStampUtil {
String formattedDateTime = ldt.format(formatter);
return formattedDateTime;
}
//
// 播放时间戳确定时的提示音乐
//
public static void playNotifyMusic(Context context) {
// 播放默认短信铃声
//Uri defaultSmsRingtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
//AudioPlayerUriUtil.playAudio(context, defaultSmsRingtoneUri);
// 播放应用铃声
// 获取MP3文件的Uri
Uri soundUri = Uri.parse("android.resource://" + context.getPackageName() + "/" + R.raw.diweiyi);
AudioPlayerUriUtil.playAudio(context, soundUri);
}
}

View File

@@ -1,180 +1,144 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ScrollView
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<Switch
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="启用时间戳常驻通知栏"
android:id="@+id/activitymainSwitch1"
android:onClick="onSetMainServiceStatus"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Show Format Preview:"
android:paddingRight="10dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text"
android:id="@+id/tv_timestampformatstring"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<EditText
android:layout_width="0dp"
android:ems="10"
android:layout_height="wrap_content"
android:id="@+id/et_timestampformatstring"
android:layout_weight="1.0"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ApplyShow"
android:id="@+id/btn_saveformatstring"
android:textAllCaps="false"
android:onClick="onSaveFormatString"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Copy Format Preview:"
android:paddingRight="10dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text"
android:id="@+id/tv_timestampcopyformatstring"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<EditText
android:layout_width="0dp"
android:ems="10"
android:layout_height="wrap_content"
android:id="@+id/et_timestampcopyformatstring"
android:layout_weight="1.0"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ApplyCopy"
android:id="@+id/btn_savecopyformatstring"
android:textAllCaps="false"
android:onClick="onSaveCopyFormatString"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.0"
android:gravity="center_vertical|center_horizontal">
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.0">
<LinearLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
<cc.winboll.studio.libappbase.LogView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:id="@+id/logview"/>
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<Switch
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="启用时间戳常驻通知栏"
android:id="@+id/activitymainSwitch1"
android:onClick="onSetMainServiceStatus"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Show Format Preview:"
android:paddingRight="10dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text"
android:id="@+id/tv_timestampformatstring"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<EditText
android:layout_width="0dp"
android:ems="10"
android:layout_height="wrap_content"
android:id="@+id/et_timestampformatstring"
android:layout_weight="1.0"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ApplyShow"
android:id="@+id/btn_saveformatstring"
android:textAllCaps="false"
android:onClick="onSaveFormatString"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Copy Format Preview:"
android:paddingRight="10dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text"
android:id="@+id/tv_timestampcopyformatstring"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<EditText
android:layout_width="0dp"
android:ems="10"
android:layout_height="wrap_content"
android:id="@+id/et_timestampcopyformatstring"
android:layout_weight="1.0"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ApplyCopy"
android:id="@+id/btn_savecopyformatstring"
android:textAllCaps="false"
android:onClick="onSaveCopyFormatString"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="当前截取的时间戳为:"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal">
<ImageButton
android:layout_width="100dp"
android:layout_height="100dp"
android:onClick="onTimeStamp"
android:background="@drawable/ic_timestamp"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="match_parent"
android:ems="10"
android:layout_height="wrap_content"
android:id="@+id/et_timestamp"/>
</LinearLayout>
</LinearLayout>
</ScrollView>
<cc.winboll.studio.libappbase.LogView
android:layout_width="match_parent"
android:layout_height="200dp"
android:id="@+id/logview"/>
</LinearLayout>
</LinearLayout>