Skip to content

Commit e531166

Browse files
committed
The server list can now be loaded from URL; Minor bug fixes
1 parent e81c393 commit e531166

10 files changed

Lines changed: 204 additions & 94 deletions

File tree

Speedtest-Android/.idea/gradle.xml

Lines changed: 8 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Speedtest-Android/app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ android {
77
applicationId "your.name.here.speedtest"
88
minSdkVersion 15
99
targetSdkVersion 28
10-
versionCode 5
11-
versionName '1.1.3'
10+
versionCode 6
11+
versionName '1.2'
1212
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
1313
}
1414
buildTypes {

Speedtest-Android/app/src/main/java/com/fdossena/speedtest/core/Speedtest.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
import org.json.JSONException;
55
import org.json.JSONObject;
66

7+
import java.io.BufferedReader;
8+
import java.io.InputStream;
9+
import java.io.InputStreamReader;
10+
import java.net.URL;
711
import java.util.ArrayList;
812

913
import com.fdossena.speedtest.core.config.SpeedtestConfig;
@@ -73,6 +77,58 @@ public void addTestPoints(JSONArray json){
7377
}
7478
}
7579

80+
private static class ServerListLoader {
81+
private static String read(String url){
82+
try{
83+
URL u=new URL(url);
84+
InputStream in=u.openStream();
85+
BufferedReader br=new BufferedReader(new InputStreamReader(u.openStream()));
86+
String s="";
87+
try{
88+
for(;;){
89+
String r=br.readLine();
90+
if(r==null) break; else s+=r;
91+
}
92+
}catch(Throwable t){}
93+
br.close();
94+
in.close();
95+
return s;
96+
}catch(Throwable t){
97+
return null;
98+
}
99+
}
100+
101+
public static TestPoint[] loadServerList(String url){
102+
try{
103+
String s=null;
104+
if(url.startsWith("//")){
105+
s=read("https:"+url);
106+
if(s==null) s=read("http:"+url);
107+
}else s=read(url);
108+
if(s==null) throw new Exception("Failed");
109+
JSONArray a=new JSONArray(s);
110+
ArrayList<TestPoint> ret=new ArrayList<>();
111+
for(int i=0;i<a.length();i++){
112+
ret.add(new TestPoint(a.getJSONObject(i)));
113+
}
114+
return ret.toArray(new TestPoint[0]);
115+
}catch(Throwable t){
116+
return null;
117+
}
118+
}
119+
}
120+
public boolean loadServerList(String url){
121+
synchronized (mutex) {
122+
if (state == 0) state = 1;
123+
if (state > 1) throw new IllegalStateException("Cannot add test points at this moment");
124+
TestPoint[] pts= ServerListLoader.loadServerList(url);
125+
if(pts!=null){
126+
addTestPoints(pts);
127+
return true;
128+
}else return false;
129+
}
130+
}
131+
76132
public TestPoint[] getTestPoints(){
77133
synchronized (mutex) {
78134
return servers.toArray(new TestPoint[0]);

Speedtest-Android/app/src/main/java/com/fdossena/speedtest/core/base/Connection.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class Connection {
2121
private int mode=MODE_NOT_SET;
2222
private static final int MODE_NOT_SET=0, MODE_HTTP=1, MODE_HTTPS=2;
2323

24-
private static final String USER_AGENT="Speedtest-Android/1.1.3 (SDK "+Build.VERSION.SDK_INT+"; "+Build.PRODUCT+"; Android "+Build.VERSION.RELEASE+")",
24+
private static final String USER_AGENT="Speedtest-Android/1.2 (SDK "+Build.VERSION.SDK_INT+"; "+Build.PRODUCT+"; Android "+Build.VERSION.RELEASE+")",
2525
LOCALE= Build.VERSION.SDK_INT>=21?Locale.getDefault().toLanguageTag():null;
2626

2727
public Connection(String url, int connectTimeout, int soTimeout, int recvBuffer, int sendBuffer){

Speedtest-Android/app/src/main/java/com/fdossena/speedtest/core/ping/Pinger.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.fdossena.speedtest.core.ping;
22

33
import java.io.InputStream;
4+
import java.util.HashMap;
5+
import java.util.Map;
46

57
import com.fdossena.speedtest.core.base.Connection;
68

@@ -24,11 +26,22 @@ public void run(){
2426
c.GET(s,true);
2527
if(stopASAP) break;
2628
long t=System.nanoTime();
27-
if(c.readLineUnbuffered().trim().isEmpty()) throw new Exception("Persistent connection died");
29+
boolean chunked=false;
30+
boolean ok=false;
31+
while(true){
32+
String l=c.readLineUnbuffered();
33+
if(l==null) break;
34+
l=l.trim().toLowerCase();
35+
if(l.equals("transfer-encoding: chunked")) chunked=true;
36+
if(l.contains("200 ok")) ok=true;
37+
if(l.trim().isEmpty()){
38+
if(chunked){c.readLineUnbuffered(); c.readLineUnbuffered();}
39+
break;
40+
}
41+
}
42+
if(!ok) throw new Exception("Did not get a 200");
2843
t=System.nanoTime()-t;
2944
if(stopASAP) break;
30-
while(!c.readLineUnbuffered().trim().isEmpty());
31-
if(stopASAP) break;
3245
if(!onPong(t/2)) break;
3346
}
3447
c.close();

Speedtest-Android/app/src/main/java/com/fdossena/speedtest/core/serverSelector/ServerSelector.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,16 @@
44
import org.json.JSONException;
55
import org.json.JSONObject;
66

7+
import java.io.BufferedInputStream;
8+
import java.io.BufferedReader;
9+
import java.io.InputStream;
10+
import java.io.InputStreamReader;
11+
import java.net.URI;
12+
import java.net.URL;
713
import java.util.ArrayList;
14+
import java.util.HashMap;
815

16+
import com.fdossena.speedtest.core.base.Connection;
917
import com.fdossena.speedtest.core.config.SpeedtestConfig;
1018
import com.fdossena.speedtest.core.ping.PingStream;
1119

@@ -18,6 +26,7 @@ public abstract class ServerSelector {
1826
private int timeout;
1927
private static final int PINGS=3, SLOW_THRESHOLD=500;
2028
private boolean stopASAP=false;
29+
private boolean loadingServers=false;
2130

2231
public ServerSelector(TestPoint[] servers, int timeout){
2332
addTestPoints(servers);

Speedtest-Android/app/src/main/java/com/fdossena/speedtest/ui/MainActivity.java

Lines changed: 98 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -75,98 +75,85 @@ public void run() {
7575
private static Speedtest st=null;
7676

7777
private void page_init(){
78-
transition(R.id.page_init,TRANSITION_LENGTH);
79-
final TextView t=((TextView)findViewById(R.id.init_text));
80-
runOnUiThread(new Runnable() {
78+
new Thread(){
8179
@Override
8280
public void run() {
83-
t.setText(R.string.init_init);
84-
}
85-
});
86-
SpeedtestConfig config=null;
87-
TelemetryConfig telemetryConfig=null;
88-
TestPoint[] servers=null;
89-
try{
90-
String c=readFileFromAssets("SpeedtestConfig.json");
91-
JSONObject o=new JSONObject(c);
92-
config=new SpeedtestConfig(o);
93-
c=readFileFromAssets("TelemetryConfig.json");
94-
o=new JSONObject(c);
95-
telemetryConfig=new TelemetryConfig(o);
96-
if(telemetryConfig.getTelemetryLevel().equals(TelemetryConfig.LEVEL_DISABLED)){
9781
runOnUiThread(new Runnable() {
9882
@Override
9983
public void run() {
100-
hideView(R.id.privacy_open);
84+
transition(R.id.page_init,TRANSITION_LENGTH);
10185
}
10286
});
103-
}
104-
c=readFileFromAssets("ServerList.json");
105-
JSONArray a=new JSONArray(c);
106-
if(a.length()==0) throw new Exception("No test points");
107-
ArrayList<TestPoint> s=new ArrayList<>();
108-
for(int i=0;i<a.length();i++) s.add(new TestPoint(a.getJSONObject(i)));
109-
servers=s.toArray(new TestPoint[0]);
110-
if(st!=null){
111-
try{st.abort();}catch (Throwable e){}
112-
}
113-
st=new Speedtest();
114-
st.setSpeedtestConfig(config);
115-
st.setTelemetryConfig(telemetryConfig);
116-
st.addTestPoints(servers);
117-
final String testOrder=config.getTest_order();
118-
runOnUiThread(new Runnable() {
119-
@Override
120-
public void run() {
121-
if(!testOrder.contains("D")){
122-
hideView(R.id.dlArea);
87+
final TextView t=((TextView)findViewById(R.id.init_text));
88+
runOnUiThread(new Runnable() {
89+
@Override
90+
public void run() {
91+
t.setText(R.string.init_init);
12392
}
124-
if(!testOrder.contains("U")){
125-
hideView(R.id.ulArea);
93+
});
94+
SpeedtestConfig config=null;
95+
TelemetryConfig telemetryConfig=null;
96+
TestPoint[] servers=null;
97+
try{
98+
String c=readFileFromAssets("SpeedtestConfig.json");
99+
JSONObject o=new JSONObject(c);
100+
config=new SpeedtestConfig(o);
101+
c=readFileFromAssets("TelemetryConfig.json");
102+
o=new JSONObject(c);
103+
telemetryConfig=new TelemetryConfig(o);
104+
if(telemetryConfig.getTelemetryLevel().equals(TelemetryConfig.LEVEL_DISABLED)){
105+
runOnUiThread(new Runnable() {
106+
@Override
107+
public void run() {
108+
hideView(R.id.privacy_open);
109+
}
110+
});
126111
}
127-
if(!testOrder.contains("P")){
128-
hideView(R.id.pingArea);
112+
if(st!=null){
113+
try{st.abort();}catch (Throwable e){}
129114
}
130-
if(!testOrder.contains("I")){
131-
hideView(R.id.ipInfo);
115+
st=new Speedtest();
116+
st.setSpeedtestConfig(config);
117+
st.setTelemetryConfig(telemetryConfig);
118+
c=readFileFromAssets("ServerList.json");
119+
if(c.startsWith("\"")||c.startsWith("'")){ //fetch server list from URL
120+
if(!st.loadServerList(c.subSequence(1,c.length()-1).toString())){
121+
throw new Exception("Failed to load server list");
122+
}
123+
}else{ //use provided server list
124+
JSONArray a=new JSONArray(c);
125+
if(a.length()==0) throw new Exception("No test points");
126+
ArrayList<TestPoint> s=new ArrayList<>();
127+
for(int i=0;i<a.length();i++) s.add(new TestPoint(a.getJSONObject(i)));
128+
servers=s.toArray(new TestPoint[0]);
129+
st.addTestPoints(servers);
132130
}
133-
}
134-
});
135-
}catch (final Throwable e){
136-
st=null;
137-
transition(R.id.page_fail,TRANSITION_LENGTH);
138-
runOnUiThread(new Runnable() {
139-
@Override
140-
public void run() {
141-
((TextView)findViewById(R.id.fail_text)).setText(getString(R.string.initFail_configError)+": "+e.getMessage());
142-
final Button b=(Button)findViewById(R.id.fail_button);
143-
b.setText(R.string.initFail_retry);
144-
b.setOnClickListener(new View.OnClickListener() {
131+
final String testOrder=config.getTest_order();
132+
runOnUiThread(new Runnable() {
145133
@Override
146-
public void onClick(View v) {
147-
page_init();
148-
b.setOnClickListener(null);
134+
public void run() {
135+
if(!testOrder.contains("D")){
136+
hideView(R.id.dlArea);
137+
}
138+
if(!testOrder.contains("U")){
139+
hideView(R.id.ulArea);
140+
}
141+
if(!testOrder.contains("P")){
142+
hideView(R.id.pingArea);
143+
}
144+
if(!testOrder.contains("I")){
145+
hideView(R.id.ipInfo);
146+
}
149147
}
150148
});
151-
}
152-
});
153-
return;
154-
}
155-
runOnUiThread(new Runnable() {
156-
@Override
157-
public void run() {
158-
t.setText(R.string.init_selecting);
159-
}
160-
});
161-
st.selectServer(new Speedtest.ServerSelectedHandler() {
162-
@Override
163-
public void onServerSelected(final TestPoint server) {
164-
runOnUiThread(new Runnable() {
165-
@Override
166-
public void run() {
167-
if(server==null){
168-
transition(R.id.page_fail,TRANSITION_LENGTH);
169-
((TextView)findViewById(R.id.fail_text)).setText(getString(R.string.initFail_noServers));
149+
}catch (final Throwable e){
150+
System.err.println(e);
151+
st=null;
152+
transition(R.id.page_fail,TRANSITION_LENGTH);
153+
runOnUiThread(new Runnable() {
154+
@Override
155+
public void run() {
156+
((TextView)findViewById(R.id.fail_text)).setText(getString(R.string.initFail_configError)+": "+e.getMessage());
170157
final Button b=(Button)findViewById(R.id.fail_button);
171158
b.setText(R.string.initFail_retry);
172159
b.setOnClickListener(new View.OnClickListener() {
@@ -176,13 +163,43 @@ public void onClick(View v) {
176163
b.setOnClickListener(null);
177164
}
178165
});
179-
}else{
180-
page_serverSelect(server,st.getTestPoints());
181166
}
167+
});
168+
return;
169+
}
170+
runOnUiThread(new Runnable() {
171+
@Override
172+
public void run() {
173+
t.setText(R.string.init_selecting);
174+
}
175+
});
176+
st.selectServer(new Speedtest.ServerSelectedHandler() {
177+
@Override
178+
public void onServerSelected(final TestPoint server) {
179+
runOnUiThread(new Runnable() {
180+
@Override
181+
public void run() {
182+
if(server==null){
183+
transition(R.id.page_fail,TRANSITION_LENGTH);
184+
((TextView)findViewById(R.id.fail_text)).setText(getString(R.string.initFail_noServers));
185+
final Button b=(Button)findViewById(R.id.fail_button);
186+
b.setText(R.string.initFail_retry);
187+
b.setOnClickListener(new View.OnClickListener() {
188+
@Override
189+
public void onClick(View v) {
190+
page_init();
191+
b.setOnClickListener(null);
192+
}
193+
});
194+
}else{
195+
page_serverSelect(server,st.getTestPoints());
196+
}
197+
}
198+
});
182199
}
183200
});
184201
}
185-
});
202+
}.start();
186203
}
187204

188205
private void page_serverSelect(TestPoint selected, TestPoint[] servers){

Speedtest-Android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ buildscript {
77

88
}
99
dependencies {
10-
classpath 'com.android.tools.build:gradle:3.5.3'
10+
classpath 'com.android.tools.build:gradle:3.6.0'
1111

1212
// NOTE: Do not place your application dependencies here; they belong
1313
// in the individual module build.gradle files

0 commit comments

Comments
 (0)