diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b0840da..536d8a8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -20,6 +20,7 @@ 1) { - FileZipper zz = new FileZipper(output, fileUriZ, launcherActivity.getContentResolver()); + FileZipper zz = new FileZipper(output, fileUriZ, MyApp.getInstance().getContentResolver()); zz.run(); } else { byte[] buffer = new byte[8 * 1024 * 1024];//8M diff --git a/app/src/main/java/com/sibyl/httpfiledominator/MyApp.kt b/app/src/main/java/com/sibyl/httpfiledominator/MyApp.kt new file mode 100644 index 0000000..f3e2885 --- /dev/null +++ b/app/src/main/java/com/sibyl/httpfiledominator/MyApp.kt @@ -0,0 +1,18 @@ +package com.sibyl.httpfiledominator + +import android.app.Application + +/** + * @author Sasuke on 2020/6/23. + */ +class MyApp : Application(){ + companion object{ + @JvmStatic + var instance: MyApp? = null + } + + override fun onCreate() { + super.onCreate() + instance = this + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sibyl/httpfiledominator/MyHttpServer.java b/app/src/main/java/com/sibyl/httpfiledominator/MyHttpServer.java index d2c6de5..43ef9eb 100644 --- a/app/src/main/java/com/sibyl/httpfiledominator/MyHttpServer.java +++ b/app/src/main/java/com/sibyl/httpfiledominator/MyHttpServer.java @@ -68,7 +68,6 @@ public class MyHttpServer extends Thread { // by design, we only serve one file at a time. - private static final ExecutorService threadPool = Executors.newCachedThreadPool(); private static int port; private static ArrayList fileUris = new ArrayList<>();//主列表 @@ -128,17 +127,6 @@ public static void setClipboardUris(ArrayList newUris){ MyHttpServer.clipboardUris = newUris; } - /**根据类型来传uri们*/ - public static void addAllUrisByMode(boolean isClipboardMode, ArrayList newUris) { - if (isClipboardMode) { - clipboardUris.addAll(newUris); - fileUris = clipboardUris; - } else { - normalUris.addAll(newUris); - fileUris = normalUris; - } - } - public static void changeUrisByMode(boolean isClipboardMode){ fileUris = isClipboardMode? clipboardUris : normalUris; } @@ -215,7 +203,7 @@ public synchronized void stopServer() { } } - public CharSequence[] listOfIpAddresses() { + public ArrayList listOfIpAddresses() { ArrayList arrayOfIps = new ArrayList(); @@ -259,9 +247,9 @@ public int compare(String o1, String o2) { } }); - CharSequence[] output = arrayOfIps.toArray(new CharSequence[arrayOfIps - .size()]); - return output; +// CharSequence[] output = arrayOfIps.toArray(new CharSequence[arrayOfIps +// .size()]); + return arrayOfIps; } private boolean normalBind(int thePort) { diff --git a/app/src/main/java/com/sibyl/httpfiledominator/activities/BaseActivity.kt b/app/src/main/java/com/sibyl/httpfiledominator/activities/BaseActivity.kt index 3219e54..0bae6d4 100644 --- a/app/src/main/java/com/sibyl/httpfiledominator/activities/BaseActivity.kt +++ b/app/src/main/java/com/sibyl/httpfiledominator/activities/BaseActivity.kt @@ -1,9 +1,30 @@ package com.sibyl.httpfiledominator.activities +import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.widget.Toolbar +import com.sibyl.httpfiledominator.R /** * @author Sasuke on 2020/6/23. */ -class BaseActivity: AppCompatActivity() { +open class BaseActivity: AppCompatActivity() { + companion object{ + val HANDLER_CONNECTION_START = 42 + val HANDLER_CONNECTION_END = 4242 + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + } + + fun initUIAfter(toolbar: Toolbar){ + window.navigationBarColor = resources.getColor(R.color.main_activity_background_color, null) + //设置ActionBar + setSupportActionBar(toolbar.apply { + setTitle(getString(R.string.app_name)) + setTitleTextColor(getResources().getColor(R.color.light_blue, null)) + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/sibyl/httpfiledominator/activities/MainActivity0.java b/app/src/main/java/com/sibyl/httpfiledominator/activities/MainActivity0.java index 25bc9f7..46de499 100644 --- a/app/src/main/java/com/sibyl/httpfiledominator/activities/MainActivity0.java +++ b/app/src/main/java/com/sibyl/httpfiledominator/activities/MainActivity0.java @@ -412,8 +412,7 @@ private ArrayList getIntentFileUris(Intent dataIntent) { } private ArrayList getUrisForActionSendMultiple(Intent dataIntent, ArrayList theUris) { - ArrayList list = dataIntent - .getParcelableArrayListExtra(Intent.EXTRA_STREAM); + ArrayList list = dataIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); if (list != null) { for (Parcelable parcelable : list) { Uri stream = (Uri) parcelable; @@ -506,7 +505,8 @@ protected void initHttpServer(ArrayList myUris) { } notiDominator.showNotifi(); httpServer = new MyHttpServer(1120); - listOfServerUris = httpServer.listOfIpAddresses(); + //注释掉防报错 +// listOfServerUris = httpServer.listOfIpAddresses(); preferredServerUrl = listOfServerUris[0].toString(); showIPText(); diff --git a/app/src/main/java/com/sibyl/httpfiledominator/mainactivity/model/MainModel.kt b/app/src/main/java/com/sibyl/httpfiledominator/mainactivity/model/MainModel.kt index d2fdf12..2603e07 100644 --- a/app/src/main/java/com/sibyl/httpfiledominator/mainactivity/model/MainModel.kt +++ b/app/src/main/java/com/sibyl/httpfiledominator/mainactivity/model/MainModel.kt @@ -1,11 +1,84 @@ package com.sibyl.httpfiledominator.mainactivity.model +import android.content.Intent +import android.os.Handler +import android.os.Looper +import androidx.databinding.ObservableField +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.sibyl.httpfiledominator.MyHttpServer +import com.sibyl.httpfiledominator.UriInterpretation import com.sibyl.httpfiledominator.mainactivity.repo.MainRepo +import kotlinx.coroutines.launch /** * @author HUANGSHI-PC on 2020-03-06 0006. */ -class MainModel(val repo: MainRepo): ViewModel() { +class MainModel(val repo: MainRepo) : ViewModel() { + val isLoading = MutableLiveData().apply { value = false } + + val snackbarMsg = MutableLiveData().apply { value = "" } + + val httpServer = MutableLiveData() + /**默认显示的IP地址*/ + val preferredServerUrl = ObservableField() + /**服务器IP地址集*/ + val listOfServerUris = MutableLiveData>() + + /**每次加的新数据缓存在这里*/ + val newUrisCache = MutableLiveData>() + + /**是否剪切板模式*/ + val isClipboardMode = MutableLiveData().apply { value = false } + + /**处理刚进页面时传入的Intent*/ + fun dealWithNewIntent(intent: Intent?) = viewModelScope.launch { +// if (isFinishing()) conti.resumeWithException(Exception("")) + if (intent?.extras != null) isLoading.value = true + try { + intent?.extras?.let { + val sharedUriList = repo.getIntentFileUris(intent) + dealWithNewUris(sharedUriList) + } + } catch (e: Exception) { + snackbarMsg.value = e.message + }finally { + isLoading.value = false + } + } + + /**处理ActivityResult传入的Intent*/ + fun dealActivityResultIntent(intent: Intent?) = viewModelScope.launch { + if (intent != null) isLoading.value = true + try { + val newUriList = repo.getActivityResultUris(intent) + dealWithNewUris(newUriList) + } catch (e: Exception) { + snackbarMsg.value = e.message + }finally { + isLoading.value = false + } + } + + + + /**对新uri的处理*/ + fun dealWithNewUris(newUriList: MutableList?) = viewModelScope.launch { + //先过滤一波已经添加过的 + newUriList?.removeAll(MyHttpServer.getNormalUris()) + if (newUriList.isNullOrEmpty()) return@launch + //如果没有建立起http服务时========== + if (httpServer.value == null){ + httpServer.value = MyHttpServer(1120) + } + MyHttpServer.getNormalUris().addAll(newUriList) + //显示到UI + newUrisCache.value = newUriList + MyHttpServer.changeUrisByMode(false) + //切换模式 + isClipboardMode.value = false + } + } \ No newline at end of file diff --git a/app/src/main/java/com/sibyl/httpfiledominator/mainactivity/repo/MainRepo.kt b/app/src/main/java/com/sibyl/httpfiledominator/mainactivity/repo/MainRepo.kt index 36f4c26..4d92864 100644 --- a/app/src/main/java/com/sibyl/httpfiledominator/mainactivity/repo/MainRepo.kt +++ b/app/src/main/java/com/sibyl/httpfiledominator/mainactivity/repo/MainRepo.kt @@ -1,7 +1,63 @@ package com.sibyl.httpfiledominator.mainactivity.repo +import android.content.Intent +import android.net.Uri +import android.os.Parcelable +import com.sibyl.httpfiledominator.MyApp +import com.sibyl.httpfiledominator.UriInterpretation +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + /** * @author HUANGSHI-PC on 2020-03-06 0006. */ class MainRepo { + + /** + * 以下是从SendFileActivity里拷过来的。用来接收直接从外面分享进来的文件, + * 原SendFileActivity已废弃 + */ + suspend fun getIntentFileUris(dataIntent: Intent): MutableList? = withContext(Dispatchers.IO) { + val theUris = mutableListOf() + if (Intent.ACTION_SEND_MULTIPLE == dataIntent.action) { + dataIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM)?.forEach { + it?.let { theUris.add(UriInterpretation(it as Uri, MyApp.instance?.contentResolver)) } + } + return@withContext theUris + } + val extras = dataIntent.extras + if (extras == null) {//直接手动进的主页,不会存在传intent数据的情况 + throw Exception() + } + var myUri: Uri? = extras[Intent.EXTRA_STREAM] as Uri + if (myUri == null) { + val tempString = extras[Intent.EXTRA_TEXT] as String? + if (tempString == null) { + throw Exception("Error obtaining the file path") + } + myUri = Uri.parse(tempString) + if (myUri == null) { + throw Exception("Error obtaining the file path") + } + } + theUris.add(UriInterpretation(myUri, MyApp.instance?.getContentResolver())) + theUris + } + + /**处理onActivityResult()里的新数据*/ + suspend fun getActivityResultUris(data: Intent?): MutableList = withContext(Dispatchers.IO) { + val theUris = mutableListOf() + val dataUri = data?.getData() + if (dataUri != null) { + theUris.add(UriInterpretation(dataUri, MyApp.instance?.getContentResolver())) + } else { + val clipData = data?.getClipData() + for (i in 0 until (clipData?.itemCount ?: 0)) { + val item = clipData?.getItemAt(i) + val uri = item?.uri + theUris.add(UriInterpretation(uri, MyApp.instance?.getContentResolver())) + } + } + theUris + } } \ No newline at end of file diff --git a/app/src/main/java/com/sibyl/httpfiledominator/mainactivity/view/MainActivity.kt b/app/src/main/java/com/sibyl/httpfiledominator/mainactivity/view/MainActivity.kt index 362bef8..0576db0 100644 --- a/app/src/main/java/com/sibyl/httpfiledominator/mainactivity/view/MainActivity.kt +++ b/app/src/main/java/com/sibyl/httpfiledominator/mainactivity/view/MainActivity.kt @@ -1,34 +1,304 @@ package com.sibyl.httpfiledominator.mainactivity.view -import android.os.Build -import android.os.Bundle -import android.view.WindowManager -import androidx.appcompat.app.AppCompatActivity +import android.Manifest +import android.app.Activity +import android.app.AlertDialog +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Context +import android.content.Intent +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.os.* +import android.text.TextUtils +import android.view.LayoutInflater +import android.view.View +import android.widget.ImageButton +import android.widget.ImageView +import android.widget.TextView import androidx.databinding.DataBindingUtil +import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders +import com.hjq.permissions.OnPermission +import com.hjq.permissions.XXPermissions +import com.sibyl.httpfiledominator.LoadWaitDominator +import com.sibyl.httpfiledominator.MyHttpServer import com.sibyl.httpfiledominator.R +import com.sibyl.httpfiledominator.UriInterpretation +import com.sibyl.httpfiledominator.activities.BaseActivity import com.sibyl.httpfiledominator.databinding.ActivityMainBinding import com.sibyl.httpfiledominator.mainactivity.model.MainModel import com.sibyl.httpfiledominator.mainactivity.repo.MainModelFactory import com.sibyl.httpfiledominator.mainactivity.repo.MainRepo +import com.sibyl.httpfiledominator.utils.* +import kotlinx.android.synthetic.main.activity_main.* +import kotlinx.android.synthetic.main.link_layout.* +import kotlinx.android.synthetic.main.toolbar.toolbar -class MainActivity : AppCompatActivity() { +open class MainActivity : BaseActivity() { + companion object { + const val REQUEST_CODE = 1024 + const val HANDLER_CONNECTION_START = 42 + const val HANDLER_CONNECTION_END = 4242 + } val binding by lazy { DataBindingUtil.setContentView(this, R.layout.activity_main) } - val loginModel by lazy{ ViewModelProviders.of(this, MainModelFactory(MainRepo())).get(MainModel::class.java) } + val mainModel by lazy { ViewModelProviders.of(this, MainModelFactory(MainRepo())).get(MainModel::class.java) } + + + protected var loadWait: LoadWaitDominator? = null + + val notiDominator by lazy { NotiDominator(this) } + override fun onCreate(savedInstanceState: Bundle?) { - window.setBackgroundDrawable(null) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) +// window.setBackgroundDrawable(null) +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) super.onCreate(savedInstanceState) + if (intent.getBooleanExtra("isStopServer", false)) { + stopServer() + finish() + } bind() + setObservers() + setListeners() + grantPermissions() //操你妈6.0权限 + mainModel.dealWithNewIntent(intent) + } + override fun onNewIntent(newIntent: Intent?) { + super.onNewIntent(newIntent) + if (newIntent?.getBooleanExtra("isStopServer", false) ?: false) { + newIntent?.putExtra("isStopServer", false) + stopServer() + finish() + } + mainModel.dealWithNewIntent(intent) } - fun bind(){ + /**绑他妈的*/ + fun bind() { binding.apply { + model = mainModel + loadWait = LoadWaitDominator(this@MainActivity, containerLayout) + + } + initUIAfter(toolbar) + } + + /**观察者们*/ + fun setObservers() { + mainModel.run { + //loadWait状态 + isLoading.observe(this@MainActivity, Observer { + loadWait?.show(if (it) LoadWaitDominator.LOADING else LoadWaitDominator.DISMISS) + }) + //snackbar的显示 + snackbarMsg.observe(this@MainActivity, Observer { if (it.isNotBlank()) showSnackbar(fab, it) }) + + //httpServer的初始化 + httpServer.observe(this@MainActivity, Observer { + if (it == null) return@Observer + listOfServerUris.value = it.listOfIpAddresses().apply { + preferredServerUrl.set(this[0]) + } + //不需要了,直接用数据绑定来更新 +// runOnUiThread { link_msg.text = preferredServerUrl.get() ?: "" } + }) + + //新加数据时 + newUrisCache.observe(this@MainActivity, Observer { newUriList -> + if (isFinishing) return@Observer + runOnUiThread { + newUriList.forEach { + val view = LayoutInflater.from(this@MainActivity) + .inflate(R.layout.flex_item, fileNameContainer, false) + view.tag = it //把uriInterpretation保存到tag,到时候点击时用它来找到实时的index + view.findViewById(R.id.itemNameTv).text = it.path + view.findViewById(R.id.isFolderIcon).visibility = if (it.isDirectory) View.VISIBLE else View.GONE + view.findViewById(R.id.itemDeleteBtn).setOnClickListener { + val deleteIndex = MyHttpServer.getNormalUris().indexOf(view.tag as UriInterpretation) + if (deleteIndex != -1) { + fileNameContainer.removeViewAt(deleteIndex) + MyHttpServer.getNormalUris().removeAt(deleteIndex) + //如果删光了 + if (MyHttpServer.getNormalUris().isEmpty()) { + mainModel.preferredServerUrl.set("") + stopServer() + showSnackbar(fab, getString(R.string.files_clear_stop_server)) + } + } + }//setOnClickListener + fileNameContainer.addView(view) + notiDominator.showNotifi() + } + } + }) + + //模式切换时(剪切板 or 普通模式) + isClipboardMode.observe(this@MainActivity, Observer { + MyHttpServer.changeUrisByMode(it)//切换主url + refreshClipModeVisibility(it)//切换组件显示状态 + showSnackbar(fab, getString(if (it) R.string.clipboard_mode_on else R.string.clipboard_mode_off)) + }) + } + } + + /**挂监听器*/ + fun setListeners() { + fab.setOnClickListener { + val intent = Intent(Intent.ACTION_GET_CONTENT) + intent.addCategory(Intent.CATEGORY_OPENABLE) + intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true) + intent.type = "*/*" + startActivityForResult(intent, REQUEST_CODE) + } + + clipboardBtn.setOnClickListener { + mainModel.isClipboardMode.value = !(mainModel.isClipboardMode.value ?:false) + } + + copyBtn.setOnClickListener { + //不允许复制的情况 + if (TextUtils.isEmpty(link_msg.text.toString())) { + showSnackbar(fab, getString(R.string.pls_add_first)) + return@setOnClickListener + } + //开始复制 + (getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager).primaryClip = + ClipData.newPlainText(mainModel.preferredServerUrl.get(), mainModel.preferredServerUrl.get()) + showSnackbar(fab, getString(R.string.url_clipboard)) + } + + qrcodeBtn.setOnClickListener { + if (TextUtils.isEmpty(link_msg.text.toString())) { + showSnackbar(fab, getString(R.string.pls_add_first)) + return@setOnClickListener + } + qrCodeDialog?.show() + } + } + + /**根据模式的不同,切换不同的组件显示状态*/ + fun refreshClipModeVisibility(isClipboardMode: Boolean) { + runOnUiThread { + clipboardBtn.setImageResource(if (isClipboardMode) R.drawable.ic_clipboard_on else R.drawable.ic_clipboard_off) + clipboardContainer.visibility = if (isClipboardMode) View.VISIBLE else View.GONE + fileNameContainer.visibility = if (isClipboardMode) View.GONE else View.VISIBLE + if (isClipboardMode) { + fab.hide() + } else { + fab.show() + } + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) { + mainModel.dealActivityResultIntent(data) + } + } + + /**二维码弹窗*/ + val qrCodeDialog: AlertDialog? by lazy { + val view = LayoutInflater.from(this).inflate(R.layout.qrcode_dialog_layout, null, false) + view.findViewById(R.id.dismissBtn).setOnClickListener { qrCodeDialog?.dismiss() } + val dialog = AlertDialog.Builder(this).setView(view) + .setCancelable(false) + .create() + val window = dialog.getWindow() + if (window != null) { + window.setContentView(view) + window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + val p = window.attributes //获取对话框当前的参数值 + // p.height = DensityUtil.dp2px(350); + p.width = DensityUtil.dp2px(350f) + window.attributes = p //设置生效 + } + val qrcodeBmp = ZxingCodeTool.create2DCode(link_msg.getText().toString(), DensityUtil.dp2px(350f), DensityUtil.dp2px(350f)) + (dialog.findViewById(R.id.qrcodeImage) as ImageView).setImageBitmap(qrcodeBmp) + dialog + } + + val mHandler: Handler by lazy { + object : Handler(Looper.getMainLooper()) { + override fun handleMessage(inputMessage: Message) { + when (inputMessage.what) { + HANDLER_CONNECTION_START -> { + val msg = String.format(getString(R.string.connected_ip), inputMessage.obj as String) + showSnackbar(findViewById(android.R.id.content), msg) + } + HANDLER_CONNECTION_END -> { + val msg2 = String.format(getString(R.string.disconnected_ip), inputMessage.obj as String) + showSnackbar(findViewById(android.R.id.content), msg2) + } + else -> super.handleMessage(inputMessage) + } + } + } + } + + private fun stopServer() { + notiDominator.dismissAll(this) + mainModel.httpServer.run { + value?.stopServer() + value = null + } + MyHttpServer.clearFiles() + } + + override fun onDestroy() { + stopServer() + super.onDestroy() + } + + /** + * 6.0的权限 + */ + private fun grantPermissions() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + XXPermissions.with(this) + .constantRequest() //可设置被拒绝后继续申请,直到用户授权或者永久拒绝 + //.permission(Permission.SYSTEM_ALERT_WINDOW, Permission.REQUEST_INSTALL_PACKAGES) //支持请求6.0悬浮窗权限8.0请求安装权限 + // .permission(Permission.Group.STORAGE, Permission.Group.CALENDAR) //不指定权限则自动获取清单中的危险权限 + .permission( //存储 + Manifest.permission.WRITE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE // //电话 + // Manifest.permission.CALL_PHONE, + // Manifest.permission.READ_PHONE_STATE + // //短信 + // Manifest.permission.SEND_SMS, + // //通讯录 + // Manifest.permission.READ_PHONE_NUMBERS, + // Manifest.permission.GET_ACCOUNTS + // Manifest.permission.READ_CONTACTS + // //定位 + // Manifest.permission.ACCESS_COARSE_LOCATION, + // Manifest.permission.ACCESS_FINE_LOCATION, + // //相机 + // Manifest.permission.CAMERA + // Manifest.permission.CHANGE_NETWORK_STATE, + // Manifest.permission.WRITE_SETTINGS + //安装APK + /*Manifest.permission.REQUEST_INSTALL_PACKAGES*/ + ).request(object : OnPermission { + override fun hasPermission(granted: List, isAll: Boolean) { + if (isAll) { + BatteryOptiDominator.requestIgnoreBatteryOpti(this@MainActivity) + } + } + override fun noPermission(denied: List, quick: Boolean) { + if (quick) { + androidx.appcompat.app.AlertDialog.Builder(this@MainActivity) + .setMessage("请允许权限") + .setPositiveButton("好的") { dialog, which -> XXPermissions.gotoPermissionSettings(this@MainActivity) } + .show() + } + } + }) } } } diff --git a/app/src/main/java/com/sibyl/httpfiledominator/utils/MySnackbar.kt b/app/src/main/java/com/sibyl/httpfiledominator/utils/MySnackbar.kt index df96703..c9bbedb 100644 --- a/app/src/main/java/com/sibyl/httpfiledominator/utils/MySnackbar.kt +++ b/app/src/main/java/com/sibyl/httpfiledominator/utils/MySnackbar.kt @@ -7,8 +7,15 @@ import com.sibyl.httpfiledominator.R /** * @author Sasuke on 2020/6/21. */ +//SasukeTodo 重构完了记得把这个删掉,这是用来兼容老MainActivity的 fun show(view: View,msg: String){ Snackbar.make(view,msg,Snackbar.LENGTH_LONG) .apply { getView().setBackgroundResource(R.color.snackbar_background_color) } .show() +} + +fun showSnackbar(view: View,msg: String){ + Snackbar.make(view,msg,Snackbar.LENGTH_LONG) + .apply { getView().setBackgroundResource(R.color.snackbar_background_color) } + .show() } \ No newline at end of file diff --git a/app/src/main/java/com/sibyl/httpfiledominator/utils/ThreadManager.java b/app/src/main/java/com/sibyl/httpfiledominator/utils/ThreadManager.java index 303d069..3b7d4a1 100644 --- a/app/src/main/java/com/sibyl/httpfiledominator/utils/ThreadManager.java +++ b/app/src/main/java/com/sibyl/httpfiledominator/utils/ThreadManager.java @@ -14,7 +14,7 @@ * @date 2017/10/20 */ public class ThreadManager { - public static ThreadPool instance; + private static ThreadPool instance; /** * 获取单例的线程池对象 diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 494e65a..835d266 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,9 +1,13 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:bind="http://schemas.android.com/tools"> + - - + + - - diff --git a/app/src/main/res/layout/link_layout.xml b/app/src/main/res/layout/link_layout.xml index c5e210c..fb635d6 100644 --- a/app/src/main/res/layout/link_layout.xml +++ b/app/src/main/res/layout/link_layout.xml @@ -1,86 +1,96 @@ - - + - + + + + + android:gravity="center_vertical" + android:orientation="horizontal" + android:layout_marginBottom="6dp" + android:paddingRight="8dp" + android:paddingLeft="5dp"> + + + - - + + - - - - - - - - - + + + + + + + + + - + - + - + - \ No newline at end of file + + \ No newline at end of file