老毛子代码写的还真是精致,在昨天把中文XML资源撸出来后,发现里面的代码写的还是挺有意思的,可读性很强。

今天继续研究设置代理的业务逻辑。

通过猜测,我们可知道ProxyListActivity.java就是设置代理的界面了,那么里面肯定有设置代理的代码,

public boolean onFragmentCreate() {
        super.onFragmentCreate();

        SharedConfig.loadProxyList();  // 这句是重点!!!!!
        currentConnectionState = ConnectionsManager.getInstance(currentAccount).getConnectionState();

        NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.proxySettingsChanged);
        NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.proxyCheckDone);
        NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.didUpdateConnectionState);

        final SharedPreferences preferences = MessagesController.getGlobalMainSettings();
        useProxySettings = preferences.getBoolean("proxy_enabled", false) && !SharedConfig.proxyList.isEmpty();
        useProxyForCalls = preferences.getBoolean("proxy_enabled_calls", false);

        updateRows(true);

        return true;
    }

通过上句我们发现了一个很有意思的类:SharedConfig, 通过名字我们可以猜测应该是共享的通用配置,就是多个账户公用信息。而每个账户也会有自己单独的信息,比如ConnectionManager等。

所以我们去看看  SharedConfig.loadProxyList(); 到底如何加载数据,并且看看这个公用配置里面有什么。

里面有个简单实体类:ProxyInfo,我们简单看一眼,大概也就知道什么意思。

 public ProxyInfo(String a, int p, String u, String pw, String s) {
            address = a;
            port = p;
            username = u;
            password = pw;
            secret = s;
            if (address == null) {
                address = "";
            }
            if (password == null) {
                password = "";
            }
            if (username == null) {
                username = "";
            }
            if (secret == null) {
                secret = "";
            }
        }

Load函数,无非是从配置的"proxy_list"部分反序列化出多个代理信息,加到静态的list之中,对应的还有saveProxyList()函数。

我们得看看重点,如何添加一个代理信息:

public static ProxyInfo addProxy(ProxyInfo proxyInfo) {
        loadProxyList();
        int count = proxyList.size();
        for (int a = 0; a < count; a++) {
            ProxyInfo info = proxyList.get(a);
            if (proxyInfo.address.equals(info.address) && proxyInfo.port == info.port && proxyInfo.username.equals(info.username) && proxyInfo.password.equals(info.password) && proxyInfo.secret.equals(info.secret)) {
                return info;
            }
        }
        proxyList.add(proxyInfo);
        saveProxyList();
        return proxyInfo;
    }

代码的大概意思就是如果和已有信息相同就不再添加,直接返回,如果没有添加过就加到列表中,并保存。这个有个问题,

就是:没有通知底层去激活或者测试代理能否使用。

相反在

public static void deleteProxy(ProxyInfo proxyInfo)
{
    ……  ……
}

函数中有一句很重要:

 ConnectionsManager.setProxySettings(false, "", 0, "", "", "");

如果当前使用了代理,则通知底层禁用代理。

那么,可以得出结论:这个类SharedConfig仅仅是管理了各种信息,并没有和底层的开关逻辑相捆绑。

于是我们回到之前的界面类中,仔细研读,在视图创建类中,有关于点击了某一行代理的信息:

// 当点击位置,位于第1行与最后1行之间,
 else if (position >= proxyStartRow && position < proxyEndRow) {
                SharedConfig.ProxyInfo info = SharedConfig.proxyList.get(position - proxyStartRow);
                useProxySettings = true;
                SharedPreferences.Editor editor = MessagesController.getGlobalMainSettings().edit();
                editor.putString("proxy_ip", info.address);
                editor.putString("proxy_pass", info.password);
                editor.putString("proxy_user", info.username);
                editor.putInt("proxy_port", info.port);
                editor.putString("proxy_secret", info.secret);
                editor.putBoolean("proxy_enabled", useProxySettings);
                if (!info.secret.isEmpty()) {
                    useProxyForCalls = false;
                    editor.putBoolean("proxy_enabled_calls", false);
                }
                editor.commit();
                SharedConfig.currentProxy = info;
                for (int a = proxyStartRow; a < proxyEndRow; a++) {
                    RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.findViewHolderForAdapterPosition(a);
                    if (holder != null) {
                        TextDetailProxyCell cell = (TextDetailProxyCell) holder.itemView;
                        cell.setChecked(cell.currentInfo == info);
                        cell.updateStatus();
                    }
                }
                updateRows(false);
                RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.findViewHolderForAdapterPosition(useProxyRow);
                if (holder != null) {
                    TextCheckCell textCheckCell = (TextCheckCell) holder.itemView;
                    textCheckCell.setChecked(true);
                }
                // 这句重点:告诉底层当前的代理设置
                ConnectionsManager.setProxySettings(useProxySettings, SharedConfig.currentProxy.address, SharedConfig.currentProxy.port, SharedConfig.currentProxy.username, SharedConfig.currentProxy.password, SharedConfig.currentProxy.secret);
            } 

这样就与之前的分析有些不同,详见telegram android 源码分析 (一)自动设置代理,

ConnectionsManager.setProxySettings()函数的代码如下:

 public static void setProxySettings(boolean enabled, String address, int port, String username, String password, String secret) {
        if (address == null) {
            address = "";
        }
        if (username == null) {
            username = "";
        }
        if (password == null) {
            password = "";
        }
        if (secret == null) {
            secret = "";
        }
        for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) {
            if (enabled && !TextUtils.isEmpty(address)) {
                native_setProxySettings(a, address, port, username, password, secret);
            } else {
                native_setProxySettings(a, "", 1080, "", "", "");
            }
            AccountInstance accountInstance = AccountInstance.getInstance(a);
            if (accountInstance.getUserConfig().isClientActivated()) {
                accountInstance.getMessagesController().checkProxyInfo(true);
            }
        }
    }

代码不复杂,大概是说检查一下各个参数合法性,然后对当前每个账户分别设置代理的参数。

 native_setProxySettings是个JNI函数,具体实现在C语言的包中,从函数参数可以猜测出,并没有启动与停止的的参数,而是使用了""空字符串来表示不使用代理。

 

到此,我们已经完整的分析完了上层设置代理的逻辑,至于如何自己添加自动设置的功能,我祝大家好运。

 

如果觉得这篇文章有用,如果您能打赏一下,我会很欣慰的!:)

 

更多推荐