移植来自APPUtils的模块,命名空间重构。
This commit is contained in:
		@@ -13,6 +13,12 @@
 | 
			
		||||
 | 
			
		||||
        <activity android:name="cc.winboll.studio.libaes.unittests.TestASupportToolbarActivity"/>
 | 
			
		||||
 | 
			
		||||
        <service android:name="cc.winboll.studio.libaes.winboll.WinBollClientService"/>
 | 
			
		||||
 | 
			
		||||
        <service android:name="cc.winboll.studio.libaes.winboll.AssistantService"/>
 | 
			
		||||
 | 
			
		||||
        <service android:name="cc.winboll.studio.libaes.winboll.WinBollMail"/>
 | 
			
		||||
 | 
			
		||||
    </application>
 | 
			
		||||
 | 
			
		||||
</manifest>
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@ import android.view.View;
 | 
			
		||||
import android.widget.AdapterView;
 | 
			
		||||
import androidx.appcompat.app.ActionBarDrawerToggle;
 | 
			
		||||
import androidx.appcompat.app.AppCompatActivity;
 | 
			
		||||
import androidx.appcompat.widget.Toolbar;
 | 
			
		||||
import androidx.drawerlayout.widget.DrawerLayout;
 | 
			
		||||
import androidx.fragment.app.Fragment;
 | 
			
		||||
import androidx.fragment.app.FragmentManager;
 | 
			
		||||
@@ -27,10 +28,9 @@ import cc.winboll.studio.libaes.beans.DrawerMenuBean;
 | 
			
		||||
import cc.winboll.studio.libaes.utils.AESThemeUtil;
 | 
			
		||||
import cc.winboll.studio.libaes.views.ADrawerMenuListView;
 | 
			
		||||
import cc.winboll.studio.libappbase.LogUtils;
 | 
			
		||||
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
 | 
			
		||||
import com.baoyz.widget.PullRefreshLayout;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import cc.winboll.studio.libaes.winboll.IWinBollActivity;
 | 
			
		||||
import androidx.appcompat.widget.Toolbar;
 | 
			
		||||
 | 
			
		||||
public abstract class DrawerFragmentActivity extends AppCompatActivity implements IWinBollActivity,AdapterView.OnItemClickListener {
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,13 @@
 | 
			
		||||
package cc.winboll.studio.libaes.unittests;
 | 
			
		||||
 | 
			
		||||
import android.app.Activity;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.view.Menu;
 | 
			
		||||
import android.view.MenuItem;
 | 
			
		||||
import android.widget.Toast;
 | 
			
		||||
import android.widget.Toolbar;
 | 
			
		||||
import androidx.appcompat.app.AppCompatActivity;
 | 
			
		||||
import cc.winboll.studio.libaes.R;
 | 
			
		||||
import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity;
 | 
			
		||||
import cc.winboll.studio.libaes.winboll.APPInfo;
 | 
			
		||||
import cc.winboll.studio.libaes.winboll.IWinBollActivity;
 | 
			
		||||
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @Author ZhanGSKen@QQ.COM
 | 
			
		||||
@@ -23,7 +21,7 @@ public class SecondaryLibraryActivity extends DrawerFragmentActivity implements
 | 
			
		||||
    SecondaryLibraryFragment mSecondaryLibraryFragment;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public AppCompatActivity getActivity() {
 | 
			
		||||
    public Activity getActivity() {
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -32,21 +30,6 @@ public class SecondaryLibraryActivity extends DrawerFragmentActivity implements
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Toolbar initToolBar() {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean isAddWinBollToolBar() {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean isEnableDisplayHomeAsUp() {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void onCreate(Bundle savedInstanceState) {
 | 
			
		||||
        super.onCreate(savedInstanceState);
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ import androidx.fragment.app.Fragment;
 | 
			
		||||
import cc.winboll.studio.libaes.R;
 | 
			
		||||
import cc.winboll.studio.libaes.views.AButton;
 | 
			
		||||
import cc.winboll.studio.libappbase.LogUtils;
 | 
			
		||||
import cc.winboll.studio.libappbase.utils.ToastUtils;
 | 
			
		||||
import com.hjq.toast.ToastUtils;
 | 
			
		||||
 | 
			
		||||
public class TestAButtonFragment extends Fragment {
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,19 +5,27 @@ package cc.winboll.studio.libaes.unittests;
 | 
			
		||||
 * @Date 2024/07/16 01:14:00
 | 
			
		||||
 * @Describe TestASupportToolbarActivity
 | 
			
		||||
 */
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.SharedPreferences;
 | 
			
		||||
import android.app.Activity;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import androidx.appcompat.app.AppCompatActivity;
 | 
			
		||||
import androidx.appcompat.widget.Toolbar;
 | 
			
		||||
import cc.winboll.studio.libaes.R;
 | 
			
		||||
import cc.winboll.studio.libaes.beans.AESThemeBean;
 | 
			
		||||
import cc.winboll.studio.libaes.utils.AESThemeUtil;
 | 
			
		||||
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
 | 
			
		||||
 | 
			
		||||
public class TestASupportToolbarActivity extends AppCompatActivity {
 | 
			
		||||
public class TestASupportToolbarActivity extends AppCompatActivity implements IWinBollActivity  {
 | 
			
		||||
 | 
			
		||||
    public static final String TAG = "TestASupportToolbarActivity";
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Activity getActivity() {
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getTag() {
 | 
			
		||||
        return TAG;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void onCreate(Bundle savedInstanceState) {
 | 
			
		||||
 
 | 
			
		||||
@@ -10,11 +10,22 @@ import android.os.Bundle;
 | 
			
		||||
import android.widget.Toolbar;
 | 
			
		||||
import cc.winboll.studio.libaes.R;
 | 
			
		||||
import cc.winboll.studio.libaes.utils.AESThemeUtil;
 | 
			
		||||
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
 | 
			
		||||
 | 
			
		||||
public class TestAToolbarActivity extends Activity {
 | 
			
		||||
public class TestAToolbarActivity extends Activity implements IWinBollActivity {
 | 
			
		||||
 | 
			
		||||
    public static final String TAG = "TestAToolbarActivity";
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    public Activity getActivity() {
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getTag() {
 | 
			
		||||
        return TAG;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void onCreate(Bundle savedInstanceState) {
 | 
			
		||||
        AESThemeUtil.applyAppTheme(this);
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ package cc.winboll.studio.libaes.unittests;
 | 
			
		||||
 * @Author ZhanGSKen@QQ.COM
 | 
			
		||||
 * @Date 2024/06/30 15:00:51
 | 
			
		||||
 */
 | 
			
		||||
import android.app.Activity;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.view.LayoutInflater;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
@@ -11,19 +12,18 @@ import android.view.ViewGroup;
 | 
			
		||||
import android.widget.AdapterView;
 | 
			
		||||
import android.widget.Toast;
 | 
			
		||||
import android.widget.Toolbar;
 | 
			
		||||
import androidx.appcompat.app.AppCompatActivity;
 | 
			
		||||
import androidx.fragment.app.Fragment;
 | 
			
		||||
import cc.winboll.studio.libaes.R;
 | 
			
		||||
import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity;
 | 
			
		||||
import cc.winboll.studio.libaes.beans.DrawerMenuBean;
 | 
			
		||||
import cc.winboll.studio.libaes.winboll.IWinBollActivity;
 | 
			
		||||
import cc.winboll.studio.libappbase.LogUtils;
 | 
			
		||||
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
 | 
			
		||||
public class TestDrawerFragmentActivity extends DrawerFragmentActivity implements IWinBollActivity {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public AppCompatActivity getActivity() {
 | 
			
		||||
    public Activity getActivity() {
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -32,22 +32,6 @@ public class TestDrawerFragmentActivity extends DrawerFragmentActivity implement
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Toolbar initToolBar() {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean isAddWinBollToolBar() {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean isEnableDisplayHomeAsUp() {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public static final String TAG = "TestDrawerFragmentActivity";
 | 
			
		||||
 | 
			
		||||
    TestFragment1 mTestFragment1;
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ import cc.winboll.studio.libaes.ImagePagerAdapter;
 | 
			
		||||
import cc.winboll.studio.libaes.R;
 | 
			
		||||
import cc.winboll.studio.libaes.views.AOHPCTCSeekBar;
 | 
			
		||||
import cc.winboll.studio.libappbase.LogView;
 | 
			
		||||
import cc.winboll.studio.libappbase.utils.ToastUtils;
 | 
			
		||||
import com.hjq.toast.ToastUtils;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,162 @@
 | 
			
		||||
package cc.winboll.studio.libaes.utils;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @Author ZhanGSKen@AliYun.Com
 | 
			
		||||
 * @Date 2024/08/12 14:45:35
 | 
			
		||||
 * @Describe 应用版本工具集
 | 
			
		||||
 */
 | 
			
		||||
import cc.winboll.studio.libappbase.LogUtils;
 | 
			
		||||
import java.util.regex.Matcher;
 | 
			
		||||
import java.util.regex.Pattern;
 | 
			
		||||
 | 
			
		||||
public class AppVersionUtils {
 | 
			
		||||
 | 
			
		||||
    public static final String TAG = "AppVersionUtils";
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // 检查新版本是否成立
 | 
			
		||||
    // szCurrentCode : 当前版本应用包名
 | 
			
		||||
    // szNextCode : 新版本应用包名
 | 
			
		||||
    // 返回 :情况1:当前版本是发布版
 | 
			
		||||
    //       返回 true (新版本 > 当前版本)
 | 
			
		||||
    //       情况1:当前版本是Beta版
 | 
			
		||||
    //       true 新版本 == 当前版本
 | 
			
		||||
    //
 | 
			
		||||
    public static boolean isHasNewVersion2(String szCurrentName, String szNextName) {
 | 
			
		||||
        LogUtils.d(TAG, String.format("isHasNewVersion2\nszCurrentName : %s\nszNextName : %s", szCurrentName, szNextName));
 | 
			
		||||
        //szCurrentName = "AES_6.2.0-beta0_3234.apk";
 | 
			
		||||
        //szNextName = "AES_6.1.12.apk";
 | 
			
		||||
        //szCurrentName = "AES_6.2.0-beta0_3234.apk";
 | 
			
		||||
        //szNextName = "AES_6.2.0.apk";
 | 
			
		||||
        //szCurrentName = "AES_6.2.0-beta0_3234.apk";
 | 
			
		||||
        //szNextName = "AES_6.2.2.apk";
 | 
			
		||||
        //szCurrentName = "AES_6.2.0-beta0_3234.apk";
 | 
			
		||||
        //szNextName = "AES_6.2.0.apk";
 | 
			
		||||
        //szCurrentName = "AES_6.1.0.apk";
 | 
			
		||||
        //szNextName = "AES_6.2.0.apk";
 | 
			
		||||
        //LogUtils.d(TAG, "szCurrentName : " + szCurrentName);
 | 
			
		||||
        //LogUtils.d(TAG, "szNextName : " + szNextName);
 | 
			
		||||
 | 
			
		||||
        //boolean isVersionNewer = false;
 | 
			
		||||
        //if(szCurrentName.equals(szNextName)) {
 | 
			
		||||
        //    isVersionNewer = false;
 | 
			
		||||
        //} else {
 | 
			
		||||
        //ToastUtils.show("szCurrent : " + szCurrent + "\nszNext : " + szNext);
 | 
			
		||||
        //int nApk = szNextName.lastIndexOf(".apk");
 | 
			
		||||
        //ToastUtils.show("nApk : " + Integer.toString(nApk));
 | 
			
		||||
        //String szNextNoApkName = szNextName.substring(0, nApk);
 | 
			
		||||
        //ToastUtils.show("szNextNoApkName : " + szNextNoApkName);
 | 
			
		||||
        //String szCurrentNoApkName = szCurrentName.substring(0, szNextNoApkName.length());
 | 
			
		||||
        //ToastUtils.show("szCurrentNoApkName : " + szCurrentNoApkName);
 | 
			
		||||
        //String str1 = "3.4.50";
 | 
			
		||||
        //String str2 = "3.3.60";
 | 
			
		||||
        //String str1 = getCodeInPackageName(szCurrentName);
 | 
			
		||||
        //String str2 = getCodeInPackageName(szNextName);
 | 
			
		||||
        //String str1 = getCodeInPackageName(szNextName);
 | 
			
		||||
        //String str2 = getCodeInPackageName(szCurrentName);
 | 
			
		||||
        //Boolean isVersionNewer2 = checkNewVersion(str1,str2);
 | 
			
		||||
        //ToastUtils.show("isVersionNewer2 : " + Boolean.toString(isVersionNewer2));
 | 
			
		||||
        //ToastUtils.show(checkNewVersion(getCodeInPackageName(szCurrentName), getCodeInPackageName(szNextName)));
 | 
			
		||||
        //return checkNewVersion(getCodeInPackageName(szCurrentName), getCodeInPackageName(szNextName));
 | 
			
		||||
        //}
 | 
			
		||||
        //return isVersionNewer;
 | 
			
		||||
        if (checkNewVersion(getCodeInPackageName(szCurrentName), getCodeInPackageName(szNextName))) {
 | 
			
		||||
            // 比 AES_6.2.0.apk 版本大,如 AES_6.2.1.apk。
 | 
			
		||||
            // 比 AES_6.2.0-beta0_3234.apk 大,如 AES_6.2.1.apk。
 | 
			
		||||
            //LogUtils.d(TAG, "App newer stage version is released. Release name : " + szNextName);
 | 
			
		||||
            return true;
 | 
			
		||||
        } 
 | 
			
		||||
        if (szCurrentName.matches(".*_\\d+\\.\\d+\\.\\d+-beta.*\\.apk")) {
 | 
			
		||||
            String szCurrentReleasePackageName = getReleasePackageName(szCurrentName);
 | 
			
		||||
            //LogUtils.d(TAG, "szCurrentReleasePackageName : " + szCurrentReleasePackageName);
 | 
			
		||||
            if (szCurrentReleasePackageName.equals(szNextName)) {
 | 
			
		||||
                // 与 AES_6.2.0-beta0_3234.apk 版本相同,如 AES_6.2.0.apk。
 | 
			
		||||
                //LogUtils.d(TAG, "App stage version is released. Release name : " + szNextName);
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        //LogUtils.d(TAG, "App version is the newest. ");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean isHasNewStageReleaseVersion(String szCurrentName, String szNextName) {
 | 
			
		||||
        LogUtils.d(TAG, String.format("isHasNewStageReleaseVersion\nszCurrentName : %s\nszNextName : %s", szCurrentName, szNextName));
 | 
			
		||||
        //szCurrentName = "AES_6.2.12.apk";
 | 
			
		||||
        //szNextName = "AES_6.3.12.apk";
 | 
			
		||||
        if (checkNewVersion(getCodeInPackageName(szCurrentName), getCodeInPackageName(szNextName))) {
 | 
			
		||||
            // 比 AES_6.2.0.apk 版本大,如 AES_6.2.1.apk。
 | 
			
		||||
            //LogUtils.d(TAG, "App newer stage version is released. Release name : " + szNextName);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // 检查新版本是否成立
 | 
			
		||||
    // szCurrentCode : 当前版本
 | 
			
		||||
    // szNextCode : 新版本
 | 
			
		||||
    // 返回 :true 新版本 > 当前版本
 | 
			
		||||
    //
 | 
			
		||||
    public static Boolean checkNewVersion(String szCurrentCode, String szNextCode) {
 | 
			
		||||
        if (szCurrentCode == null || szCurrentCode.equals("") || szNextCode == null || szNextCode.equals("")) {
 | 
			
		||||
            LogUtils.d(TAG, String.format("checkNewVersion unexpected parameters:\nszCurrentCode : %s\nszNextCode : %s", szCurrentCode, szNextCode));
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        boolean isNew = false;
 | 
			
		||||
        String[] appVersionCurrent = szCurrentCode.split("\\.");
 | 
			
		||||
        String[] appVersionNext = szNextCode.split("\\.");
 | 
			
		||||
        //根据位数最短的判断
 | 
			
		||||
        int lim = appVersionCurrent.length > appVersionNext.length ? appVersionNext.length : appVersionCurrent.length;
 | 
			
		||||
        //根据位数循环判断各个版本
 | 
			
		||||
        for (int i = 0; i < lim; i++) {
 | 
			
		||||
            if (Integer.parseInt(appVersionNext[i]) > Integer.parseInt(appVersionCurrent[i])) {
 | 
			
		||||
                isNew = true;
 | 
			
		||||
                return isNew;
 | 
			
		||||
            } else if (Integer.parseInt(appVersionNext[i]) == Integer.parseInt(appVersionCurrent[i])) {
 | 
			
		||||
                continue ;
 | 
			
		||||
            } else {
 | 
			
		||||
                isNew = false;
 | 
			
		||||
                return isNew;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return isNew;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // 截取应用包名称版本号信息
 | 
			
		||||
    // 如 :AppUtils_7.0.4-beta1_0120.apk 版本号为 7.0.4
 | 
			
		||||
    // 如 :AppUtils_7.0.4.apk 版本号为 7.0.4
 | 
			
		||||
    //
 | 
			
		||||
    public static String getCodeInPackageName(String apkName) {
 | 
			
		||||
        LogUtils.d(TAG, String.format("getCodeInPackageName apkName : %s", apkName));
 | 
			
		||||
        //String apkName = "AppUtils_7.0.0.apk";
 | 
			
		||||
        Pattern pattern = Pattern.compile("\\d+\\.\\d+\\.\\d+");
 | 
			
		||||
        Matcher matcher = pattern.matcher(apkName);
 | 
			
		||||
        if (matcher.find()) {
 | 
			
		||||
            String version = matcher.group();
 | 
			
		||||
            LogUtils.d(TAG, String.format("version is %s", version));
 | 
			
		||||
            return version;
 | 
			
		||||
            //System.out.println("Version number: " + version); // 输出:7.0.0
 | 
			
		||||
        }
 | 
			
		||||
        LogUtils.d(TAG, String.format("No result."));
 | 
			
		||||
        return "";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // 根据Beta版名称生成发布版应用包名称
 | 
			
		||||
    // 如 AppUtils_7.0.4-beta1_0120.apk
 | 
			
		||||
    // 发布版名称就为AppUtils_7.0.4.apk
 | 
			
		||||
    //
 | 
			
		||||
    public static String getReleasePackageName(String szBetaPackageName) {
 | 
			
		||||
        //String szBetaPackageName = "AppUtils_7.0.4-beta1_0120.apk";
 | 
			
		||||
        Pattern pattern = Pattern.compile(".*\\d+\\.\\d+\\.\\d+");
 | 
			
		||||
        Matcher matcher = pattern.matcher(szBetaPackageName);
 | 
			
		||||
        if (matcher.find()) {
 | 
			
		||||
            String szReleasePackageName = matcher.group();
 | 
			
		||||
            return szReleasePackageName + ".apk";
 | 
			
		||||
            //System.out.println("Version number: " + version); // 输出:7.0.0
 | 
			
		||||
        }
 | 
			
		||||
        return "";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -17,13 +17,12 @@ import android.view.View;
 | 
			
		||||
import android.widget.EditText;
 | 
			
		||||
import android.widget.LinearLayout;
 | 
			
		||||
import cc.winboll.studio.libaes.R;
 | 
			
		||||
import cc.winboll.studio.libaes.utils.AppVersionUtils;
 | 
			
		||||
import cc.winboll.studio.libappbase.GlobalApplication;
 | 
			
		||||
import cc.winboll.studio.libappbase.LogUtils;
 | 
			
		||||
import cc.winboll.studio.libappbase.utils.ToastUtils;
 | 
			
		||||
import cc.winboll.studio.libapputils.app.AppVersionUtils;
 | 
			
		||||
import cc.winboll.studio.libapputils.util.PrefUtils;
 | 
			
		||||
import cc.winboll.studio.libapputils.view.WinBollServiceStatusView;
 | 
			
		||||
import cc.winboll.studio.libapputils.view.YesNoAlertDialog;
 | 
			
		||||
import cc.winboll.studio.libappbase.dialogs.YesNoAlertDialog;
 | 
			
		||||
import cc.winboll.studio.libapputils.utils.PrefUtils;
 | 
			
		||||
import com.hjq.toast.ToastUtils;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import mehdi.sakout.aboutpage.AboutPage;
 | 
			
		||||
import mehdi.sakout.aboutpage.Element;
 | 
			
		||||
@@ -284,7 +283,7 @@ public class AboutView extends LinearLayout {
 | 
			
		||||
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 | 
			
		||||
            GlobalApplication.setIsDebuging(true);
 | 
			
		||||
 | 
			
		||||
            WinBollActivityManager.getInstance(context).finishAll();
 | 
			
		||||
            GlobalApplication.getWinBollActivityManager().finishAll();
 | 
			
		||||
            context.startActivity(intent);
 | 
			
		||||
        } 
 | 
			
		||||
    }
 | 
			
		||||
@@ -295,7 +294,7 @@ public class AboutView extends LinearLayout {
 | 
			
		||||
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 | 
			
		||||
            GlobalApplication.setIsDebuging(false);
 | 
			
		||||
 | 
			
		||||
            WinBollActivityManager.getInstance(context).finishAll();
 | 
			
		||||
            GlobalApplication.getWinBollActivityManager().finishAll();
 | 
			
		||||
            context.startActivity(intent);
 | 
			
		||||
        } 
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,96 @@
 | 
			
		||||
package cc.winboll.studio.libaes.winboll;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @Author ZhanGSKen@AliYun.Com
 | 
			
		||||
 * @Date 2025/03/28 19:12:12
 | 
			
		||||
 * @Describe 应用主要服务组件类守护进程服务组件类
 | 
			
		||||
 */
 | 
			
		||||
import android.app.Service;
 | 
			
		||||
import android.content.ComponentName;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.content.ServiceConnection;
 | 
			
		||||
import android.os.IBinder;
 | 
			
		||||
import cc.winboll.studio.libaes.winboll.WinBollClientService;
 | 
			
		||||
import cc.winboll.studio.libappbase.utils.ServiceUtils;
 | 
			
		||||
 | 
			
		||||
public class AssistantService extends Service {
 | 
			
		||||
 | 
			
		||||
    public final static String TAG = "AssistantService";
 | 
			
		||||
 | 
			
		||||
    WinBollClientServiceBean mWinBollServiceBean;
 | 
			
		||||
    MyServiceConnection mMyServiceConnection;
 | 
			
		||||
    volatile boolean mIsServiceRunning;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public IBinder onBind(Intent intent) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onCreate() {
 | 
			
		||||
        super.onCreate();
 | 
			
		||||
        mWinBollServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(this);
 | 
			
		||||
        if (mMyServiceConnection == null) {
 | 
			
		||||
            mMyServiceConnection = new MyServiceConnection();
 | 
			
		||||
        }
 | 
			
		||||
        // 设置运行参数
 | 
			
		||||
        mIsServiceRunning = false;
 | 
			
		||||
        run();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int onStartCommand(Intent intent, int flags, int startId) {
 | 
			
		||||
        run();
 | 
			
		||||
        return START_STICKY;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onDestroy() {
 | 
			
		||||
        mIsServiceRunning = false;
 | 
			
		||||
        super.onDestroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // 运行服务内容
 | 
			
		||||
    //
 | 
			
		||||
    void run() {
 | 
			
		||||
        mWinBollServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(this);
 | 
			
		||||
        if (mWinBollServiceBean.isEnable()) {
 | 
			
		||||
            if (mIsServiceRunning == false) {
 | 
			
		||||
                // 设置运行状态
 | 
			
		||||
                mIsServiceRunning = true;
 | 
			
		||||
                // 唤醒和绑定主进程
 | 
			
		||||
                wakeupAndBindMain();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // 唤醒和绑定主进程
 | 
			
		||||
    //
 | 
			
		||||
    void wakeupAndBindMain() {
 | 
			
		||||
        if (ServiceUtils.isServiceRunning(getApplicationContext(), WinBollClientService.class.getName()) == false) {
 | 
			
		||||
            startForegroundService(new Intent(AssistantService.this, WinBollClientService.class));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        bindService(new Intent(AssistantService.this, WinBollClientService.class), mMyServiceConnection, Context.BIND_IMPORTANT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // 主进程与守护进程连接时需要用到此类
 | 
			
		||||
    //
 | 
			
		||||
    class MyServiceConnection implements ServiceConnection {
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onServiceConnected(ComponentName name, IBinder service) {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onServiceDisconnected(ComponentName name) {
 | 
			
		||||
            mWinBollServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(AssistantService.this);
 | 
			
		||||
            if (mWinBollServiceBean.isEnable()) {
 | 
			
		||||
                wakeupAndBindMain();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,35 @@
 | 
			
		||||
package cc.winboll.studio.libaes.winboll;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @Author ZhanGSKen@AliYun.Com
 | 
			
		||||
 * @Date 2025/03/28 19:11:27
 | 
			
		||||
 * @Describe WinBoll UI 状态图标枚举
 | 
			
		||||
 */
 | 
			
		||||
import cc.winboll.studio.libaes.R;
 | 
			
		||||
 | 
			
		||||
public enum EWUIStatusIconDrawable {
 | 
			
		||||
    NORMAL(0),
 | 
			
		||||
    NEWS(1)
 | 
			
		||||
    ;
 | 
			
		||||
 | 
			
		||||
    static final String TAG = "WUIStatusIconDrawable";
 | 
			
		||||
 | 
			
		||||
    static String[] _mlistCNName = { "正常", "新的消息" };
 | 
			
		||||
 | 
			
		||||
    private int value = 0;
 | 
			
		||||
    private EWUIStatusIconDrawable(int value) {    //必须是private的,否则编译错误
 | 
			
		||||
        this.value = value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int getIconDrawableId(EWUIStatusIconDrawable drawableId) {
 | 
			
		||||
        int res;
 | 
			
		||||
        switch(drawableId){
 | 
			
		||||
            case NEWS :
 | 
			
		||||
                res = R.drawable.ic_winbollbeta;
 | 
			
		||||
                break;
 | 
			
		||||
            default :
 | 
			
		||||
                res = R.drawable.ic_winboll;
 | 
			
		||||
        }
 | 
			
		||||
        return res;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,21 +0,0 @@
 | 
			
		||||
package cc.winboll.studio.libaes.winboll;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @Author ZhanGSKen@AliYun.Com
 | 
			
		||||
 * @Date 2025/03/24 08:23:40
 | 
			
		||||
 * @Describe WinBoll 活动窗口通用接口
 | 
			
		||||
 */
 | 
			
		||||
import android.widget.Toolbar;
 | 
			
		||||
import androidx.appcompat.app.AppCompatActivity;
 | 
			
		||||
 | 
			
		||||
public interface IWinBollActivity {
 | 
			
		||||
 | 
			
		||||
    public static final String TAG = "IWinBollActivity";
 | 
			
		||||
 | 
			
		||||
    // 获取应用资源上下文
 | 
			
		||||
    abstract public AppCompatActivity getActivity();
 | 
			
		||||
    abstract public String getTag();
 | 
			
		||||
    abstract public Toolbar initToolBar();
 | 
			
		||||
    abstract public boolean isEnableDisplayHomeAsUp();
 | 
			
		||||
    abstract public boolean isAddWinBollToolBar();
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,17 @@
 | 
			
		||||
package cc.winboll.studio.libaes.winboll;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @Author ZhanGSKen@AliYun.Com
 | 
			
		||||
 * @Date 2025/03/28 19:08:45
 | 
			
		||||
 * @Describe WinBollService 服务 Binder。
 | 
			
		||||
 */
 | 
			
		||||
import android.graphics.drawable.Drawable;
 | 
			
		||||
 | 
			
		||||
public interface IWinBollClientServiceBinder {
 | 
			
		||||
 | 
			
		||||
    public static final String TAG = "IWinBollClientServiceBinder";
 | 
			
		||||
 | 
			
		||||
    public WinBollClientService getService();
 | 
			
		||||
 | 
			
		||||
    public Drawable getCurrentStatusIconDrawable();
 | 
			
		||||
}
 | 
			
		||||
@@ -1,97 +0,0 @@
 | 
			
		||||
package cc.winboll.studio.libaes.winboll;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @Author ZhanGSKen@AliYun.Com
 | 
			
		||||
 * @Date 2025/03/24 08:24:52
 | 
			
		||||
 */
 | 
			
		||||
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");
 | 
			
		||||
    } 
 | 
			
		||||
}
 | 
			
		||||
@@ -1,318 +0,0 @@
 | 
			
		||||
package cc.winboll.studio.libaes.winboll;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @Author ZhanGSKen@AliYun.Com
 | 
			
		||||
 * @Date 2025/03/24 08:25:43
 | 
			
		||||
 * @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.ActivityManager;
 | 
			
		||||
import android.app.TaskStackBuilder;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import cc.winboll.studio.libappbase.LogUtils;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Iterator;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
public class WinBollActivityManager {
 | 
			
		||||
 | 
			
		||||
    public static final String TAG = "WinBollActivityManager";
 | 
			
		||||
    public static final String EXTRA_TAG = "EXTRA_TAG";
 | 
			
		||||
 | 
			
		||||
    public static enum WinBollUI_TYPE {
 | 
			
		||||
        Aplication, // 退出应用后,保持最近任务栏任务记录主窗口
 | 
			
		||||
        Service // 退出应用后,清理所有最近任务栏任务记录窗口
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
    // 应用类型标志
 | 
			
		||||
    volatile static WinBollUI_TYPE _mWinBollUI_TYPE = WinBollUI_TYPE.Service;
 | 
			
		||||
 | 
			
		||||
    Context mContext;
 | 
			
		||||
    MyActivityLifecycleCallbacks mMyActivityLifecycleCallbacks;
 | 
			
		||||
    static WinBollActivityManager _mWinBollActivityManager;
 | 
			
		||||
    static Map<String, IWinBollActivity> _mapIWinBollList;
 | 
			
		||||
    IWinBollActivity firstIWinBollActivity;
 | 
			
		||||
 | 
			
		||||
    public WinBollActivityManager(Context context) {
 | 
			
		||||
        mContext = context;
 | 
			
		||||
        LogUtils.d(TAG, "WinBollActivityManager()");
 | 
			
		||||
        _mapIWinBollList = new HashMap<String, IWinBollActivity>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static synchronized WinBollActivityManager getInstance(Context context) {
 | 
			
		||||
        LogUtils.d(TAG, "getInstance");
 | 
			
		||||
        if (_mWinBollActivityManager == null) {
 | 
			
		||||
            LogUtils.d(TAG, "_mWinBollActivityManager == null");
 | 
			
		||||
            _mWinBollActivityManager = new WinBollActivityManager(context);
 | 
			
		||||
        }
 | 
			
		||||
        return _mWinBollActivityManager;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // 设置 WinBoll 应用 UI 类型
 | 
			
		||||
    //
 | 
			
		||||
    public synchronized static void setWinBollUI_TYPE(WinBollUI_TYPE mWinBollUI_TYPE) {
 | 
			
		||||
        _mWinBollUI_TYPE = mWinBollUI_TYPE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // 获取 WinBoll 应用 UI 类型
 | 
			
		||||
    //
 | 
			
		||||
    public synchronized static WinBollUI_TYPE getWinBollUI_TYPE() {
 | 
			
		||||
        return _mWinBollUI_TYPE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // 把Activity添加到管理中
 | 
			
		||||
    //
 | 
			
		||||
    public <T extends IWinBollActivity> void add(T iWinBoll) {
 | 
			
		||||
        if (isActive(iWinBoll.getTag())) {
 | 
			
		||||
            LogUtils.d(TAG, String.format("add(...) %s is active.", iWinBoll.getTag()));
 | 
			
		||||
        } else {
 | 
			
		||||
            // 设置起始活动窗口,以便最后退出时提问
 | 
			
		||||
            if (firstIWinBollActivity == null && _mapIWinBollList.size() == 0) {
 | 
			
		||||
                firstIWinBollActivity = iWinBoll;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // 添加到活动窗口列表
 | 
			
		||||
            _mapIWinBollList.put(iWinBoll.getTag(), iWinBoll);
 | 
			
		||||
            LogUtils.d(TAG, String.format("Add activity : %s\n_mapActivityList.size() : %d", iWinBoll.getTag(), _mapIWinBollList.size()));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // activity: 为 null 时,
 | 
			
		||||
    // intent.putExtra 函数 EXTRA_TAG 参数为 tag
 | 
			
		||||
    // activity: 不为 null 时,
 | 
			
		||||
    // intent.putExtra 函数 "tag" 参数为 activity.getTag()
 | 
			
		||||
    //
 | 
			
		||||
    public <T extends IWinBollActivity> void startWinBollActivity(Context context, Class<T> clazz) {
 | 
			
		||||
        try {
 | 
			
		||||
            // 如果窗口已存在就重启窗口
 | 
			
		||||
            String tag = clazz.newInstance().getTag();
 | 
			
		||||
            if (isActive(tag)) {
 | 
			
		||||
                resumeActivity(context, tag);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // 新建一个任务窗口
 | 
			
		||||
            Intent intent = new Intent(context, clazz);
 | 
			
		||||
            //打开多任务窗口 flags
 | 
			
		||||
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
 | 
			
		||||
            intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
 | 
			
		||||
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 | 
			
		||||
            intent.putExtra(EXTRA_TAG, tag);
 | 
			
		||||
            mContext.startActivity(intent);
 | 
			
		||||
        } catch (InstantiationException | IllegalAccessException e) {
 | 
			
		||||
            LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public <T extends IWinBollActivity> void startWinBollActivity(Context context, Intent intent, Class<T> clazz) {
 | 
			
		||||
        try {
 | 
			
		||||
            // 如果窗口已存在就重启窗口
 | 
			
		||||
            String tag = clazz.newInstance().getTag();
 | 
			
		||||
            if (isActive(tag)) {
 | 
			
		||||
                resumeActivity(context, tag);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // 新建一个任务窗口
 | 
			
		||||
            //Intent intent = new Intent(context, clazz);
 | 
			
		||||
            //打开多任务窗口 flags
 | 
			
		||||
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
 | 
			
		||||
            intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
 | 
			
		||||
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 | 
			
		||||
            intent.putExtra(EXTRA_TAG, tag);
 | 
			
		||||
            mContext.startActivity(intent);
 | 
			
		||||
        } catch (InstantiationException | IllegalAccessException e) {
 | 
			
		||||
            LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean isFirstIWinBollActivity(IWinBollActivity iWinBollActivity) {
 | 
			
		||||
        return firstIWinBollActivity != null && firstIWinBollActivity == iWinBollActivity;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // 判断 tag绑定的 MyActivity是否存在
 | 
			
		||||
    //
 | 
			
		||||
    public boolean isActive(String tag) {
 | 
			
		||||
        //printAvtivityListInfo();
 | 
			
		||||
        IWinBollActivity iWinBoll = getIWinBoll(tag);
 | 
			
		||||
        if (iWinBoll != null) {
 | 
			
		||||
            LogUtils.d(TAG, "isActive(...) activity != null tag " + tag);
 | 
			
		||||
            //ToastUtils.show("activity != null tag " + tag);
 | 
			
		||||
            //判断是否为 BaseActivity,如果已经销毁,则移除
 | 
			
		||||
            if (iWinBoll.getActivity().isFinishing() || iWinBoll.getActivity().isDestroyed()) {
 | 
			
		||||
                _mapIWinBollList.remove(iWinBoll.getTag());
 | 
			
		||||
                //_mWinBollActivityList.remove(activity);
 | 
			
		||||
                LogUtils.d(TAG, String.format("isActive(...) remove activity.\ntag : %s", tag));
 | 
			
		||||
                return false;
 | 
			
		||||
            } else {
 | 
			
		||||
                LogUtils.d(TAG, String.format("isActive(...) activity is exist.\ntag : %s", tag));
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            LogUtils.d(TAG, String.format("isActive(...) activity == null\ntag : %s", tag));
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static IWinBollActivity getIWinBoll(String tag) {
 | 
			
		||||
        return _mapIWinBollList.get(tag);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // 找到tag 绑定的 BaseActivity ,通过 getTaskId() 移动到前台
 | 
			
		||||
    //
 | 
			
		||||
    public <T extends IWinBollActivity> void resumeActivity(Context context, String tag) {
 | 
			
		||||
        LogUtils.d(TAG, "resumeActivty");
 | 
			
		||||
        T iWinBoll = (T)getIWinBoll(tag);
 | 
			
		||||
        //LogUtils.d(TAG, "activity " + activity.getTag());
 | 
			
		||||
        if (iWinBoll != null && !iWinBoll.getActivity().isFinishing() && !iWinBoll.getActivity().isDestroyed()) {
 | 
			
		||||
            resumeActivity(context, iWinBoll);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // 找到tag 绑定的 BaseActivity ,通过 getTaskId() 移动到前台
 | 
			
		||||
    //
 | 
			
		||||
    public <T extends IWinBollActivity> void resumeActivity(Context context, T iWinBoll) {
 | 
			
		||||
        ActivityManager am = (ActivityManager) iWinBoll.getActivity().getSystemService(Context.ACTIVITY_SERVICE);
 | 
			
		||||
        //返回启动它的根任务(home 或者 MainActivity)
 | 
			
		||||
        Intent intent = new Intent(context, iWinBoll.getClass());
 | 
			
		||||
        TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
 | 
			
		||||
        stackBuilder.addNextIntentWithParentStack(intent);
 | 
			
		||||
        stackBuilder.startActivities();
 | 
			
		||||
        //moveTaskToFront(YourTaskId, 0);
 | 
			
		||||
        LogUtils.d(TAG, "am.moveTaskToFront");
 | 
			
		||||
        //ToastUtils.show("resumeActivity am.moveTaskToFront");
 | 
			
		||||
        am.moveTaskToFront(iWinBoll.getActivity().getTaskId(), ActivityManager.MOVE_TASK_NO_USER_ACTION);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // 结束所有 Activity
 | 
			
		||||
    //
 | 
			
		||||
    public void finishAll() {
 | 
			
		||||
        try {
 | 
			
		||||
            for (String key : _mapIWinBollList.keySet()) {
 | 
			
		||||
                //System.out.println("Key: " + key + ", Value: " + _mapActivityList.get(key));
 | 
			
		||||
                IWinBollActivity iWinBoll = _mapIWinBollList.get(key);
 | 
			
		||||
                //ToastUtils.show("finishAll() activity");
 | 
			
		||||
                if (iWinBoll != null && !iWinBoll.getActivity().isFinishing() && !iWinBoll.getActivity().isDestroyed()) {
 | 
			
		||||
                    //ToastUtils.show("activity != null ...");
 | 
			
		||||
                    if (getWinBollUI_TYPE() == WinBollUI_TYPE.Service) {
 | 
			
		||||
                        // 结束窗口和最近任务栏, 建议前台服务类应用使用,可以方便用户再次调用 UI 操作。
 | 
			
		||||
                        iWinBoll.getActivity().finishAndRemoveTask();
 | 
			
		||||
                        //ToastUtils.show("finishAll() activity.finishAndRemoveTask();");
 | 
			
		||||
                    } else if (getWinBollUI_TYPE() == WinBollUI_TYPE.Aplication) {
 | 
			
		||||
                        // 结束窗口保留最近任务栏,建议前台服务类应用使用,可以保持应用的系统自觉性。
 | 
			
		||||
                        iWinBoll.getActivity().finish();
 | 
			
		||||
                        //ToastUtils.show("finishAll() activity.finish();");
 | 
			
		||||
                    } else {
 | 
			
		||||
                        LogUtils.d(TAG, "WinBollApplication.WinBollUI_TYPE error.");
 | 
			
		||||
                        //ToastUtils.show("WinBollApplication.WinBollUI_TYPE error.");
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // 结束指定Activity
 | 
			
		||||
    //
 | 
			
		||||
    public <T extends IWinBollActivity> void finish(T iWinBoll) {
 | 
			
		||||
        try {
 | 
			
		||||
            if (iWinBoll != null && !iWinBoll.getActivity().isFinishing() && !iWinBoll.getActivity().isDestroyed()) {
 | 
			
		||||
                //根据tag 移除 MyActivity
 | 
			
		||||
                //String tag= activity.getTag();
 | 
			
		||||
                //_mWinBollActivityList.remove(tag);
 | 
			
		||||
                //ToastUtils.show("remove");
 | 
			
		||||
                //ToastUtils.show("_mWinBollActivityArrayMap.size() " + Integer.toString(_mWinBollActivityArrayMap.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] >> 直接关闭当前窗口
 | 
			
		||||
                LogUtils.d(TAG, "finish no yet.");
 | 
			
		||||
                IWinBollActivity preIWinBoll = getPreIWinBoll(iWinBoll);
 | 
			
		||||
                iWinBoll.getActivity().finish();
 | 
			
		||||
                if (preIWinBoll != null) {
 | 
			
		||||
                    resumeActivity(mContext, preIWinBoll);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // 获取窗口队列中的前一个窗口
 | 
			
		||||
    //
 | 
			
		||||
    IWinBollActivity getPreIWinBoll(IWinBollActivity iWinBoll) {
 | 
			
		||||
        try {
 | 
			
		||||
            boolean bingo = false;
 | 
			
		||||
            IWinBollActivity preIWinBoll = null;
 | 
			
		||||
            for (Map.Entry<String, IWinBollActivity> entity : _mapIWinBollList.entrySet()) {
 | 
			
		||||
                if (entity.getKey().equals(iWinBoll.getTag())) {
 | 
			
		||||
                    bingo = true;
 | 
			
		||||
                    LogUtils.d(TAG, "bingo");
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                preIWinBoll = entity.getValue();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (bingo) {
 | 
			
		||||
                return preIWinBoll;
 | 
			
		||||
            }
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // 从管理列表中移除管理项
 | 
			
		||||
    //
 | 
			
		||||
    public <T extends IWinBollActivity> boolean registeRemove(T activity) {
 | 
			
		||||
        IWinBollActivity iWinBollTest = _mapIWinBollList.get(activity.getTag());
 | 
			
		||||
        if (iWinBollTest != null) {
 | 
			
		||||
            _mapIWinBollList.remove(activity.getTag());
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // 打印管理列表项列表里的信息
 | 
			
		||||
    //
 | 
			
		||||
    public static void printIWinBollListInfo() {
 | 
			
		||||
        //LogUtils.d(TAG, "printAvtivityListInfo");
 | 
			
		||||
        if (!_mapIWinBollList.isEmpty()) {
 | 
			
		||||
            StringBuilder sb = new StringBuilder("Map entries : " + Integer.toString(_mapIWinBollList.size()));
 | 
			
		||||
            Iterator<Map.Entry<String, IWinBollActivity>> iterator = _mapIWinBollList.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.");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,190 @@
 | 
			
		||||
package cc.winboll.studio.libaes.winboll;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @Author ZhanGSKen@AliYun.Com
 | 
			
		||||
 * @Date 2025/03/28 19:06:54
 | 
			
		||||
 * @Describe WinBoll 客户端服务
 | 
			
		||||
 */
 | 
			
		||||
import android.app.Service;
 | 
			
		||||
import android.content.ComponentName;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.content.ServiceConnection;
 | 
			
		||||
import android.graphics.drawable.Drawable;
 | 
			
		||||
import android.os.IBinder;
 | 
			
		||||
import cc.winboll.studio.libaes.winboll.AssistantService;
 | 
			
		||||
import cc.winboll.studio.libappbase.LogUtils;
 | 
			
		||||
import cc.winboll.studio.libappbase.utils.ServiceUtils;
 | 
			
		||||
import com.hjq.toast.ToastUtils;
 | 
			
		||||
 | 
			
		||||
public class WinBollClientService extends Service implements IWinBollClientServiceBinder {
 | 
			
		||||
 | 
			
		||||
    public static final String TAG = "WinBollClientService";
 | 
			
		||||
 | 
			
		||||
    WinBollClientServiceBean mWinBollClientServiceBean;
 | 
			
		||||
    MyServiceConnection mMyServiceConnection;
 | 
			
		||||
    volatile boolean mIsWinBollClientThreadRunning;
 | 
			
		||||
    volatile boolean mIsEnableService;
 | 
			
		||||
    WinBollClientThread mWinBollClientThread;
 | 
			
		||||
 | 
			
		||||
    public boolean isWinBollClientThreadRunning() {
 | 
			
		||||
        return mIsWinBollClientThreadRunning;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public WinBollClientService getService() {
 | 
			
		||||
        return WinBollClientService.this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Drawable getCurrentStatusIconDrawable() {
 | 
			
		||||
        return mIsWinBollClientThreadRunning ?
 | 
			
		||||
            getDrawable(EWUIStatusIconDrawable.getIconDrawableId(EWUIStatusIconDrawable.NORMAL))
 | 
			
		||||
            : getDrawable(EWUIStatusIconDrawable.getIconDrawableId(EWUIStatusIconDrawable.NEWS));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public IBinder onBind(Intent intent) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onCreate() {
 | 
			
		||||
        ToastUtils.show("onCreate");
 | 
			
		||||
        super.onCreate();
 | 
			
		||||
        mWinBollClientThread = null;
 | 
			
		||||
        mWinBollClientServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(this);
 | 
			
		||||
        mIsEnableService = mWinBollClientServiceBean.isEnable();
 | 
			
		||||
 | 
			
		||||
        if (mMyServiceConnection == null) {
 | 
			
		||||
            mMyServiceConnection = new MyServiceConnection();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 由系统启动时,应用可以通过下面函数实例化实际服务进程。
 | 
			
		||||
        runMainThread();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int onStartCommand(Intent intent, int flags, int startId) {
 | 
			
		||||
        ToastUtils.show("onStartCommand");
 | 
			
		||||
        // 由应用 Intent 启动时,应用可以通过下面函数实例化实际服务进程。
 | 
			
		||||
        runMainThread();
 | 
			
		||||
 | 
			
		||||
        // 返回运行参数持久化存储后,服务状态控制参数
 | 
			
		||||
        // 无论 Intent 传入如何,服务状态一直以持久化存储后的参数控制,
 | 
			
		||||
        // PS: 另外当然可以通过 Intent 传入的指标来修改 mWinBollServiceBean,
 | 
			
		||||
        //     不过本服务的应用方向会变得繁琐,
 | 
			
		||||
        //     现阶段只要满足手机端启动与停止本服务,WinBoll 客户端实例运行在手机端就可以了。
 | 
			
		||||
        return mIsEnableService ? Service.START_STICKY: super.onStartCommand(intent, flags, startId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void runMainThread() {
 | 
			
		||||
        if (mWinBollClientThread == null) {
 | 
			
		||||
            ToastUtils.show("runMainThread()");
 | 
			
		||||
            mWinBollClientThread = new WinBollClientThread();
 | 
			
		||||
            mWinBollClientThread.start();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void syncWinBollClientThreadStatus() {
 | 
			
		||||
        mWinBollClientServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(this);
 | 
			
		||||
        mIsEnableService = mWinBollClientServiceBean.isEnable();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // 唤醒和绑定守护进程
 | 
			
		||||
    //
 | 
			
		||||
    void wakeupAndBindAssistant() {
 | 
			
		||||
        if (ServiceUtils.isServiceRunning(getApplicationContext(), AssistantService.class.getName()) == false) {
 | 
			
		||||
            startService(new Intent(WinBollClientService.this, AssistantService.class));
 | 
			
		||||
            //LogUtils.d(TAG, "call wakeupAndBindAssistant() : Binding... AssistantService");
 | 
			
		||||
            bindService(new Intent(WinBollClientService.this, AssistantService.class), mMyServiceConnection, Context.BIND_IMPORTANT);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 主进程与守护进程连接时需要用到此类
 | 
			
		||||
    //
 | 
			
		||||
    private class MyServiceConnection implements ServiceConnection {
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onServiceConnected(ComponentName name, IBinder service) {
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onServiceDisconnected(ComponentName name) {            
 | 
			
		||||
            mWinBollClientServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(WinBollClientService.this);
 | 
			
		||||
            if (mWinBollClientServiceBean.isEnable()) {
 | 
			
		||||
                // 唤醒守护进程
 | 
			
		||||
                wakeupAndBindAssistant();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onDestroy() {
 | 
			
		||||
        super.onDestroy();
 | 
			
		||||
        ToastUtils.show("onDestroy");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onStart(Intent intent, int startId) {
 | 
			
		||||
        super.onStart(intent, startId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void setWinBollServiceEnableStatus(boolean isEnable) {
 | 
			
		||||
        WinBollClientServiceBean bean = WinBollClientServiceBean.loadWinBollClientServiceBean(this);
 | 
			
		||||
        bean.setIsEnable(isEnable);
 | 
			
		||||
        WinBollClientServiceBean.saveWinBollServiceBean(this, bean);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    boolean getWinBollServiceEnableStatus(Context context) {
 | 
			
		||||
        mWinBollClientServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(context);
 | 
			
		||||
        return mWinBollClientServiceBean.isEnable();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*public interface OnServiceStatusChangeListener {
 | 
			
		||||
     void onServerStatusChange(boolean isServiceAlive);
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
     public void setOnServerStatusChangeListener(OnServiceStatusChangeListener l) {
 | 
			
		||||
     mOnServerStatusChangeListener = l;
 | 
			
		||||
     }*/
 | 
			
		||||
 | 
			
		||||
    class WinBollClientThread extends Thread {
 | 
			
		||||
        @Override
 | 
			
		||||
        public void run() {
 | 
			
		||||
            //ToastUtils.show("WinBollClientThread");
 | 
			
		||||
            super.run();
 | 
			
		||||
            syncWinBollClientThreadStatus();
 | 
			
		||||
            if (mIsEnableService) {
 | 
			
		||||
                if (mIsWinBollClientThreadRunning == false) {
 | 
			
		||||
                    // 设置运行状态
 | 
			
		||||
                    mIsWinBollClientThreadRunning = true;
 | 
			
		||||
 | 
			
		||||
                    //ToastUtils.show("run()");
 | 
			
		||||
 | 
			
		||||
                    // 唤醒守护进程
 | 
			
		||||
                    //wakeupAndBindAssistant();
 | 
			
		||||
 | 
			
		||||
                    while (mIsEnableService) {
 | 
			
		||||
                        // 显示运行状态
 | 
			
		||||
                        ToastUtils.show(TAG + " is running.");
 | 
			
		||||
                        try {
 | 
			
		||||
                            Thread.sleep(2 * 1000);
 | 
			
		||||
                        } catch (InterruptedException e) {
 | 
			
		||||
                            LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
 | 
			
		||||
                        }
 | 
			
		||||
                        syncWinBollClientThreadStatus();
 | 
			
		||||
                        //ToastUtils.show("syncServiceThreadStatus OK.");
 | 
			
		||||
                        //ToastUtils.show("mIsExist : " + Boolean.toString(!mIsEnableService));
 | 
			
		||||
                        //break;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // 服务进程退出, 重置进程运行状态
 | 
			
		||||
                    mIsWinBollClientThreadRunning = false;
 | 
			
		||||
                    mWinBollClientThread = null;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,78 @@
 | 
			
		||||
package cc.winboll.studio.libaes.winboll;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @Author ZhanGSKen@AliYun.Com
 | 
			
		||||
 * @Date 2025/03/28 19:05:15
 | 
			
		||||
 * @Describe WinBollService 运行参数配置
 | 
			
		||||
 */
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.util.JsonReader;
 | 
			
		||||
import android.util.JsonWriter;
 | 
			
		||||
import cc.winboll.studio.libappbase.BaseBean;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
 | 
			
		||||
public class WinBollClientServiceBean extends BaseBean {
 | 
			
		||||
 | 
			
		||||
    public static final String TAG = "WinBollClientServiceBean";
 | 
			
		||||
 | 
			
		||||
    volatile boolean isEnable;
 | 
			
		||||
 | 
			
		||||
    public WinBollClientServiceBean() {
 | 
			
		||||
        isEnable = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setIsEnable(boolean isEnable) {
 | 
			
		||||
        this.isEnable = isEnable;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean isEnable() {
 | 
			
		||||
        return isEnable;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getName() {
 | 
			
		||||
        return WinBollClientServiceBean.class.getName();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
 | 
			
		||||
        super.writeThisToJsonWriter(jsonWriter);
 | 
			
		||||
        WinBollClientServiceBean bean = this;
 | 
			
		||||
        jsonWriter.name("isEnable").value(bean.isEnable());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
 | 
			
		||||
        if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
 | 
			
		||||
            if (name.equals("isEnable")) {
 | 
			
		||||
                setIsEnable(jsonReader.nextBoolean());
 | 
			
		||||
            } else {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public BaseBean readBeanFromJsonReader(JsonReader jsonReader) throws IOException {
 | 
			
		||||
        jsonReader.beginObject();
 | 
			
		||||
        while (jsonReader.hasNext()) {
 | 
			
		||||
            String name = jsonReader.nextName();
 | 
			
		||||
            if (!initObjectsFromJsonReader(jsonReader, name)) {
 | 
			
		||||
                jsonReader.skipValue();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // 结束 JSON 对象
 | 
			
		||||
        jsonReader.endObject();
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static WinBollClientServiceBean loadWinBollClientServiceBean(Context context) {
 | 
			
		||||
        WinBollClientServiceBean bean = WinBollClientServiceBean.loadBean(context, WinBollClientServiceBean.class);
 | 
			
		||||
        return bean == null ? new WinBollClientServiceBean() : bean;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean saveWinBollServiceBean(WinBollClientService service, WinBollClientServiceBean bean) {
 | 
			
		||||
        return WinBollClientServiceBean.saveBean(service, bean);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,22 @@
 | 
			
		||||
package cc.winboll.studio.libaes.winboll;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @Author ZhanGSKen@AliYun.Com
 | 
			
		||||
 * @Date 2025/03/28 19:13:20
 | 
			
		||||
 * @Describe WinBoll 邮件服务
 | 
			
		||||
 */
 | 
			
		||||
import android.app.Service;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.os.IBinder;
 | 
			
		||||
 | 
			
		||||
public class WinBollMail extends Service {
 | 
			
		||||
 | 
			
		||||
    public static final String TAG = "WinBollMail";
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public IBinder onBind(Intent intent) {
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,340 @@
 | 
			
		||||
package cc.winboll.studio.libaes.winboll;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @Author ZhanGSKen@AliYun.Com
 | 
			
		||||
 * @Date 2025/03/28 17:41:55
 | 
			
		||||
 * @Describe WinBoll 服务主机连接状态视图
 | 
			
		||||
 */
 | 
			
		||||
import android.content.ComponentName;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.content.ServiceConnection;
 | 
			
		||||
import android.graphics.drawable.Drawable;
 | 
			
		||||
import android.os.Handler;
 | 
			
		||||
import android.os.IBinder;
 | 
			
		||||
import android.os.Message;
 | 
			
		||||
import android.util.AttributeSet;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
import android.widget.ImageView;
 | 
			
		||||
import android.widget.LinearLayout;
 | 
			
		||||
import android.widget.TextView;
 | 
			
		||||
import cc.winboll.studio.libappbase.LogUtils;
 | 
			
		||||
import com.hjq.toast.ToastUtils;
 | 
			
		||||
import cc.winboll.studio.libapputils.R;
 | 
			
		||||
//import okhttp3.Authenticator;
 | 
			
		||||
//import okhttp3.Credentials;
 | 
			
		||||
//import okhttp3.OkHttpClient;
 | 
			
		||||
//import okhttp3.Request;
 | 
			
		||||
//import okhttp3.Response;
 | 
			
		||||
//import okhttp3.Route;
 | 
			
		||||
 | 
			
		||||
public class WinBollServiceStatusView extends LinearLayout {
 | 
			
		||||
 | 
			
		||||
    public static final String TAG = "WinBollServiceStatusView";
 | 
			
		||||
 | 
			
		||||
    public static final int MSG_CONNECTION_INFO = 0;
 | 
			
		||||
    public static final int MSG_UPDATE_CONNECTION_STATUS = 1;
 | 
			
		||||
 | 
			
		||||
    Context mContext;
 | 
			
		||||
    //boolean mIsConnected;
 | 
			
		||||
    ConnectionThread mConnectionThread;
 | 
			
		||||
 | 
			
		||||
    String mszServerHost;
 | 
			
		||||
    WinBollClientService mWinBollService;
 | 
			
		||||
    ImageView mImageView;
 | 
			
		||||
    TextView mTextView;
 | 
			
		||||
    WinBollServiceViewHandler mWinBollServiceViewHandler;
 | 
			
		||||
    //WebView mWebView;
 | 
			
		||||
    static volatile ConnectionStatus mConnectionStatus;
 | 
			
		||||
    View.OnClickListener mViewOnClickListener;
 | 
			
		||||
    static String _mUserName;
 | 
			
		||||
    static String _mPassword;
 | 
			
		||||
 | 
			
		||||
    static enum ConnectionStatus {
 | 
			
		||||
        DISCONNECTED,
 | 
			
		||||
        START_CONNECT,
 | 
			
		||||
        CONNECTING,
 | 
			
		||||
        CONNECTED;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    boolean isBound = false;
 | 
			
		||||
    ServiceConnection connection = new ServiceConnection() {
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onServiceConnected(ComponentName name, IBinder service) {
 | 
			
		||||
            IWinBollClientServiceBinder binder = (IWinBollClientServiceBinder) service;
 | 
			
		||||
            mWinBollService = binder.getService();
 | 
			
		||||
            isBound = true;
 | 
			
		||||
            // 可以在这里调用Service的方法进行通信,比如获取数据
 | 
			
		||||
            mImageView.setBackgroundDrawable(mWinBollService.getCurrentStatusIconDrawable());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onServiceDisconnected(ComponentName name) {
 | 
			
		||||
            isBound = false;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    public WinBollServiceStatusView(Context context) {
 | 
			
		||||
        super(context);
 | 
			
		||||
        mContext = context;
 | 
			
		||||
        initView();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public WinBollServiceStatusView(Context context, AttributeSet attrs) {
 | 
			
		||||
        super(context, attrs);
 | 
			
		||||
        mContext = context;
 | 
			
		||||
        initView();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public WinBollServiceStatusView(Context context, AttributeSet attrs, int defStyleAttr) {
 | 
			
		||||
        super(context, attrs, defStyleAttr);
 | 
			
		||||
        mContext = context;
 | 
			
		||||
        initView();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public WinBollServiceStatusView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
 | 
			
		||||
        super(context, attrs, defStyleAttr, defStyleRes);
 | 
			
		||||
        mContext = context;
 | 
			
		||||
        initView();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ConnectionStatus getConnectionStatus() {
 | 
			
		||||
        return false ?
 | 
			
		||||
            ConnectionStatus.CONNECTED 
 | 
			
		||||
            : ConnectionStatus.DISCONNECTED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void initView() {
 | 
			
		||||
        mImageView = new ImageView(mContext);
 | 
			
		||||
        setImageViewByConnection(mImageView, false);
 | 
			
		||||
        mConnectionStatus = getConnectionStatus();
 | 
			
		||||
        //mIsConnected = false;
 | 
			
		||||
        //mWinBollServerHostConnectionStatus = WinBollServerHostConnectionStatus.DISCONNECTED;
 | 
			
		||||
        //ToastUtils.show("initView()");
 | 
			
		||||
 | 
			
		||||
        mViewOnClickListener = new View.OnClickListener(){
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onClick(View v) {
 | 
			
		||||
                //ToastUtils.show("onClick()");
 | 
			
		||||
                //ToastUtils.show("mWinBollServerHostConnectionStatus : " + mWinBollServerHostConnectionStatus);
 | 
			
		||||
                //isConnected = !isConnected;
 | 
			
		||||
                if (mConnectionStatus == ConnectionStatus.CONNECTED) {
 | 
			
		||||
                    ToastUtils.show("Click to stop service.");
 | 
			
		||||
                    WinBollClientServiceBean bean = WinBollClientServiceBean.loadWinBollClientServiceBean(mContext);
 | 
			
		||||
                    bean.setIsEnable(false);
 | 
			
		||||
                    WinBollClientServiceBean.saveBean(mContext, bean);
 | 
			
		||||
                    Intent intent = new Intent(mContext, WinBollClientService.class);
 | 
			
		||||
                    mContext.stopService(intent);
 | 
			
		||||
                    mConnectionStatus = ConnectionStatus.DISCONNECTED;
 | 
			
		||||
//                  
 | 
			
		||||
                    /*//ToastUtils.show("CONNECTED");
 | 
			
		||||
                     setConnectionStatusView(false);
 | 
			
		||||
                     mWinBollServerHostConnectionStatusViewHandler.postMessageText("");
 | 
			
		||||
                     if (mConnectionThread != null) {
 | 
			
		||||
                     mConnectionThread.mIsExist = true;
 | 
			
		||||
                     mConnectionThread = null;
 | 
			
		||||
                     mWinBollServerHostConnectionStatus = WinBollServerHostConnectionStatus.DISCONNECTED;
 | 
			
		||||
                     ToastUtils.show("WinBoll Server Disconnected.");
 | 
			
		||||
                     }*/
 | 
			
		||||
                } else if (mConnectionStatus == ConnectionStatus.DISCONNECTED) {
 | 
			
		||||
                    ToastUtils.show("Click to start service.");
 | 
			
		||||
                    WinBollClientServiceBean bean = WinBollClientServiceBean.loadWinBollClientServiceBean(mContext);
 | 
			
		||||
                    bean.setIsEnable(true);
 | 
			
		||||
                    WinBollClientServiceBean.saveBean(mContext, bean);
 | 
			
		||||
                    Intent intent = new Intent(mContext, WinBollClientService.class);
 | 
			
		||||
                    mContext.startService(intent);
 | 
			
		||||
                    mConnectionStatus = ConnectionStatus.CONNECTED;
 | 
			
		||||
                    ToastUtils.show("startService");
 | 
			
		||||
                    /*//ToastUtils.show("DISCONNECTED");
 | 
			
		||||
                     setConnectionStatusView(true);
 | 
			
		||||
 | 
			
		||||
                     if (mConnectionThread == null) {
 | 
			
		||||
                     ToastUtils.show("mConnectionThread == null");
 | 
			
		||||
                     mConnectionThread = new ConnectionThread();
 | 
			
		||||
                     mWinBollServerHostConnectionStatus = WinBollServerHostConnectionStatus.START_CONNECT;
 | 
			
		||||
                     mConnectionThread.start();
 | 
			
		||||
                     }*/
 | 
			
		||||
                } else {
 | 
			
		||||
                    ToastUtils.show("Other Click condition.");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                /*if (isConnected) {
 | 
			
		||||
                 mWebView.loadUrl("https://dev.winboll.cc");
 | 
			
		||||
                 } else {
 | 
			
		||||
                 mWebView.stopLoading();
 | 
			
		||||
                 }*/
 | 
			
		||||
                //ToastUtils.show(mDevelopHostConnectionStatus);
 | 
			
		||||
                //LogUtils.d(TAG, "mDevelopHostConnectionStatus : " + mWinBollServerHostConnectionStatus);
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        setOnClickListener(mViewOnClickListener);
 | 
			
		||||
        addView(mImageView);
 | 
			
		||||
        mTextView = new TextView(mContext);
 | 
			
		||||
        mWinBollServiceViewHandler = new WinBollServiceViewHandler(this);
 | 
			
		||||
        addView(mTextView);
 | 
			
		||||
        /*mWebView = new WebView(mContext);
 | 
			
		||||
         mWebView.setWebViewClient(new WebViewClient() {
 | 
			
		||||
         @Override
 | 
			
		||||
         public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
 | 
			
		||||
         // 弹出系统基本HTTP验证窗口
 | 
			
		||||
         handler.proceed("username", "password");
 | 
			
		||||
         }
 | 
			
		||||
         });
 | 
			
		||||
         addView(mWebView);*/
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void checkWinBollServerStatusAndUpdateCurrentView() {
 | 
			
		||||
        LogUtils.d(TAG, "checkWinBollServerStatusAndUpdateCurrentView()");
 | 
			
		||||
        /*if (getConnectionStatus() == ConnectionStatus.CONNECTED) {
 | 
			
		||||
         mConnectionStatus = ConnectionStatus.CONNECTED;
 | 
			
		||||
         } else {
 | 
			
		||||
         mConnectionStatus = ConnectionStatus.DISCONNECTED;
 | 
			
		||||
         }*/
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setServerHost(String szWinBollServerHost) {
 | 
			
		||||
        mszServerHost = szWinBollServerHost;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setAuthInfo(String username, String password) {
 | 
			
		||||
        _mUserName = username;
 | 
			
		||||
        _mPassword = password;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void setImageViewByConnection(ImageView imageView, boolean isConnected) {
 | 
			
		||||
        //mIsConnected = isConnected;
 | 
			
		||||
        // 获取vector drawable
 | 
			
		||||
        Drawable drawable = mContext.getDrawable(isConnected ? R.drawable.ic_dev_connected : R.drawable.ic_dev_disconnected);
 | 
			
		||||
        if (drawable != null) {
 | 
			
		||||
            imageView.setImageDrawable(drawable);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void requestWithBasicAuth(WinBollServiceViewHandler textViewHandler, String targetUrl, final String username, final String password) {
 | 
			
		||||
        // 用户名和密码,替换为实际的认证信息
 | 
			
		||||
        //String username = "your_username";
 | 
			
		||||
        //String password = "your_password";
 | 
			
		||||
 | 
			
		||||
//        OkHttpClient client = new OkHttpClient.Builder()
 | 
			
		||||
//            .authenticator(new Authenticator() {
 | 
			
		||||
//                @Override
 | 
			
		||||
//                public Request authenticate(Route route, Response response) throws IOException {
 | 
			
		||||
//                    String credential = Credentials.basic(username, password);
 | 
			
		||||
//                    return response.request().newBuilder()
 | 
			
		||||
//                        .header("Authorization", credential)
 | 
			
		||||
//                        .build();
 | 
			
		||||
//                }
 | 
			
		||||
//            })
 | 
			
		||||
//            .build();
 | 
			
		||||
//
 | 
			
		||||
//        Request request = new Request.Builder()
 | 
			
		||||
//            .url(targetUrl) // 替换为实际要请求的网页地址
 | 
			
		||||
//            .build();
 | 
			
		||||
//
 | 
			
		||||
//        try {
 | 
			
		||||
//            Response response = client.newCall(request).execute();
 | 
			
		||||
//            if (response.isSuccessful()) {
 | 
			
		||||
//                //System.out.println(response.body().string());
 | 
			
		||||
//                //ToastUtils.show("Develop Host Connection IP is : " + response.body().string());
 | 
			
		||||
//                // 获取当前时间
 | 
			
		||||
//                LocalDateTime now = LocalDateTime.now();
 | 
			
		||||
//
 | 
			
		||||
//                // 定义时间格式
 | 
			
		||||
//                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
 | 
			
		||||
//                // 按照指定格式格式化时间并输出
 | 
			
		||||
//                String formattedDateTime = now.format(formatter);
 | 
			
		||||
//                //System.out.println(formattedDateTime);
 | 
			
		||||
//                textViewHandler.postMessageText("ClientIP<" + formattedDateTime + ">: " + response.body().string());
 | 
			
		||||
//                textViewHandler.postMessageConnectionStatus(true);
 | 
			
		||||
//            } else {
 | 
			
		||||
//                String sz = "请求失败,状态码: " + response.code();
 | 
			
		||||
//                setImageViewByConnection(mImageView, false);
 | 
			
		||||
//                textViewHandler.postMessageText(sz);
 | 
			
		||||
//                textViewHandler.postMessageConnectionStatus(false);
 | 
			
		||||
//                LogUtils.d(TAG, sz);
 | 
			
		||||
//            }
 | 
			
		||||
//        } catch (IOException e) {
 | 
			
		||||
//            textViewHandler.postMessageText(e.getMessage());
 | 
			
		||||
//            textViewHandler.postMessageConnectionStatus(false);
 | 
			
		||||
//            LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
 | 
			
		||||
//        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class WinBollServiceViewHandler extends Handler {
 | 
			
		||||
        WinBollServiceStatusView mDevelopHostConnectionStatusView;
 | 
			
		||||
 | 
			
		||||
        public WinBollServiceViewHandler(WinBollServiceStatusView view) {
 | 
			
		||||
            mDevelopHostConnectionStatusView = view;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void handleMessage(Message msg) {
 | 
			
		||||
            if (msg.what == MSG_CONNECTION_INFO) {
 | 
			
		||||
                mDevelopHostConnectionStatusView.mTextView.setText((String)msg.obj);
 | 
			
		||||
            } else if (msg.what == MSG_UPDATE_CONNECTION_STATUS) {
 | 
			
		||||
                mDevelopHostConnectionStatusView.setImageViewByConnection(mImageView, (boolean)msg.obj);
 | 
			
		||||
                mDevelopHostConnectionStatusView.mConnectionStatus = ((boolean)msg.obj) ? ConnectionStatus.CONNECTED : ConnectionStatus.DISCONNECTED;
 | 
			
		||||
            }
 | 
			
		||||
            super.handleMessage(msg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void postMessageText(String szMSG) {
 | 
			
		||||
            Message msg = new Message();
 | 
			
		||||
            msg.what = MSG_CONNECTION_INFO;
 | 
			
		||||
            msg.obj = szMSG;
 | 
			
		||||
            sendMessage(msg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void postMessageConnectionStatus(boolean isConnected) {
 | 
			
		||||
            Message msg = new Message();
 | 
			
		||||
            msg.what = MSG_UPDATE_CONNECTION_STATUS;
 | 
			
		||||
            msg.obj = isConnected;
 | 
			
		||||
            sendMessage(msg);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class ConnectionThread extends Thread {
 | 
			
		||||
 | 
			
		||||
        public volatile boolean mIsExist;
 | 
			
		||||
 | 
			
		||||
        //DevelopHostConnectionStatusViewHandler mDevelopHostConnectionStatusViewHandler;
 | 
			
		||||
 | 
			
		||||
        //public ConnectionThread(DevelopHostConnectionStatusViewHandler developHostConnectionStatusViewHandler) {
 | 
			
		||||
        //mDevelopHostConnectionStatusViewHandler = developHostConnectionStatusViewHandler;
 | 
			
		||||
        //}
 | 
			
		||||
        public ConnectionThread() {
 | 
			
		||||
            mIsExist = false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void run() {
 | 
			
		||||
            super.run();
 | 
			
		||||
            while (mIsExist == false) {
 | 
			
		||||
                if (mConnectionStatus == ConnectionStatus.START_CONNECT) {
 | 
			
		||||
                    mConnectionStatus = ConnectionStatus.CONNECTING;
 | 
			
		||||
                    ToastUtils.show("WinBoll Server Connection Start.");
 | 
			
		||||
                    //LogUtils.d(TAG, "Develop Host Connection Start.");
 | 
			
		||||
                    String targetUrl = "https://" + mszServerHost + "/cip/?simple=true";  // 这里替换成你实际要访问的网址
 | 
			
		||||
                    requestWithBasicAuth(mWinBollServiceViewHandler, targetUrl, _mUserName, _mPassword);
 | 
			
		||||
                } else if (mConnectionStatus == ConnectionStatus.CONNECTED
 | 
			
		||||
                           && mConnectionStatus == ConnectionStatus.DISCONNECTED) {
 | 
			
		||||
                    ToastUtils.show("mWinBollServerHostConnectionStatus " + mConnectionStatus);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                try {
 | 
			
		||||
                    Thread.sleep(5 * 1000);
 | 
			
		||||
                } catch (InterruptedException e) {
 | 
			
		||||
                    LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            //ToastUtils.show("ConnectionThread exit.");
 | 
			
		||||
            LogUtils.d(TAG, "ConnectionThread exit.");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*WinBollService.OnServiceStatusChangeListener mOnServerStatusChangeListener = new WinBollService.OnServiceStatusChangeListener(){
 | 
			
		||||
     @Override
 | 
			
		||||
     public void onServerStatusChange(boolean isServiceAlive) {
 | 
			
		||||
     }
 | 
			
		||||
     };*/
 | 
			
		||||
}
 | 
			
		||||
@@ -53,7 +53,7 @@
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:gravity="center_horizontal">
 | 
			
		||||
 | 
			
		||||
        <cc.winboll.studio.libapputils.view.WinBollServiceStatusView
 | 
			
		||||
        <cc.winboll.studio.libaes.winboll.WinBollServiceStatusView
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:id="@+id/viewaboutdevWinBollServiceStatusView1"/>
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:gravity="center_horizontal">
 | 
			
		||||
 | 
			
		||||
        <cc.winboll.studio.libapputils.view.WinBollServiceStatusView
 | 
			
		||||
        <cc.winboll.studio.libaes.winboll.WinBollServiceStatusView
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:id="@+id/viewaboutwwwWinBollServiceStatusView1"/>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user