diff --git a/android_app/app/build.gradle b/android_app/app/build.gradle index ffb28a6..df2a9b5 100644 --- a/android_app/app/build.gradle +++ b/android_app/app/build.gradle @@ -1,16 +1,16 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 29 - buildToolsVersion "29.0.3" + compileSdkVersion 30 + buildToolsVersion "30.0.3" - sourceCompatibility = '11' // -source - targetCompatibility = '11' // -target + sourceCompatibility = '1.8' // -source + targetCompatibility = '1.8' // -target defaultConfig { applicationId "tun.proxy" minSdkVersion 21 - targetSdkVersion 29 + targetSdkVersion 30 versionCode 100260 versionName VERSION_NAME testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/android_app/app/src/androidTest/java/tun/proxy/ProgressTaskTest.java b/android_app/app/src/androidTest/java/tun/proxy/ProgressTaskTest.java new file mode 100644 index 0000000..2bc4d4d --- /dev/null +++ b/android_app/app/src/androidTest/java/tun/proxy/ProgressTaskTest.java @@ -0,0 +1,66 @@ +package tun.proxy; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.util.Log; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.List; + +import tun.utils.ProgressTask; +import tun.utils.Util; + +import static org.junit.Assert.assertEquals; + +@RunWith(AndroidJUnit4.class) +public class ProgressTaskTest { + private static final String TAG = "ProgressTaskTest"; + + @Before + public void setUp() { + + } + + @After + public void tearDown() { + + } + + @Test + public void progressTask() { + Log.w(TAG, "progressTask: start"); + + ProgressTask task = new ProgressTask>() { + + @Override + protected List doInBackground(String... var1) { + for (int i = 0; i < 100; i++) { + try { + Thread.sleep(10); + Log.d(TAG, "Progress:" + i); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + return null; + } + + }; + + Assert.assertEquals(task.getStatus(), ProgressTask.Status.PENDING); + Log.w(TAG, "progressTask: execute"); + task.execute(); + Assert.assertEquals(task.getStatus(), ProgressTask.Status.RUNNING); + + Log.w(TAG, "progressTask: end"); + + } +} diff --git a/android_app/app/src/main/java/tun/proxy/MainActivity.java b/android_app/app/src/main/java/tun/proxy/MainActivity.java index f88ad9e..687b05c 100644 --- a/android_app/app/src/main/java/tun/proxy/MainActivity.java +++ b/android_app/app/src/main/java/tun/proxy/MainActivity.java @@ -22,6 +22,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.text.TextUtils; import android.util.Log; import android.view.View; @@ -42,7 +43,7 @@ public class MainActivity extends AppCompatActivity implements Button start; Button stop; EditText hostEditText; - Handler statusHandler = new Handler(); + Handler statusHandler = new Handler(Looper.getMainLooper()); private Tun2HttpVpnService service; diff --git a/android_app/app/src/main/java/tun/proxy/SettingsActivity.java b/android_app/app/src/main/java/tun/proxy/SettingsActivity.java index c6c730a..fe6fc2b 100644 --- a/android_app/app/src/main/java/tun/proxy/SettingsActivity.java +++ b/android_app/app/src/main/java/tun/proxy/SettingsActivity.java @@ -7,7 +7,7 @@ import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.os.AsyncTask; +//import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import androidx.appcompat.app.ActionBar; @@ -29,8 +29,8 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; + +import tun.utils.ProgressTask; public class SettingsActivity extends AppCompatActivity { private static final String TAG = "SettingsActivity"; @@ -285,7 +285,7 @@ protected void filter(String filter, final MyApplication.AppSortBy filterBy, fin this.removeAllPreferenceScreen(); - if (task != null && task.getStatus() == AsyncTask.Status.PENDING) { + if (task != null && task.getStatus() == ProgressTask.Status.PENDING) { task.execute(); } else { @@ -522,7 +522,7 @@ public boolean onClose() { * https://developer.android.com/reference/android/os/AsyncTask * Deprecated in API level R * */ - public static class AsyncTaskProgress extends AsyncTask> { + public static class AsyncTaskProgress extends ProgressTask> { final PackageListFragment packageFragment; diff --git a/android_app/app/src/main/java/tun/utils/ProgressTask.java b/android_app/app/src/main/java/tun/utils/ProgressTask.java new file mode 100644 index 0000000..abd79f3 --- /dev/null +++ b/android_app/app/src/main/java/tun/utils/ProgressTask.java @@ -0,0 +1,88 @@ +package tun.utils; + +import android.os.Handler; +import android.os.Looper; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public abstract class ProgressTask { + private volatile Status mStatus = Status.PENDING; + private boolean canceled = false; + + public final ProgressTask.Status getStatus() { + return mStatus; + } + + private class ProgressRunnable implements Runnable { + + final Params [] params; + + @SafeVarargs + public ProgressRunnable(Params... params) { + this.params = params; + } + + private Result result; + Handler handler = new Handler(Looper.getMainLooper()); + + @Override + public void run() { + if (mStatus != Status.PENDING) { + switch (mStatus) { + case RUNNING: + throw new IllegalStateException("Cannot execute task:" + + " the task is already running."); + case FINISHED: + throw new IllegalStateException("Cannot execute task:" + + " the task has already been executed " + + "(a task can be executed only once)"); + } + } + mStatus = Status.RUNNING; + try { + onPreExecute(); + result = doInBackground(params); + } catch (Exception ex) { + ex.printStackTrace(); + } + handler.post(new Runnable() { + @Override + public void run() { + if (!canceled) { + onPostExecute(result); + mStatus = Status.FINISHED; + } else { + onCancelled(); + } + } + }); + } + } + + public void execute(Params... params) { + ExecutorService executorService = Executors.newSingleThreadExecutor(); + executorService.submit(new ProgressRunnable(params)); + } + + protected void onPreExecute() { + } + + protected abstract Result doInBackground(Params... params); + + protected void onPostExecute(Result result) { + } + + public void cancel(boolean flag) { + canceled = flag; + } + + public final boolean isCancelled() { + return canceled; + } + + protected void onCancelled() { + } + + public enum Status { PENDING, RUNNING, FINISHED } +} \ No newline at end of file