Compare commits

..

2 Commits

Author SHA1 Message Date
c1af20009a <aes>APK 15.9.4 release Publish. 2025-09-26 20:36:26 +08:00
ZhanGSKen
cb3796bfea 加入APPBase转移模块 2025-09-26 20:32:06 +08:00
25 changed files with 560 additions and 503 deletions

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Sun Aug 31 23:40:17 HKT 2025
stageCount=4
#Fri Sep 26 20:36:26 HKT 2025
stageCount=5
libraryProject=libaes
baseVersion=15.9
publishVersion=15.9.3
publishVersion=15.9.4
buildCount=0
baseBetaVersion=15.9.4
baseBetaVersion=15.9.5

View File

@@ -18,8 +18,8 @@ def genVersionName(def versionName){
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
compileSdkVersion 32
buildToolsVersion "32.0.0"
defaultConfig {
applicationId "cc.winboll.studio.contacts"
@@ -66,7 +66,7 @@ dependencies {
// 应用介绍页类库
api 'io.github.medyo:android-about-page:2.0.0'
// 吐司类库
//api 'com.github.getActivity:ToastUtils:10.5'
api 'com.github.getActivity:ToastUtils:10.5'
// 网络连接类库
api 'com.squareup.okhttp3:okhttp:4.4.1'

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Sat Oct 18 13:43:14 HKT 2025
stageCount=21
#Sun Aug 31 06:05:42 CST 2025
stageCount=17
libraryProject=
baseVersion=15.3
publishVersion=15.3.20
publishVersion=15.3.16
buildCount=0
baseBetaVersion=15.3.21
baseBetaVersion=15.3.17

View File

@@ -7,8 +7,8 @@ package cc.winboll.studio.contacts;
*/
import android.view.Gravity;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import cc.winboll.studio.libappbase.winboll.WinBoLLActivityManager;
import com.hjq.toast.ToastUtils;
public class App extends GlobalApplication {
@@ -30,7 +30,7 @@ public class App extends GlobalApplication {
// 设置 Toast 布局样式
//ToastUtils.setView(R.layout.toast_custom_view);
//ToastUtils.setStyle(new WhiteToastStyle());
//ToastUtils.setGravity(Gravity.BOTTOM, 0, 200);
ToastUtils.setGravity(Gravity.BOTTOM, 0, 200);
}

View File

@@ -8,7 +8,6 @@ package cc.winboll.studio.contacts;
import android.Manifest;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -32,8 +31,6 @@ import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;
import // 新增导入 AppGoToSettingsUtil 工具类确保包路径与项目实际一致
cc.winboll.studio.contacts.utils.AppGoToSettingsUtil;
import cc.winboll.studio.contacts.R;
import cc.winboll.studio.contacts.activities.SettingsActivity;
import cc.winboll.studio.contacts.beans.MainServiceBean;
@@ -51,9 +48,10 @@ import java.util.List;
final public class MainActivity extends AppCompatActivity implements IWinBoLLActivity, ViewPager.OnPageChangeListener, View.OnClickListener {
public static final String TAG = "MainActivity";
public static final int REQUEST_HOME_ACTIVITY = 0;
public static final int REQUEST_ABOUT_ACTIVITY = 1;
public static final int REQUEST_APP_SETTINGS = 2;
public static final String ACTION_SOS = "cc.winboll.studio.libappbase.WinBoLL.ACTION_SOS";
static MainActivity _MainActivity;
@@ -74,13 +72,6 @@ final public class MainActivity extends AppCompatActivity implements IWinBoLLAct
List<String> tabTitleList;
private static final int DIALER_REQUEST_CODE = 1;
private static final int REQUEST_REQUIRED_PERMISSIONS = 1002;
// 关键修改1新增 READ_CALL_LOG 权限到必需权限列表(解决通话记录读取崩溃)
private String[] REQUIRED_PERMISSIONS = new String[]{
Manifest.permission.READ_CONTACTS, // 通讯录读取(原)
Manifest.permission.CALL_PHONE, // 电话拨号(原)
Manifest.permission.READ_CALL_LOG // 通话记录读取(新增,核心修复)
};
@Override
@@ -97,86 +88,9 @@ final public class MainActivity extends AppCompatActivity implements IWinBoLLAct
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
_MainActivity = this;
// 优先检查所有必需权限(含新增的 READ_CALL_LOG
if (!checkAllRequiredPermissions()) {
requestAllRequiredPermissions();
} else {
initUIAndLogic(savedInstanceState);
}
}
// 权限检查方法(无需修改,自动包含新增的 READ_CALL_LOG
private boolean checkAllRequiredPermissions() {
for (String permission : REQUIRED_PERMISSIONS) {
if (ActivityCompat.checkSelfPermission(this, permission)
!= PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
// 权限申请方法(无需修改,自动申请新增的 READ_CALL_LOG
private void requestAllRequiredPermissions() {
ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_REQUIRED_PERMISSIONS);
}
// 权限结果回调(无需修改,确保所有权限(含 READ_CALL_LOG都通过才加载UI
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_REQUIRED_PERMISSIONS) {
boolean allPermissionsGranted = true;
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
allPermissionsGranted = false;
break;
}
}
if (allPermissionsGranted) {
initUIAndLogic(null);
} else {
// 关键修改2更新提示文案告知用户新增的“通话记录权限”
showPermissionDeniedDialogAndExit();
}
}
}
// 核心修改:新增“设置权限”按钮,点击调用 AppGoToSettingsUtil 跳转设置页
private void showPermissionDeniedDialogAndExit() {
new AlertDialog.Builder(this)
.setTitle("权限不足,无法使用")
// 文案修改:明确新增“通话记录读取”权限
.setMessage("应用需要「通讯录读取」、「电话」和「通话记录读取」权限才能正常运行,请授予权限后重新打开应用。")
.setCancelable(false)
// 新增:左侧“设置权限”按钮(先添加的按钮在左侧)
.setNegativeButton("设置权限", new AlertDialog.OnClickListener() {
@Override
public void onClick(android.content.DialogInterface dialog, int which) {
dialog.dismiss();
// 调用工具类跳转应用设置页(按需求实现)
AppGoToSettingsUtil appGoToSettingsUtil = new AppGoToSettingsUtil();
appGoToSettingsUtil.GoToSetting(MainActivity.this);
}
})
// 原有:右侧“确定退出”按钮(后添加的按钮在右侧)
.setPositiveButton("确定退出", new AlertDialog.OnClickListener() {
@Override
public void onClick(android.content.DialogInterface dialog, int which) {
dialog.dismiss();
finishAndRemoveTask();
}
})
.show();
}
// 初始化UI和逻辑无需修改权限通过后才加载 CallLogFragment
private void initUIAndLogic(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
// 初始化工具栏仅加载基础UI
mToolbar = (Toolbar) findViewById(R.id.activitymainToolbar1);
setSupportActionBar(mToolbar);
getSupportActionBar().setSubtitle(TAG);
@@ -184,28 +98,34 @@ final public class MainActivity extends AppCompatActivity implements IWinBoLLAct
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
viewPager = (ViewPager) findViewById(R.id.viewPager);
// 创建Fragment列表仅实例化不加载数据
fragmentList = new ArrayList<Fragment>();
tabTitleList = new ArrayList<String>();
// CallLogFragment 仅在权限通过后才实例化(避免提前触发读取)
fragmentList.add(CallLogFragment.newInstance(0));
fragmentList.add(ContactsFragment.newInstance(1));
fragmentList.add(ContactsFragment.newInstance(1)); // 延迟加载联系人数据
fragmentList.add(LogFragment.newInstance(2));
tabTitleList.add("通话记录");
tabTitleList.add("联系人");
tabTitleList.add("应用日志");
// 设置ViewPager适配器
MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager(), fragmentList, tabTitleList);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(0); // 关闭预加载,避免提前初始化 CallLogFragment
// 关键:关闭预加载,仅当前页初始化
viewPager.setOffscreenPageLimit(0);
// 关联TabLayout和ViewPager
tabLayout.setupWithViewPager(viewPager);
// 原有服务启动、电话监听等逻辑...
// 初始化服务状态(延迟启动非核心服务)
MainServiceBean mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
if (mMainServiceBean == null) {
mMainServiceBean = new MainServiceBean();
MainServiceBean.saveBean(this, mMainServiceBean);
}
if (mMainServiceBean.isEnable()) {
// 延迟1秒启动服务避免阻塞启动
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
@@ -214,14 +134,16 @@ final public class MainActivity extends AppCompatActivity implements IWinBoLLAct
}, 1000);
}
// 初始化电话状态监听(基础功能保留)
telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
phoneStateListener = new MyPhoneStateListener();
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
// 以下为原有代码(无需修改
// ViewPager适配器Java 7语法
private class MyPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> fragmentList;
private List<String> tabTitleList;
@@ -251,18 +173,21 @@ final public class MainActivity extends AppCompatActivity implements IWinBoLLAct
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(android.net.Uri.parse("tel:" + phoneNumber));
if (ActivityCompat.checkSelfPermission(_MainActivity, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(_MainActivity, "拨号权限不足", Toast.LENGTH_SHORT).show();
return;
}
_MainActivity.startActivity(intent);
}
// OnPageChangeListener接口实现
@Override
public void onPageScrollStateChanged(int state) {}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
@Override
public void onPageSelected(int position) {}
@Override
public void onClick(View v) {}
@@ -314,6 +239,9 @@ final public class MainActivity extends AppCompatActivity implements IWinBoLLAct
super.onResume();
}
/**
* 检查是否是系统默认电话应用
*/
public boolean isDefaultPhoneCallApp() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
TelecomManager manger = (TelecomManager) getSystemService(TELECOM_SERVICE);
@@ -344,9 +272,7 @@ final public class MainActivity extends AppCompatActivity implements IWinBoLLAct
Toast.makeText(MainActivity.this, getString(R.string.app_name) + " 已成为默认电话应用",
Toast.LENGTH_SHORT).show();
}
} else if (requestCode == REQUEST_APP_SETTINGS) {
recreate();
}
}
}
}

View File

@@ -36,8 +36,8 @@ import cc.winboll.studio.contacts.dun.Rules;
import cc.winboll.studio.contacts.services.MainService;
import cc.winboll.studio.contacts.views.DuInfoTextView;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity;
import com.hjq.toast.ToastUtils;
import java.lang.reflect.Field;
import java.util.List;

View File

@@ -23,7 +23,7 @@ import cc.winboll.studio.contacts.R;
import cc.winboll.studio.contacts.beans.CallLogModel;
import cc.winboll.studio.contacts.utils.ContactUtils;
import cc.winboll.studio.libaes.views.AOHPCTCSeekBar;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import com.hjq.toast.ToastUtils;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;
@@ -76,9 +76,6 @@ public class CallLogAdapter extends RecyclerView.Adapter<CallLogAdapter.CallLogV
// Set the clipboard's primary clip.
clipboard.setPrimaryClip(clip);
Toast.makeText(mContext, "Copy to clipboard.", Toast.LENGTH_SHORT).show();
} else if (nItemId == R.id.item_calllog_phonenumber_add_contact) {
//ToastUtils.show(callLog.getPhoneNumber());
ContactUtils.jumpToAddContact(mContext, callLog.getPhoneNumber());
}
return true;

View File

@@ -21,9 +21,8 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import cc.winboll.studio.contacts.R;
import cc.winboll.studio.contacts.beans.ContactModel;
import cc.winboll.studio.contacts.utils.ContactUtils;
import cc.winboll.studio.libaes.views.AOHPCTCSeekBar;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import com.hjq.toast.ToastUtils;
import java.util.List;
public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContactViewHolder> {
@@ -70,11 +69,6 @@ public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContactV
// Set the clipboard's primary clip.
clipboard.setPrimaryClip(clip);
Toast.makeText(mContext, "Copy to clipboard.", Toast.LENGTH_SHORT).show();
} else if (nItemId == R.id.item_calllog_phonenumber_edit_contact) {
//ToastUtils.show("Test");
Long nContactId = ContactUtils.getContactIdByPhone(mContext, contact.getNumber());
//ToastUtils.show(String.format("%d", nContactId));
ContactUtils.jumpToEditContact(mContext, contact.getNumber(), nContactId);
}
return true;
@@ -118,7 +112,7 @@ public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContactV
TextView contactName;
TextView contactNumber;
AOHPCTCSeekBar dialAOHPCTCSeekBar;
public ContactViewHolder(@NonNull View itemView) {
super(itemView);
llPhoneNumberMain = itemView.findViewById(R.id.itemcontactLinearLayout1);

View File

@@ -7,6 +7,7 @@ package cc.winboll.studio.contacts.adapters;
*/
import android.content.Context;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
@@ -20,8 +21,9 @@ import cc.winboll.studio.contacts.R;
import cc.winboll.studio.contacts.beans.PhoneConnectRuleModel;
import cc.winboll.studio.contacts.dun.Rules;
import cc.winboll.studio.contacts.views.LeftScrollView;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.dialogs.YesNoAlertDialog;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import com.hjq.toast.ToastUtils;
import java.util.ArrayList;
import java.util.List;

View File

@@ -9,7 +9,7 @@ import android.content.Context;
import cc.winboll.studio.contacts.R;
import cc.winboll.studio.contacts.dun.Rules;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import com.hjq.toast.ToastUtils;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;

View File

@@ -25,6 +25,7 @@ import androidx.recyclerview.widget.RecyclerView;
import cc.winboll.studio.contacts.R;
import cc.winboll.studio.contacts.adapters.CallLogAdapter;
import cc.winboll.studio.contacts.beans.CallLogModel;
import com.hjq.toast.ToastUtils;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -160,7 +161,7 @@ public class CallLogFragment extends Fragment {
_CallLogFragment.triggerUpdate();
}
}
@Override
public void onResume() {
super.onResume();

View File

@@ -31,7 +31,7 @@ import cc.winboll.studio.contacts.R;
import cc.winboll.studio.contacts.adapters.ContactAdapter;
import cc.winboll.studio.contacts.beans.ContactModel;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import com.hjq.toast.ToastUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
@@ -95,7 +95,7 @@ public class ContactsFragment extends Fragment {
recyclerView = (RecyclerView) view.findViewById(R.id.contacts_recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
contactList = new ArrayList<ContactModel>();
contactAdapter = new ContactAdapter(getActivity(), contactList);
contactAdapter = new ContactAdapter(getContext(), contactList);
recyclerView.setAdapter(contactAdapter);
// 初始隐藏列表,数据加载后显示
recyclerView.setVisibility(View.GONE);

View File

@@ -14,6 +14,7 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import cc.winboll.studio.contacts.R;
import cc.winboll.studio.libappbase.LogView;
import com.hjq.toast.ToastUtils;
public class LogFragment extends Fragment {

View File

@@ -10,7 +10,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import cc.winboll.studio.contacts.services.MainService;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import com.hjq.toast.ToastUtils;
import java.lang.ref.WeakReference;
public class MainReceiver extends BroadcastReceiver {

View File

@@ -1,270 +0,0 @@
package cc.winboll.studio.contacts.utils;
/**
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
* @Date 2025/09/27 14:27
* @Describe 调用应用属性设置页工具类
* 来源https://blog.csdn.net/zhuhai__yizhi/article/details/78737593
* Created by zyy on 2018/3/12.
* 直接跳转到权限后返回,可以监控权限授权情况,但是,跳转到应用详情页,无法监测权限情况
* 是否要加以区分若是应用详情页则跳转回来后onRestart检测所求权限如果授权则收回提示如果没授权则继续提示
*/
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import cc.winboll.studio.contacts.MainActivity;
public class AppGoToSettingsUtil {
public static final String TAG = "AppGoToSettingsUtil";
public static final int ACTIVITY_RESULT_APP_SETTINGS = MainActivity.REQUEST_APP_SETTINGS;
/**
* Build.MANUFACTURER判断各大手机厂商品牌
*/
private static final String MANUFACTURER_HUAWEI = "Huawei";//华为
private static final String MANUFACTURER_MEIZU = "Meizu";//魅族
private static final String MANUFACTURER_XIAOMI = "Xiaomi";//小米
private static final String MANUFACTURER_SONY = "Sony";//索尼
private static final String MANUFACTURER_OPPO = "OPPO";
private static final String MANUFACTURER_LG = "LG";
private static final String MANUFACTURER_VIVO = "vivo";
private static final String MANUFACTURER_SAMSUNG = "samsung";//三星
private static final String MANUFACTURER_LETV = "Letv";//乐视
private static final String MANUFACTURER_ZTE = "ZTE";//中兴
private static final String MANUFACTURER_YULONG = "YuLong";//酷派
private static final String MANUFACTURER_LENOVO = "LENOVO";//联想
public static boolean isAppSettingOpen=false;
/**
* 跳转到相应品牌手机系统权限设置页,如果跳转不成功,则跳转到应用详情页
* 这里需要改造成返回true或者false应用详情页:true应用权限页:false
* @param activity
*/
public static void GoToSetting(Activity activity) {
switch (Build.MANUFACTURER) {
case MANUFACTURER_HUAWEI://华为
Huawei(activity);
break;
case MANUFACTURER_MEIZU://魅族
Meizu(activity);
break;
case MANUFACTURER_XIAOMI://小米
Xiaomi(activity);
break;
case MANUFACTURER_SONY://索尼
Sony(activity);
break;
case MANUFACTURER_OPPO://oppo
OPPO(activity);
break;
case MANUFACTURER_LG://lg
LG(activity);
break;
case MANUFACTURER_LETV://乐视
Letv(activity);
break;
default://其他
try {//防止应用详情页也找不到,捕获异常后跳转到设置,这里跳转最好是两级,太多用户也会觉得麻烦,还不如不跳
openAppDetailSetting(activity);
//activity.startActivityForResult(getAppDetailSettingIntent(activity), PERMISSION_SETTING_FOR_RESULT);
} catch (Exception e) {
SystemConfig(activity);
}
break;
}
}
/**
* 华为跳转权限设置页
* @param activity
*/
public static void Huawei(Activity activity) {
try {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("packageName", activity.getPackageName());
ComponentName comp = new ComponentName("com.huawei.systemmanager", "com.huawei.permissionmanager.ui.MainActivity");
intent.setComponent(comp);
activity.startActivityForResult(intent, ACTIVITY_RESULT_APP_SETTINGS);
isAppSettingOpen = false;
} catch (Exception e) {
openAppDetailSetting(activity);
//activity.startActivityForResult(getAppDetailSettingIntent(activity), PERMISSION_SETTING_FOR_RESULT);
}
}
/**
* 魅族跳转权限设置页,测试时,点击无反应,具体原因不明
* @param activity
*/
public static void Meizu(Activity activity) {
try {
Intent intent = new Intent("com.meizu.safe.security.SHOW_APPSEC");
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.putExtra("packageName", activity.getPackageName());
activity.startActivity(intent);
isAppSettingOpen = false;
} catch (Exception e) {
openAppDetailSetting(activity);
//activity.startActivityForResult(getAppDetailSettingIntent(activity), PERMISSION_SETTING_FOR_RESULT);
}
}
/**
* 小米,功能正常
* @param activity
*/
public static void Xiaomi(Activity activity) {
try { //MIUI 8 9
Intent localIntent = new Intent("miui.intent.action.APP_PERM_EDITOR");
localIntent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
localIntent.putExtra("extra_pkgname", activity.getPackageName());
activity.startActivityForResult(localIntent, ACTIVITY_RESULT_APP_SETTINGS);
isAppSettingOpen = false;
//activity.startActivity(localIntent);
} catch (Exception e) {
try { //MIUI 5/6/7
Intent localIntent = new Intent("miui.intent.action.APP_PERM_EDITOR");
localIntent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
localIntent.putExtra("extra_pkgname", activity.getPackageName());
activity.startActivityForResult(localIntent, ACTIVITY_RESULT_APP_SETTINGS);
isAppSettingOpen = false;
//activity.startActivity(localIntent);
} catch (Exception e1) { //否则跳转到应用详情
openAppDetailSetting(activity);
//activity.startActivityForResult(getAppDetailSettingIntent(activity), PERMISSION_SETTING_FOR_RESULT);
//这里有个问题,进入活动后需要再跳一级活动,就检测不到返回结果
//activity.startActivity(getAppDetailSettingIntent());
}
}
}
/**
* 索尼6.0以上的手机非常少,基本没看见
* @param activity
*/
public static void Sony(Activity activity) {
try {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("packageName", activity.getPackageName());
ComponentName comp = new ComponentName("com.sonymobile.cta", "com.sonymobile.cta.SomcCTAMainActivity");
intent.setComponent(comp);
activity.startActivity(intent);
isAppSettingOpen = false;
} catch (Exception e) {
openAppDetailSetting(activity);
//activity.startActivityForResult(getAppDetailSettingIntent(activity), PERMISSION_SETTING_FOR_RESULT);
}
}
/**
* OPPO
* @param activity
*/
public static void OPPO(Activity activity) {
try {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("packageName", activity.getPackageName());
ComponentName comp = new ComponentName("com.color.safecenter", "com.color.safecenter.permission.PermissionManagerActivity");
intent.setComponent(comp);
activity.startActivity(intent);
isAppSettingOpen = false;
} catch (Exception e) {
openAppDetailSetting(activity);
//activity.startActivityForResult(getAppDetailSettingIntent(activity), PERMISSION_SETTING_FOR_RESULT);
}
}
/**
* LG经过测试正常使用
* @param activity
*/
public static void LG(Activity activity) {
try {
Intent intent = new Intent("android.intent.action.MAIN");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("packageName", activity.getPackageName());
ComponentName comp = new ComponentName("com.android.settings", "com.android.settings.Settings$AccessLockSummaryActivity");
intent.setComponent(comp);
activity.startActivity(intent);
isAppSettingOpen = false;
} catch (Exception e) {
openAppDetailSetting(activity);
//activity.startActivityForResult(getAppDetailSettingIntent(activity), PERMISSION_SETTING_FOR_RESULT);
}
}
/**
* 乐视6.0以上很少,基本都可以忽略了,现在乐视手机不多
* @param activity
*/
public static void Letv(Activity activity) {
try {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("packageName", activity.getPackageName());
ComponentName comp = new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.PermissionAndApps");
intent.setComponent(comp);
activity.startActivity(intent);
isAppSettingOpen = false;
} catch (Exception e) {
openAppDetailSetting(activity);
//activity.startActivityForResult(getAppDetailSettingIntent(activity), PERMISSION_SETTING_FOR_RESULT);
}
}
/**
* 只能打开到自带安全软件
* @param activity
*/
public static void _360(Activity activity) {
try {
Intent intent = new Intent("android.intent.action.MAIN");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("packageName", activity.getPackageName());
ComponentName comp = new ComponentName("com.qihoo360.mobilesafe", "com.qihoo360.mobilesafe.ui.index.AppEnterActivity");
intent.setComponent(comp);
activity.startActivity(intent);
} catch (Exception e) {
openAppDetailSetting(activity);
//activity.startActivityForResult(getAppDetailSettingIntent(activity), PERMISSION_SETTING_FOR_RESULT);
}
}
/**
* 系统设置界面
* @param activity
*/
public static void SystemConfig(Activity activity) {
Intent intent = new Intent(Settings.ACTION_SETTINGS);
activity.startActivity(intent);
}
/**
* 获取应用详情页面
* @return
*/
private static Intent getAppDetailSettingIntent(Activity activity) {
Intent localIntent = new Intent();
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//if (Build.VERSION.SDK_INT >= 9) {
localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
localIntent.setData(Uri.fromParts("package", activity.getPackageName(), null));
/*} else if (Build.VERSION.SDK_INT <= 8) {
localIntent.setAction(Intent.ACTION_VIEW);
localIntent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
localIntent.putExtra("com.android.settings.ApplicationPkgName", activity.getPackageName());
}*/
return localIntent;
}
public static void openAppDetailSetting(Activity activity) {
activity.startActivityForResult(getAppDetailSettingIntent(activity), ACTIVITY_RESULT_APP_SETTINGS);
isAppSettingOpen = true;
}
}

View File

@@ -6,14 +6,10 @@ package cc.winboll.studio.contacts.utils;
* @Describe 联系人工具集
*/
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import java.util.HashMap;
import java.util.Map;
@@ -124,92 +120,4 @@ public class ContactUtils {
}
return sbSpaceNumber.toString();
}
/**
* 跳转至系统添加联系人界面的工具函数
* @param context 上下文(如 PhoneCallService、Activity、Fragment 均可,需传入有效上下文)
* @param phoneNumber 可选参数:预填的联系人电话(传 null 则跳转空表单)
*/
public static void jumpToAddContact(Context mContext, String phoneNumber) {
Intent intent = new Intent(Intent.ACTION_INSERT);
intent.setType("vnd.android.cursor.dir/person");
intent.putExtra(android.provider.ContactsContract.Intents.Insert.PHONE, phoneNumber);
mContext.startActivity(intent);
}
/**
* 跳转至系统编辑联系人界面(适配小米等定制机型)
* @param context 上下文Activity/Service/Fragment
* @param phoneNumber 待编辑联系人的电话号码(用于匹配已有联系人,必传)
* @param contactId 可选已有联系人的ID通过 ContactsContract 获取传null则自动匹配号码
*/
public static void jumpToEditContact(Context context, String phoneNumber, Long contactId) {
Intent intent = new Intent(Intent.ACTION_EDIT);
// 关键:小米等机型需明确设置数据类型为“单个联系人”,避免参数丢失
intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
// 场景A已知联系人ID精准定位优先用此方式参数传递最稳定
if (contactId != null && contactId > 0) {
// 构建联系人的Uri格式content://contacts/people/[contactId],系统标准格式)
Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
intent.setData(contactUri);
//ToastUtils.show("1");
} else if (phoneNumber != null && !phoneNumber.isEmpty()) {
// 方式1小米等机型兼容的“通过号码定位联系人”参数部分系统认此参数
//intent.putExtra(ContactsContract.Intents.Insert.PHONE_NUMBER, phoneNumber);
// 方式2补充系统标准的“数据Uri”强化匹配避免参数被定制系统忽略
Uri phoneUri = Uri.withAppendedPath(ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
intent.setData(phoneUri);
} else {
LogUtils.d(TAG, "编辑联系人失败电话号码和联系人ID均为空");
return;
}
// 可选:预填最新号码(覆盖原有号码,若用户修改了号码,编辑时自动更新)
if (phoneNumber != null && !phoneNumber.isEmpty()) {
intent.putExtra(ContactsContract.CommonDataKinds.Phone.NUMBER, phoneNumber);
intent.putExtra(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);
}
// 启动活动(加防护,避免无联系人应用崩溃)
// 小米机型在Service/非Activity中调用需加NEW_TASK标志否则可能无法启动
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
/**
* 通过电话号码查询联系人ID适配小米机型解决编辑时匹配不稳定问题
* @param context 上下文
* @param phoneNumber 待查询的电话号码
* @return 联系人ID无匹配时返回-1
*/
public static Long getContactIdByPhone(Context context, String phoneNumber) {
if (phoneNumber == null || phoneNumber.isEmpty()) {
return -1L;
}
ContentResolver cr = context.getContentResolver();
// 1. 构建电话查询Uri系统标准通过号码过滤联系人数据
Uri queryUri = Uri.withAppendedPath(ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
// 2. 只查询“联系人ID”字段高效避免冗余数据
String[] projection = {ContactsContract.CommonDataKinds.Phone.CONTACT_ID};
Cursor cursor = null;
try {
cursor = cr.query(queryUri, projection, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
// 3. 读取联系人ID返回Long类型避免int溢出
return cursor.getLong(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
}
} catch (Exception e) {
LogUtils.d(TAG, "查询联系人ID失败。" + e);
} finally {
if (cursor != null) {
cursor.close(); // 关闭游标,避免内存泄漏
}
}
return -1L; // 无匹配联系人
}
}

View File

@@ -13,8 +13,9 @@ import android.content.Context;
import android.content.Intent;
import android.widget.RemoteViews;
import cc.winboll.studio.contacts.R;
import cc.winboll.studio.contacts.threads.MainServiceThread;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import com.hjq.toast.ToastUtils;
public class APPStatusWidget extends AppWidgetProvider {

View File

@@ -5,8 +5,5 @@
<item
android:id="@+id/item_calllog_phonenumber_copy"
android:title="Copy"/>
<item
android:id="@+id/item_calllog_phonenumber_add_contact"
android:title="Add Contact"/>
</menu>

View File

@@ -5,8 +5,5 @@
<item
android:id="@+id/item_contact_phonenumber_copy"
android:title="Copy"/>
<item
android:id="@+id/item_calllog_phonenumber_edit_contact"
android:title="Edit Contact"/>
</menu>

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Sun Aug 31 05:00:43 CST 2025
stageCount=4
#Fri Sep 26 20:36:26 HKT 2025
stageCount=5
libraryProject=libaes
baseVersion=15.9
publishVersion=15.9.3
publishVersion=15.9.4
buildCount=0
baseBetaVersion=15.9.4
baseBetaVersion=15.9.5

View File

@@ -0,0 +1,60 @@
package cc.winboll.studio.libaes.dialogs;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
* @Date 2025/03/28 17:40:47
* @Date 2024/08/12 14:46:25
* @Describe 询问用户确定与否的选择框
*/
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
public class YesNoAlertDialog {
public static final String TAG = "YesNoAlertDialog";
public static void show(Context context, String szTitle, String szMessage, final OnDialogResultListener listener) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
context);
// set title
alertDialogBuilder.setTitle(szTitle);
// set dialog message
alertDialogBuilder
.setMessage(szMessage)
.setCancelable(true)
.setOnCancelListener(new DialogInterface.OnCancelListener(){
@Override
public void onCancel(DialogInterface dialog) {
listener.onNo();
}
})
.setPositiveButton("YES", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// if this button is clicked, close
// current activity
listener.onYes();
}
})
.setNegativeButton("NO", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// if this button is clicked, just close
// the dialog box and do nothing
dialog.cancel();
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
public interface OnDialogResultListener {
abstract void onYes();
abstract void onNo();
}
}

View File

@@ -0,0 +1,17 @@
package cc.winboll.studio.libaes.winboll;
import android.app.Activity;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
* @Date 2025/05/10 09:34
* @Describe WinBoLL 窗口操作接口
*/
public abstract interface IWinBoLLActivity {
public static final String TAG = "IWinBoLLActivity";
public static final String ACTION_BIND = IWinBoLLActivity.class.getName() + ".ACTION_BIND";
public Activity getActivity();
public String getTag();
}

View File

@@ -0,0 +1,98 @@
package cc.winboll.studio.libaes.winboll;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
* @Date 2025/03/25 04:29:19
*/
import android.app.Activity;
import android.app.Application;
import android.content.Intent;
import android.os.Bundle;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.utils.ToastUtils;
public class MyActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
public static final String TAG = "MyActivityLifecycleCallbacks";
public String mInfo = "";
public MyActivityLifecycleCallbacks() {
}
void createActivityeInfo(Activity activity) {
StringBuilder sb = new StringBuilder();
Intent receivedIntent = activity.getIntent();
sb.append("\nCallingActivity : \n");
if (activity.getCallingActivity() != null) {
sb.append(activity.getCallingActivity().getPackageName());
}
sb.append("\nReceived Intent Package : \n");
sb.append(receivedIntent.getPackage());
Bundle extras = receivedIntent.getExtras();
if (extras != null) {
for (String key : extras.keySet()) {
sb.append("\nIntentInfo");
sb.append("\n键: ");
sb.append(key);
sb.append(", 值: ");
sb.append(extras.get(key));
//Log.d("IntentInfo", "键: " + key + ", 值: " + extras.get(key));
}
}
mInfo = sb.toString();
//Log.d("IntentInfo", "发送Intent的应用包名: " + senderPackage);
}
public void showActivityeInfo() {
//ToastUtils.show("ActivityeInfo : " + mInfo);
LogUtils.d(TAG, "ActivityeInfo : " + mInfo);
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
// 在这里可以做一些初始化相关的操作例如记录Activity的创建时间等
//System.out.println(activity.getLocalClassName() + " was created");
LogUtils.d(TAG, activity.getLocalClassName() + " was created");
createActivityeInfo(activity);
}
@Override
public void onActivityStarted(Activity activity) {
//System.out.println(activity.getLocalClassName() + " was started");
LogUtils.d(TAG, activity.getLocalClassName() + " was started");
//createActivityeInfo(activity);
}
@Override
public void onActivityResumed(Activity activity) {
//System.out.println(activity.getLocalClassName() + " was resumed");
LogUtils.d(TAG, activity.getLocalClassName() + " was resumed");
//createActivityeInfo(activity);
}
@Override
public void onActivityPaused(Activity activity) {
//System.out.println(activity.getLocalClassName() + " was paused");
LogUtils.d(TAG, activity.getLocalClassName() + " was paused");
}
@Override
public void onActivityStopped(Activity activity) {
//System.out.println(activity.getLocalClassName() + " was stopped");
LogUtils.d(TAG, activity.getLocalClassName() + " was stopped");
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
// 可以在这里添加保存状态的自定义逻辑
}
@Override
public void onActivityDestroyed(Activity activity) {
//System.out.println(activity.getLocalClassName() + " was destroyed");
LogUtils.d(TAG, activity.getLocalClassName() + " was destroyed");
}
}

View File

@@ -0,0 +1,40 @@
package cc.winboll.studio.libaes.winboll;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
* @Date 2025/05/10 10:13
* @Describe WinBoLL 系列应用通用管理类
*/
import android.content.Context;
import android.content.Intent;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.models.WinBoLLModel;
public class WinBoLL {
public static final String TAG = "WinBoLL";
public static final String ACTION_BIND = WinBoLL.class.getName() + ".ACTION_BIND";
public static final String EXTRA_WINBOLLMODEL = "EXTRA_WINBOLLMODEL";
public static void bindToAPPBase(Context context, String appMainService) {
LogUtils.d(TAG, "bindToAPPBase(...)");
String toPackage = "cc.winboll.studio.appbase";
startBind(context, toPackage, appMainService);
}
public static void bindToAPPBaseBeta(Context context, String appMainService) {
LogUtils.d(TAG, "bindToAPPBaseBeta(...)");
String toPackage = "cc.winboll.studio.appbase.beta";
startBind(context, toPackage, appMainService);
}
static void startBind(Context context, String toPackage, String appMainService) {
Intent intent = new Intent(ACTION_BIND);
intent.putExtra(EXTRA_WINBOLLMODEL, (new WinBoLLModel(toPackage, appMainService)).toString());
intent.setPackage(toPackage);
LogUtils.d(TAG, String.format("ACTION_BIND :\nTo Package : %s\nAPP Main Service : %s", toPackage, appMainService));
context.sendBroadcast(intent);
}
}

View File

@@ -0,0 +1,288 @@
package cc.winboll.studio.libaes.winboll;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
* @Date 2025/05/10 10:02
* @Describe 应用活动窗口管理器
* 参考
* android 类似微信小程序多任务窗口 及 设置 TaskDescription 修改 icon 和 label
* https://blog.csdn.net/qq_29364417/article/details/109379915?app_version=6.4.2&code=app_1562916241&csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22109379915%22%2C%22source%22%3A%22weixin_38986226%22%7D&uLinkId=usr1mkqgl919blen&utm_source=app
*/
import android.app.Activity;
import android.app.ActivityManager;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import cc.winboll.studio.libappbase.winboll.LogActivity;
public class WinBoLLActivityManager {
public static final String TAG = "WinBoLLActivityManager";
public static final String EXTRA_TAG = "EXTRA_TAG";
public enum WinBoLLUI_TYPE { Aplication, Service }
Context mContext;
volatile static WinBoLLActivityManager _mIWinBoLLActivityManager;
Map<String, IWinBoLLActivity> mActivityListMap;
volatile static WinBoLLUI_TYPE _WinBoLLUI_TYPE = WinBoLLUI_TYPE.Service;
public static void setWinBoLLUI_TYPE(WinBoLLUI_TYPE winBoLLUI_TYPE) {
_WinBoLLUI_TYPE = winBoLLUI_TYPE;
}
public static WinBoLLUI_TYPE getWinBoLLUI_TYPE() {
return _WinBoLLUI_TYPE;
}
WinBoLLActivityManager() {
mContext = GlobalApplication.getInstance();
mActivityListMap = new HashMap<String, IWinBoLLActivity>();
}
public static synchronized WinBoLLActivityManager getInstance() {
if (_mIWinBoLLActivityManager == null) {
_mIWinBoLLActivityManager = new WinBoLLActivityManager();
}
return _mIWinBoLLActivityManager;
}
/**
* 把Activity添加到管理中
*/
public <T extends IWinBoLLActivity> void add(T activity) {
if (isActivityActive(activity.getTag())) {
LogUtils.d(TAG, String.format("add(...) %s is active.", activity.getTag()));
} else {
mActivityListMap.put(activity.getTag(), activity);
LogUtils.d(TAG, String.format("Add activity : %s\n_mapActivityList.size() : %d", activity.getTag(), mActivityListMap.size()));
}
}
//
// activity: 为 null 时,
// intent.putExtra 函数 "tag" 参数为 tag
// activity: 不为 null 时,
// intent.putExtra 函数 "tag" 参数为 activity.getTag()
//
public <T extends IWinBoLLActivity> void startWinBoLLActivity(Context context, Class<T> clazz) {
// 如果窗口已存在就重启窗口
if (!resumeActivity(clazz)) {
// 新建一个任务窗口
Intent intent = new Intent(context, clazz);
//打开多任务窗口 flags
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
//intent.putExtra("tag", tag);
context.startActivity(intent);
}
}
public <T extends IWinBoLLActivity> void startWinBoLLActivity(Context context, Intent intent, Class<T> clazz) {
// 如果窗口已存在就重启窗口
if (!resumeActivity(clazz)) {
// 新建一个任务窗口
//Intent intent = new Intent(context, clazz);
//打开多任务窗口 flags
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
//intent.putExtra("tag", tag);
context.startActivity(intent);
}
}
public <T extends IWinBoLLActivity> void startLogActivity(Context context) {
// 如果窗口已存在就重启窗口
//if (!resumeActivity(LogActivity.class)) {
// 新建一个任务窗口
Intent intent = new Intent(context, LogActivity.class);
//打开多任务窗口 flags
// Define the bounds.
// Rect bounds = new Rect(0, 0, 800, 200);
// // Set the bounds as an activity option.
// ActivityOptions options = ActivityOptions.makeBasic();
// options.setLaunchBounds(bounds);
intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
//intent.putExtra(EXTRA_TAG, tag);
//context.startActivity(intent, options.toBundle());
context.startActivity(intent);
//}
}
//
// 判断 tag 绑定的 Activity 是否已经创建
//
public boolean isActivityActive(String tag) {
return mActivityListMap.get(tag) != null;
}
Activity getActivityByTag(String tag) {
return (mActivityListMap.get(tag) == null) ?null: mActivityListMap.get(tag).getActivity();
}
//
// 找到tag 绑定的 BaseActivity ,通过 getTaskId() 移动到前台
//
public <T extends IWinBoLLActivity> boolean resumeActivity(Class<T> clazz) {
try {
Activity activity = getActivityByTag(clazz.newInstance().getTag());
if (activity != null) {
return resumeActivity(activity);
}
} catch (InstantiationException | IllegalAccessException e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
return false;
}
//
// 找到tag 绑定的 BaseActivity ,通过 getTaskId() 移动到前台
//
public <T extends IWinBoLLActivity> boolean resumeActivity(String tag) {
Activity activity = getActivityByTag(tag);
if (activity != null) {
return resumeActivity(activity);
}
return false;
}
//
// 找到tag 绑定的 BaseActivity ,通过 getTaskId() 移动到前台
//
public <T extends IWinBoLLActivity> boolean resumeActivity(Activity activity) {
ActivityManager am = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
//返回启动它的根任务home 或者 MainActivity
//Intent intent = new Intent(mContext, activity.getClass());
//TaskStackBuilder stackBuilder = TaskStackBuilder.create(mContext);
//stackBuilder.addNextIntentWithParentStack(intent);
//stackBuilder.startActivities();
am.moveTaskToFront(activity.getTaskId(), ActivityManager.MOVE_TASK_NO_USER_ACTION);
//ToastUtils.show("resumeActivity");
return true;
}
/**
* 结束所有 Activity
*/
public void finishAll() {
try {
//ToastUtils.show(String.format("finishAll() size : %d", _mIWinBoLLActivityList.size()));
for (int i = mActivityListMap.size() - 1; i > -1; i--) {
IWinBoLLActivity iWinBoLLActivity = mActivityListMap.get(i);
ToastUtils.show("finishAll() activity");
if (iWinBoLLActivity != null && iWinBoLLActivity.getActivity() != null && !iWinBoLLActivity.getActivity().isFinishing() && !iWinBoLLActivity.getActivity().isDestroyed()) {
//ToastUtils.show("activity != null ...");
if (WinBoLLActivityManager.getInstance().getWinBoLLUI_TYPE() == WinBoLLUI_TYPE.Service) {
// 结束窗口和最近任务栏, 建议前台服务类应用使用,可以方便用户再次调用 UI 操作。
iWinBoLLActivity.getActivity().finishAndRemoveTask();
//ToastUtils.show("finishAll() activity.finishAndRemoveTask();");
} else if (WinBoLLActivityManager.getInstance().getWinBoLLUI_TYPE() == WinBoLLUI_TYPE.Aplication) {
// 结束窗口保留最近任务栏,建议前台服务类应用使用,可以保持应用的系统自觉性。
iWinBoLLActivity.getActivity().finish();
//ToastUtils.show("finishAll() activity.finish();");
} else {
ToastUtils.show("WinBollApplication.WinBollUI_TYPE error.");
}
}
}
} catch (Exception e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
}
/**
* 结束指定Activity
*/
public <T extends IWinBoLLActivity> void finish(T iWinBoLLActivity) {
try {
if (iWinBoLLActivity != null && iWinBoLLActivity.getActivity() != null && !iWinBoLLActivity.getActivity().isFinishing() && !iWinBoLLActivity.getActivity().isDestroyed()) {
//根据tag 移除 MyActivity
//String tag= activity.getTag();
//_mIWinBoLLActivityList.remove(tag);
//ToastUtils.show("remove");
//ToastUtils.show("_mIWinBoLLActivityArrayMap.size() " + Integer.toString(_mIWinBoLLActivityArrayMap.size()));
// 窗口回调规则:
// [] 当前窗口位置 >> 调度出的窗口位置
// ★:[0] 1 2 3 4 >> 1
// ★0 1 [2] 3 4 >> 1
// ★0 1 2 [3] 4 >> 2
// ★0 1 2 3 [4] >> 3
// ★:[0] >> 直接关闭当前窗口
Activity preActivity = getPreActivity(iWinBoLLActivity);
iWinBoLLActivity.getActivity().finish();
if (preActivity != null) {
resumeActivity(preActivity);
}
}
} catch (Exception e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
}
Activity getPreActivity(IWinBoLLActivity iWinBoLLActivity) {
try {
boolean bingo = false;
IWinBoLLActivity preIWinBoLLActivity = null;
for (Map.Entry<String, IWinBoLLActivity> entity : mActivityListMap.entrySet()) {
if (entity.getKey().equals(iWinBoLLActivity.getTag())) {
bingo = true;
LogUtils.d(TAG, "bingo");
break;
}
preIWinBoLLActivity = entity.getValue();
}
if (bingo) {
return preIWinBoLLActivity.getActivity();
}
} catch (Exception e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
return null;
}
public <T extends IWinBoLLActivity> boolean registeRemove(T iWinBoLLActivity) {
IWinBoLLActivity iWinBoLLActivityTest = mActivityListMap.get(iWinBoLLActivity.getTag());
if (iWinBoLLActivityTest != null) {
mActivityListMap.remove(iWinBoLLActivity.getTag());
return true;
}
return false;
}
public void printAvtivityListInfo() {
if (!mActivityListMap.isEmpty()) {
StringBuilder sb = new StringBuilder("Map entries : " + Integer.toString(mActivityListMap.size()));
Iterator<Map.Entry<String, IWinBoLLActivity>> iterator = mActivityListMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, IWinBoLLActivity> entry = iterator.next();
sb.append("\nKey: " + entry.getKey() + ", \nValue: " + entry.getValue().getTag());
//ToastUtils.show("\nKey: " + entry.getKey() + ", Value: " + entry.getValue().getTag());
}
sb.append("\nMap entries end.");
LogUtils.d(TAG, sb.toString());
} else {
LogUtils.d(TAG, "The map is empty.");
}
}
}