简介

原作者仓库似乎挺长时间没有更新了。最近又需要用到该软件,就顺手更新一下.

  1. 更新核心至官方最新1.14.2版本
  2. 添加磁贴功能,操作更便捷
  3. 修复外部中断服务后状态不同步的问题

关键代码摘要

清单文件添加Tile服务

AndroidManifest.xml
<service
        android:name=".service.ZeroTierTileService"
        android:icon="@drawable/zerotier_one"
        android:label="@string/tile_label"
        android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
        android:exported="true">
        <intent-filter>
            <action android:name="android.service.quicksettings.action.QS_TILE" />
        </intent-filter>
    </service>

ZeroTierTileService中检测主服务运行状态并注册广播接收器

ZeroTierTileService.java
private boolean isServiceRunning() {
    ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (ZeroTierOneService.class.getName().equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}

@Override
public void onStartListening() {
    super.onStartListening();
    Log.w("ZeroTierTileService", "onStartListening");
    registerReceiver(tileReceiver, new IntentFilter(Constants.ACTION_TILE_TOGGLE),null , null);
    updateTileForService();
}

@Override
public void onStopListening() {
    Log.w("ZeroTierTileService", "onStopListening");
    unregisterReceiver(tileReceiver);
    super.onStopListening();
}
private BroadcastReceiver tileReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Constants.ACTION_TILE.equals(intent.getAction())) {
            updateTileForReceive(intent.getBooleanExtra(Constants.EXTRA_SWITCH_STATE, false));
        }
    }
};

在onClick接口实现开启/关闭主服务

@Override
public void onClick() {
    if (VpnService.prepare(this) != null) {
        Intent intent = new Intent(this, NetworkListFragment.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
        return;
    }
    boolean isConnected = isServiceRunning();
    if (isConnected) {
        Log.d("ZeroTierTileService", "ZeroTier One Stopped");
        Intent stopIntent = new Intent(this, ZeroTierOneService.class);
        stopIntent.setAction(ZeroTierOneService.ACTION_STOP_VPN);
        startService(stopIntent);
        updateTile(false);
    } else {
        long networkId = getLastNetworkId();
        if (networkId != -1) {
            Intent startIntent = new Intent(this, ZeroTierOneService.class);
            startIntent.putExtra(ZeroTierOneService.ZT1_NETWORK_ID, networkId);
            startService(startIntent);
            updateTile(false);
        } else {
            Log.d("ZeroTierTileService", "ZeroTier One Started");
            Intent intent = new Intent(this, NetworkListFragment.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        }
    }

}

主服务中在适当位置发送运行状态广播

ZeroTierOneService.java
private void sendChangedBroadcast(long networkId, boolean isConnected) {
    if (isConnected){
        startMonitoring();
    }else {
        stopMonitoring();
    }
    Log.d(TAG, "ZeroTierTileService sendChangedBroadcast(): "+isConnected);
    Intent intent = new Intent(Constants.ACTION_TILE);
    intent.putExtra(Constants.EXTRA_NETWORK_ID, networkId);
    intent.putExtra(Constants.EXTRA_SWITCH_STATE, isConnected); // 取反状态
    long currentTimeMillis = System.currentTimeMillis();
    intent.putExtra(Constants.EXTRA_TIMESTAMP, currentTimeMillis);
    sendBroadcast(intent);
}

同时需要在Fragment中注册广播接受器及时更新状态

NetworkListFragment.java
private BroadcastReceiver tileReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Constants.ACTION_TILE.equals(intent.getAction())) {
            long networkId = intent.getLongExtra(Constants.EXTRA_NETWORK_ID, -1);
            boolean newState = intent.getBooleanExtra(Constants.EXTRA_SWITCH_STATE, false);
            viewModel.doChangeConnectNetwork(newState ? networkId : null);
            int position = recyclerViewAdapter.findPositionByNetworkId(networkId);
            if (position != -1) {
                // 通知适配器局部刷新
                requireActivity().runOnUiThread(() -> {
                    recyclerViewAdapter.notifyItemChanged(position);
                });
            }
        }
    }
};


预览

20250321041703.jpg

20250321041644.png


下载地址

点此去下载
密码:0000