feat: publish Android 1.0.1 candidate source and acceptance evidence
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<application android:label="UCVL acceptance probe — test only" android:theme="@android:style/Theme.Material.Light.NoActionBar">
|
||||
<activity android:name=".ProbeActivity" android:exported="true" />
|
||||
</application>
|
||||
</manifest>
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package cn.toplc.zonghengjia.acceptanceprobe;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.widget.TextView;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.Proxy;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/** Separate UID: does not use an explicit proxy and cannot borrow the VPN app's bypass. */
|
||||
public class ProbeActivity extends Activity {
|
||||
@Override public void onCreate(Bundle state) {
|
||||
super.onCreate(state);
|
||||
TextView view = new TextView(this);
|
||||
view.setText("Testing Android system VPN from a separate application…");
|
||||
setContentView(view);
|
||||
new Thread(() -> {
|
||||
JSONObject report = new JSONObject();
|
||||
try {
|
||||
ConnectivityManager cm = getSystemService(ConnectivityManager.class);
|
||||
NetworkCapabilities caps = cm.getNetworkCapabilities(cm.getActiveNetwork());
|
||||
report.put("transport_vpn", caps != null && caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN));
|
||||
report.put("uid", android.os.Process.myUid());
|
||||
report.put("explicit_proxy", false);
|
||||
String[] urls = {"https://www.google.com/generate_204", "https://api.openai.com/v1/models",
|
||||
"https://chatgpt.com/backend-api/codex/models", "https://vpn.toplc.cn/"};
|
||||
JSONArray results = new JSONArray();
|
||||
int[] expected = {204, 401, 401, 200};
|
||||
for (int i = 0; i < urls.length; i++) {
|
||||
JSONObject row = new JSONObject();
|
||||
row.put("target", new URL(urls[i]).getHost());
|
||||
HttpsURLConnection connection = null;
|
||||
try {
|
||||
connection = (HttpsURLConnection)new URL(urls[i]).openConnection(Proxy.NO_PROXY);
|
||||
connection.setConnectTimeout(15000);
|
||||
connection.setReadTimeout(15000);
|
||||
int status = connection.getResponseCode();
|
||||
row.put("status", status);
|
||||
row.put("pass", status == expected[i]);
|
||||
} catch (Exception ex) {
|
||||
row.put("pass", false);
|
||||
row.put("error_type", ex.getClass().getSimpleName());
|
||||
} finally { if (connection != null) connection.disconnect(); }
|
||||
results.put(row);
|
||||
}
|
||||
report.put("results", results);
|
||||
try (FileOutputStream output = new FileOutputStream(new File(getFilesDir(), "result.json"))) {
|
||||
output.write(report.toString(2).getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
runOnUiThread(() -> view.setText(report.toString()));
|
||||
} catch (Exception ex) { runOnUiThread(() -> view.setText(ex.getClass().getSimpleName())); }
|
||||
}, "acceptance-probe").start();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user