mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-23 00:17:42 +00:00
Eliminate any traces of Java in app
This commit is contained in:
parent
48395ba860
commit
f2494374f8
6
app/proguard-rules.pro
vendored
6
app/proguard-rules.pro
vendored
@ -17,9 +17,9 @@
|
|||||||
#}
|
#}
|
||||||
|
|
||||||
# Snet
|
# Snet
|
||||||
-keepclassmembers class com.topjohnwu.magisk.utils.ISafetyNetHelper { *; }
|
-keepclassmembers class com.topjohnwu.magisk.utils.SafetyNetHelper { *; }
|
||||||
-keep,allowobfuscation interface com.topjohnwu.magisk.utils.ISafetyNetHelper$Callback
|
-keep,allowobfuscation interface com.topjohnwu.magisk.utils.SafetyNetHelper$Callback
|
||||||
-keepclassmembers class * implements com.topjohnwu.magisk.utils.ISafetyNetHelper$Callback {
|
-keepclassmembers class * implements com.topjohnwu.magisk.utils.SafetyNetHelper$Callback {
|
||||||
void onResponse(int);
|
void onResponse(int);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,14 +2,14 @@ package a;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.model.worker.DelegateWorker;
|
|
||||||
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.work.Worker;
|
import androidx.work.Worker;
|
||||||
import androidx.work.WorkerParameters;
|
import androidx.work.WorkerParameters;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.model.worker.DelegateWorker;
|
||||||
|
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
|
||||||
public abstract class w<T extends DelegateWorker> extends Worker {
|
public abstract class w<T extends DelegateWorker> extends Worker {
|
||||||
|
|
||||||
/* Wrapper class to workaround Proguard -keep class * extends Worker */
|
/* Wrapper class to workaround Proguard -keep class * extends Worker */
|
||||||
@ -22,7 +22,7 @@ public abstract class w<T extends DelegateWorker> extends Worker {
|
|||||||
try {
|
try {
|
||||||
base = ((Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
|
base = ((Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
|
||||||
.getActualTypeArguments()[0]).newInstance();
|
.getActualTypeArguments()[0]).newInstance();
|
||||||
base.setActualWorker(this);
|
base.attachWorker(this);
|
||||||
} catch (Exception ignored) {}
|
} catch (Exception ignored) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ object ClassMap {
|
|||||||
SuRequestActivity::class.java to a.m::class.java
|
SuRequestActivity::class.java to a.m::class.java
|
||||||
)
|
)
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
operator fun <T : Class<*>>get(c: Class<*>): T {
|
operator fun <T : Class<*>>get(c: Class<*>): T {
|
||||||
return map.getOrElse(c) { throw IllegalArgumentException() } as T
|
return map.getOrElse(c) { throw IllegalArgumentException() } as T
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,6 @@ object Config : PreferenceModel, DBConfig {
|
|||||||
var darkTheme by preference(Key.DARK_THEME, true)
|
var darkTheme by preference(Key.DARK_THEME, true)
|
||||||
var suReAuth by preference(Key.SU_REAUTH, false)
|
var suReAuth by preference(Key.SU_REAUTH, false)
|
||||||
var checkUpdate by preference(Key.CHECK_UPDATES, true)
|
var checkUpdate by preference(Key.CHECK_UPDATES, true)
|
||||||
@JvmStatic
|
|
||||||
var magiskHide by preference(Key.MAGISKHIDE, true)
|
var magiskHide by preference(Key.MAGISKHIDE, true)
|
||||||
var coreOnly by preference(Key.COREONLY, false)
|
var coreOnly by preference(Key.COREONLY, false)
|
||||||
var showSystemApp by preference(Key.SHOW_SYSTEM_APP, false)
|
var showSystemApp by preference(Key.SHOW_SYSTEM_APP, false)
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
package com.topjohnwu.magisk;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.model.entity.UpdateInfo;
|
|
||||||
import com.topjohnwu.superuser.Shell;
|
|
||||||
import com.topjohnwu.superuser.ShellUtils;
|
|
||||||
|
|
||||||
public final class Info {
|
|
||||||
|
|
||||||
public static int magiskVersionCode = -1;
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public static String magiskVersionString = "";
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public static UpdateInfo remote = new UpdateInfo();
|
|
||||||
|
|
||||||
public static boolean keepVerity = false;
|
|
||||||
public static boolean keepEnc = false;
|
|
||||||
public static boolean recovery = false;
|
|
||||||
|
|
||||||
public static void loadMagiskInfo() {
|
|
||||||
try {
|
|
||||||
magiskVersionString = ShellUtils.fastCmd("magisk -v").split(":")[0];
|
|
||||||
magiskVersionCode = Integer.parseInt(ShellUtils.fastCmd("magisk -V"));
|
|
||||||
Config.setMagiskHide(Shell.su("magiskhide --status").exec().isSuccess());
|
|
||||||
} catch (NumberFormatException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
26
app/src/main/java/com/topjohnwu/magisk/Info.kt
Normal file
26
app/src/main/java/com/topjohnwu/magisk/Info.kt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package com.topjohnwu.magisk
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.model.entity.UpdateInfo
|
||||||
|
import com.topjohnwu.superuser.Shell
|
||||||
|
import com.topjohnwu.superuser.ShellUtils
|
||||||
|
|
||||||
|
object Info {
|
||||||
|
|
||||||
|
var magiskVersionCode = -1
|
||||||
|
|
||||||
|
var magiskVersionString = ""
|
||||||
|
|
||||||
|
var remote = UpdateInfo()
|
||||||
|
|
||||||
|
var keepVerity = false
|
||||||
|
var keepEnc = false
|
||||||
|
var recovery = false
|
||||||
|
|
||||||
|
fun loadMagiskInfo() {
|
||||||
|
runCatching {
|
||||||
|
magiskVersionString = ShellUtils.fastCmd("magisk -v").split(":".toRegex())[0]
|
||||||
|
magiskVersionCode = ShellUtils.fastCmd("magisk -V").toInt()
|
||||||
|
Config.magiskHide = Shell.su("magiskhide --status").exec().isSuccess
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,84 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.model.worker;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.net.Network;
|
|
||||||
import android.net.Uri;
|
|
||||||
|
|
||||||
import androidx.annotation.MainThread;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import androidx.work.Data;
|
|
||||||
import androidx.work.ListenableWorker;
|
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public abstract class DelegateWorker {
|
|
||||||
|
|
||||||
private ListenableWorker worker;
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public abstract ListenableWorker.Result doWork();
|
|
||||||
|
|
||||||
public void onStopped() {}
|
|
||||||
|
|
||||||
public void setActualWorker(ListenableWorker w) {
|
|
||||||
worker = w;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public Context getApplicationContext() {
|
|
||||||
return worker.getApplicationContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public UUID getId() {
|
|
||||||
return worker.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public Data getInputData() {
|
|
||||||
return worker.getInputData();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public Set<String> getTags() {
|
|
||||||
return worker.getTags();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@RequiresApi(24)
|
|
||||||
public List<Uri> getTriggeredContentUris() {
|
|
||||||
return worker.getTriggeredContentUris();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@RequiresApi(24)
|
|
||||||
public List<String> getTriggeredContentAuthorities() {
|
|
||||||
return worker.getTriggeredContentAuthorities();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@RequiresApi(28)
|
|
||||||
public Network getNetwork() {
|
|
||||||
return worker.getNetwork();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getRunAttemptCount() {
|
|
||||||
return worker.getRunAttemptCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@MainThread
|
|
||||||
public ListenableFuture<ListenableWorker.Result> startWork() {
|
|
||||||
return worker.startWork();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isStopped() {
|
|
||||||
return worker.isStopped();
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,59 @@
|
|||||||
|
package com.topjohnwu.magisk.model.worker
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.Network
|
||||||
|
import android.net.Uri
|
||||||
|
import androidx.annotation.MainThread
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
import androidx.work.Data
|
||||||
|
import androidx.work.ListenableWorker
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
abstract class DelegateWorker {
|
||||||
|
|
||||||
|
private lateinit var worker: ListenableWorker
|
||||||
|
|
||||||
|
val applicationContext: Context
|
||||||
|
get() = worker.applicationContext
|
||||||
|
|
||||||
|
val id: UUID
|
||||||
|
get() = worker.id
|
||||||
|
|
||||||
|
val inputData: Data
|
||||||
|
get() = worker.inputData
|
||||||
|
|
||||||
|
val tags: Set<String>
|
||||||
|
get() = worker.tags
|
||||||
|
|
||||||
|
val triggeredContentUris: List<Uri>
|
||||||
|
@RequiresApi(24)
|
||||||
|
get() = worker.triggeredContentUris
|
||||||
|
|
||||||
|
val triggeredContentAuthorities: List<String>
|
||||||
|
@RequiresApi(24)
|
||||||
|
get() = worker.triggeredContentAuthorities
|
||||||
|
|
||||||
|
val network: Network?
|
||||||
|
@RequiresApi(28)
|
||||||
|
get() = worker.network
|
||||||
|
|
||||||
|
val runAttemptCount: Int
|
||||||
|
get() = worker.runAttemptCount
|
||||||
|
|
||||||
|
val isStopped: Boolean
|
||||||
|
get() = worker.isStopped
|
||||||
|
|
||||||
|
abstract fun doWork(): ListenableWorker.Result
|
||||||
|
|
||||||
|
fun onStopped() {}
|
||||||
|
|
||||||
|
fun attachWorker(w: ListenableWorker) {
|
||||||
|
worker = w
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainThread
|
||||||
|
fun startWork(): ListenableFuture<ListenableWorker.Result> {
|
||||||
|
return worker.startWork()
|
||||||
|
}
|
||||||
|
}
|
@ -17,8 +17,8 @@ import com.topjohnwu.magisk.extensions.writeTo
|
|||||||
import com.topjohnwu.magisk.model.events.*
|
import com.topjohnwu.magisk.model.events.*
|
||||||
import com.topjohnwu.magisk.ui.base.MagiskActivity
|
import com.topjohnwu.magisk.ui.base.MagiskActivity
|
||||||
import com.topjohnwu.magisk.ui.base.MagiskFragment
|
import com.topjohnwu.magisk.ui.base.MagiskFragment
|
||||||
import com.topjohnwu.magisk.utils.ISafetyNetHelper
|
|
||||||
import com.topjohnwu.magisk.utils.DynamicClassLoader
|
import com.topjohnwu.magisk.utils.DynamicClassLoader
|
||||||
|
import com.topjohnwu.magisk.utils.SafetyNetHelper
|
||||||
import com.topjohnwu.magisk.view.MarkDownWindow
|
import com.topjohnwu.magisk.view.MarkDownWindow
|
||||||
import com.topjohnwu.magisk.view.dialogs.*
|
import com.topjohnwu.magisk.view.dialogs.*
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
@ -26,7 +26,7 @@ import org.koin.androidx.viewmodel.ext.android.viewModel
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class HomeFragment : MagiskFragment<HomeViewModel, FragmentMagiskBinding>(),
|
class HomeFragment : MagiskFragment<HomeViewModel, FragmentMagiskBinding>(),
|
||||||
ISafetyNetHelper.Callback {
|
SafetyNetHelper.Callback {
|
||||||
|
|
||||||
override val layoutRes: Int = R.layout.fragment_magisk
|
override val layoutRes: Int = R.layout.fragment_magisk
|
||||||
override val viewModel: HomeViewModel by viewModel()
|
override val viewModel: HomeViewModel by viewModel()
|
||||||
@ -101,8 +101,8 @@ class HomeFragment : MagiskFragment<HomeViewModel, FragmentMagiskBinding>(),
|
|||||||
val clazz = loader.loadClass("com.topjohnwu.snet.Snet")
|
val clazz = loader.loadClass("com.topjohnwu.snet.Snet")
|
||||||
val helper = clazz.getMethod("newHelper",
|
val helper = clazz.getMethod("newHelper",
|
||||||
Class::class.java, String::class.java, Activity::class.java, Any::class.java)
|
Class::class.java, String::class.java, Activity::class.java, Any::class.java)
|
||||||
.invoke(null, ISafetyNetHelper::class.java, EXT_APK.path,
|
.invoke(null, SafetyNetHelper::class.java, EXT_APK.path,
|
||||||
requireActivity(), this) as ISafetyNetHelper
|
activity, this) as SafetyNetHelper
|
||||||
if (helper.version < Const.SNET_EXT_VER)
|
if (helper.version < Const.SNET_EXT_VER)
|
||||||
throw Exception()
|
throw Exception()
|
||||||
helper.attest()
|
helper.attest()
|
||||||
|
@ -12,7 +12,7 @@ import com.topjohnwu.magisk.extensions.toggle
|
|||||||
import com.topjohnwu.magisk.model.events.*
|
import com.topjohnwu.magisk.model.events.*
|
||||||
import com.topjohnwu.magisk.model.observer.Observer
|
import com.topjohnwu.magisk.model.observer.Observer
|
||||||
import com.topjohnwu.magisk.ui.base.MagiskViewModel
|
import com.topjohnwu.magisk.ui.base.MagiskViewModel
|
||||||
import com.topjohnwu.magisk.utils.ISafetyNetHelper
|
import com.topjohnwu.magisk.utils.SafetyNetHelper
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
|
|
||||||
enum class SafetyNetState {
|
enum class SafetyNetState {
|
||||||
@ -142,8 +142,8 @@ class HomeViewModel(
|
|||||||
|
|
||||||
fun finishSafetyNetCheck(response: Int) = when {
|
fun finishSafetyNetCheck(response: Int) = when {
|
||||||
response and 0x0F == 0 -> {
|
response and 0x0F == 0 -> {
|
||||||
val hasCtsPassed = response and ISafetyNetHelper.CTS_PASS != 0
|
val hasCtsPassed = response and SafetyNetHelper.CTS_PASS != 0
|
||||||
val hasBasicIntegrityPassed = response and ISafetyNetHelper.BASIC_PASS != 0
|
val hasBasicIntegrityPassed = response and SafetyNetHelper.BASIC_PASS != 0
|
||||||
safetyNetTitle.value = R.string.safetyNet_check_success
|
safetyNetTitle.value = R.string.safetyNet_check_success
|
||||||
ctsState.value = if (hasCtsPassed) {
|
ctsState.value = if (hasCtsPassed) {
|
||||||
SafetyNetState.PASS
|
SafetyNetState.PASS
|
||||||
@ -164,7 +164,7 @@ class HomeViewModel(
|
|||||||
ctsState.value = SafetyNetState.IDLE
|
ctsState.value = SafetyNetState.IDLE
|
||||||
basicIntegrityState.value = SafetyNetState.IDLE
|
basicIntegrityState.value = SafetyNetState.IDLE
|
||||||
safetyNetTitle.value = when (response) {
|
safetyNetTitle.value = when (response) {
|
||||||
ISafetyNetHelper.RESPONSE_ERR -> R.string.safetyNet_res_invalid
|
SafetyNetHelper.RESPONSE_ERR -> R.string.safetyNet_res_invalid
|
||||||
else -> R.string.safetyNet_api_error
|
else -> R.string.safetyNet_api_error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.utils;
|
|
||||||
|
|
||||||
public interface ISafetyNetHelper {
|
|
||||||
|
|
||||||
int RESPONSE_ERR = 0x01;
|
|
||||||
int CONNECTION_FAIL = 0x02;
|
|
||||||
|
|
||||||
int BASIC_PASS = 0x10;
|
|
||||||
int CTS_PASS = 0x20;
|
|
||||||
|
|
||||||
void attest();
|
|
||||||
|
|
||||||
int getVersion();
|
|
||||||
|
|
||||||
interface Callback {
|
|
||||||
void onResponse(int responseCode);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.topjohnwu.magisk.utils
|
||||||
|
|
||||||
|
interface SafetyNetHelper {
|
||||||
|
|
||||||
|
val version: Int
|
||||||
|
|
||||||
|
fun attest()
|
||||||
|
|
||||||
|
interface Callback {
|
||||||
|
fun onResponse(responseCode: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val RESPONSE_ERR = 0x01
|
||||||
|
val CONNECTION_FAIL = 0x02
|
||||||
|
|
||||||
|
val BASIC_PASS = 0x10
|
||||||
|
val CTS_PASS = 0x20
|
||||||
|
}
|
||||||
|
}
|
@ -1,61 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.utils;
|
|
||||||
|
|
||||||
import android.net.LocalSocket;
|
|
||||||
import android.net.LocalSocketAddress;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.DataInputStream;
|
|
||||||
import java.io.DataOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public abstract class SuConnector {
|
|
||||||
|
|
||||||
private LocalSocket socket;
|
|
||||||
protected DataOutputStream out;
|
|
||||||
protected DataInputStream in;
|
|
||||||
|
|
||||||
protected SuConnector(String name) throws IOException {
|
|
||||||
socket = new LocalSocket();
|
|
||||||
socket.connect(new LocalSocketAddress(name, LocalSocketAddress.Namespace.ABSTRACT));
|
|
||||||
out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
|
|
||||||
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private String readString() throws IOException {
|
|
||||||
int len = in.readInt();
|
|
||||||
byte[] buf = new byte[len];
|
|
||||||
in.readFully(buf);
|
|
||||||
return new String(buf, "UTF-8");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bundle readSocketInput() throws IOException {
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
while (true) {
|
|
||||||
String name = readString();
|
|
||||||
if (TextUtils.equals(name, "eof"))
|
|
||||||
break;
|
|
||||||
bundle.putString(name, readString());
|
|
||||||
}
|
|
||||||
return bundle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void response() {
|
|
||||||
try {
|
|
||||||
onResponse();
|
|
||||||
out.flush();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
in.close();
|
|
||||||
out.close();
|
|
||||||
socket.close();
|
|
||||||
} catch (IOException ignored) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void onResponse() throws IOException;
|
|
||||||
|
|
||||||
}
|
|
60
app/src/main/java/com/topjohnwu/magisk/utils/SuConnector.kt
Normal file
60
app/src/main/java/com/topjohnwu/magisk/utils/SuConnector.kt
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package com.topjohnwu.magisk.utils
|
||||||
|
|
||||||
|
import android.net.LocalSocket
|
||||||
|
import android.net.LocalSocketAddress
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.text.TextUtils
|
||||||
|
import timber.log.Timber
|
||||||
|
import java.io.*
|
||||||
|
import java.nio.charset.Charset
|
||||||
|
|
||||||
|
abstract class SuConnector @Throws(IOException::class)
|
||||||
|
protected constructor(name: String) {
|
||||||
|
|
||||||
|
private val socket: LocalSocket = LocalSocket()
|
||||||
|
protected var out: DataOutputStream
|
||||||
|
protected var input: DataInputStream
|
||||||
|
|
||||||
|
init {
|
||||||
|
socket.connect(LocalSocketAddress(name, LocalSocketAddress.Namespace.ABSTRACT))
|
||||||
|
out = DataOutputStream(BufferedOutputStream(socket.outputStream))
|
||||||
|
input = DataInputStream(BufferedInputStream(socket.inputStream))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
private fun readString(): String {
|
||||||
|
val len = input.readInt()
|
||||||
|
val buf = ByteArray(len)
|
||||||
|
input.readFully(buf)
|
||||||
|
return String(buf, Charset.forName("UTF-8"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun readSocketInput(): Bundle {
|
||||||
|
val bundle = Bundle()
|
||||||
|
while (true) {
|
||||||
|
val name = readString()
|
||||||
|
if (TextUtils.equals(name, "eof"))
|
||||||
|
break
|
||||||
|
bundle.putString(name, readString())
|
||||||
|
}
|
||||||
|
return bundle
|
||||||
|
}
|
||||||
|
|
||||||
|
fun response() {
|
||||||
|
runCatching {
|
||||||
|
onResponse()
|
||||||
|
out.flush()
|
||||||
|
}.onFailure { Timber.e(it) }
|
||||||
|
|
||||||
|
runCatching {
|
||||||
|
input.close()
|
||||||
|
out.close()
|
||||||
|
socket.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
protected abstract fun onResponse()
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user