리스트에 들어가 있는 스위치 아이템

뷰에있는 스위치의 포지션을 가지고 싶다.

하지만 어뎁터에서 액티비티로 데이터를 이동할 방법이 제공되지 않는다.

어뎁터에 인터페에이스를 따로 등록하여 가져와 보도록 하자.

 

엑티비티

class VhclViewActivity : BaseActivity<ActivityVhclBinding, VhclViewModel>(),VhcleAdapter.OnItemClickEventListener, VhcleCallBack {
 
    override val resId: Int = R.layout.activity_vhcl
    override val viewModel: VhclViewModel by viewModel()
    lateinit var mAdapter: VhcleAdapter
    val switchList = mutableListOf<Int>()
    override fun initView() {
        binding.vm = viewModel
    }


    override fun initBinding() {

        //TODO 임시
        val list= ArrayList<VhcleInfoDto>()
        list.add(VhcleInfoDto("1","1","1","1",0,0,"1",0,0,"1","1","1","1","1","1","1","1","1","1"))

        setRecyclerView(list)
    }


    private fun setRecyclerView(
        data: ArrayList<VhcleInfoDto>
    ) {
        mAdapter = VhcleAdapter(
            data,
            this
        )
        mAdapter.setOnItemClickListener(this)
        if (binding.vhcleRecyclerView.adapter == null) {

            binding.vhcleRecyclerView.layoutManager = LinearLayoutManager(this)
            binding.vhcleRecyclerView.adapter = mAdapter
        } else {
            binding.vhcleRecyclerView.adapter = mAdapter
        }
    }

    override fun onItemClick(position: Int,state:String) {
        //어뎁터에서 포지션값과 스위치 (on ,off) 에 따른 리스트 데이터 추가및 삭제
        if(state.equals("put"))
        switchList.add(position)
        else
        switchList.remove(position)
    }
}

 

어뎁터

class VhcleAdapter(
    private val dataSet: ArrayList<VhcleInfoDto>,
    private val callBack: VhcleCallBack
) : RecyclerView.Adapter<VhcleAdapter.ViewHolder>() {
    private var mItemClickListener: VhcleAdapter.OnItemClickEventListener? = null


    //customViewHolder
    class ViewHolder(
        private val binding: LayoutVhcleItemBinding,
        private val callBack: VhcleCallBack,
        private val itemClickListener: VhcleAdapter.OnItemClickEventListener?
    ) : RecyclerView.ViewHolder(binding.root) {

        private val mContext: Context = binding.root.context

        fun bind(data: VhcleInfoDto, position: Int, maxSize: Int) {

            binding.vhcleSwitch.setOnClickListener {
               if(binding.vhcleSwitch.isChecked)
               itemClickListener?.onItemClick(position,"put")
               else
               itemClickListener?.onItemClick(position,"out")

            }
        }
    }

    // Create new views (invoked by the layout manager)
    override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
        // Create a new view, which defines the UI of the list item
        val binding =
            LayoutVhcleItemBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
        return ViewHolder(
            binding,
            callBack,
            mItemClickListener
        )
    }
    fun setOnItemClickListener(listener: OnItemClickEventListener) {
        mItemClickListener = listener
    }
 
    override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
        // Get element from your dataset at this position and replace the
        // contents of the view with that element
        viewHolder.bind(dataSet[position], position, itemCount)
    }

    // Return the size of your dataset (invoked by the layout manager)
    override fun getItemCount() = dataSet.size


    override fun getItemViewType(position: Int): Int {
        return position
    }

    //액티비티로 보내지는 아이템 값 얻기
    interface OnItemClickEventListener {
        fun onItemClick(position: Int,state: String)
    }

}

 

스위치정보를 액티비티에서 가져왔다.

'프로그래밍 > kotlin' 카테고리의 다른 글

[Kotlin] 뷰 이미지 리사이징  (0) 2023.07.13
[Kotlin] drag and drop event (드래그드롭이벤트)  (0) 2023.07.13
루팅 체크 !  (0) 2023.04.03
공용 로딩바 만들기  (0) 2023.03.20
[kotlin]내부저장소 사용하기  (0) 2023.03.17

앱 루팅을 체크해보자 

 

https://als2019.tistory.com/84 상당히 설명이 잘된 블로그 다음에 다시봐야겠다.

https://saltlee.tistory.com/155 여기도 정리가 잘됨 참고 

본인의 앱에서는 앱이 첫실행될때만 체크하고 있지만 참고내용을 보면 주기적으로 실행해주는게 좋다고한다 앱을 실행후 루팅을 할 수 있기 때문이다. 

 

fun RootChecker(){
    if(RootChecker(getContext()).isDeviceRooted()){
        Toast.makeText(this, getString(R.string.error_modulate_os), Toast.LENGTH_SHORT).show()

        moveTaskToBack(true)
        if (Build.VERSION.SDK_INT >= 21) {
            finishAndRemoveTask()
        } else {
            finish()
        }
        exitProcess(0)
    }
}

 

fun isDeviceRooted(): Boolean {
    return checkRootFiles() || checkSUExist() || checkRootPackages()
}

 

 

1. 루팅파일 체크 

private fun checkRootFiles(): Boolean {
    for (path in rootFiles) {
        try {
            if (File(path).exists()) {
                return true
            }
        } catch (e: RuntimeException) {

        }
    }
    return false
}

 private val rootFiles = arrayOf(
        "/system/app/Superuser.apk",
        "/sbin/su",
        "/system/bin/su",
        "/system/xbin/su",
        "/system/usr/we-need-root/",
        "/data/local/xbin/su",
        "/data/local/bin/su",
        "/system/sd/xbin/su",
        "/system/bin/failsafe/su",
        "/data/local/su",
        "/su/bin/su",
        "/su/bin",
        "/system/xbin/daemonsu"
    )

 

2. 루팅 os 체크

private fun checkSUExist(): Boolean {
    var process: Process? = null
    val su = arrayOf("/system/xbin/which", "su")
    try {
        process = runtime.exec(su)
        BufferedReader(
            InputStreamReader(
                process.inputStream,
                Charset.forName("UTF-8")
            )
        ).use { reader -> return reader.readLine() != null }
    } catch (e: IOException) {

    } catch (e: Exception) {

    } finally {
        process?.destroy()
    }
    return false
}

    private val runtime by lazy {
        Runtime.getRuntime()
    }

 

3. 루팅 패키지 체크

private fun checkRootPackages(): Boolean {
    val pm = context.packageManager
    if (pm != null) {
        for (pkg in rootPackages) {
            try {
                pm.getPackageInfo(pkg, 0)
                return true
            } catch (ignored: PackageManager.NameNotFoundException) {
                // fine, package doesn't exist.
            }
        }
    }
    return false
}


    private val rootPackages = arrayOf(
        "com.devadvance.rootcloak",
        "com.devadvance.rootcloakplus",
        "com.koushikdutta.superuser",
        "com.thirdparty.superuser",
        "eu.chainfire.supersu",
        "de.robv.android.xposed.installer",
        "com.saurik.substrate",
        "com.zachspong.temprootremovejb",
        "com.amphoras.hidemyroot",
        "com.amphoras.hidemyrootadfree",
        "com.formyhm.hiderootPremium",
        "com.formyhm.hideroot",
        "com.noshufou.android.su",
        "com.noshufou.android.su.elite",
        "com.yellowes.su",
        "com.topjohnwu.magisk",
        "com.kingroot.kinguser",
        "com.kingo.root",
        "com.smedialink.oneclickroot",
        "com.zhiqupk.root.global",
        "com.alephzain.framaroot"
    )

 

로딩바 xml 만들기

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ProgressBar
        android:id="@+id/progress"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:textSize="50px"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/progress"
        android:textColor="@color/white"
        app:layout_constraintLeft_toLeftOf="@id/progress"
        app:layout_constraintRight_toRightOf="@id/progress"
        app:layout_constraintTop_toBottomOf="@id/progress" />
</androidx.constraintlayout.widget.ConstraintLayout>

로딩다이얼로그 만들기

object LoadingDialog {
    var dialog: Dialog? = null //obj
    fun displayLoadingWithText(context: Context?, text: String?, cancelable: Boolean) {
        dialog!!.requestWindowFeature(Window.FEATURE_NO_TITLE)
        dialog!!.setContentView(R.layout.layout_loding)
        dialog!!.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
        dialog!!.setCancelable(cancelable)
        val textView = dialog!!.findViewById<TextView>(R.id.text)
        textView.text = text
        try {
            dialog!!.show()
        } catch (e: Exception) {
        }
    }

    fun hideLoading() {
        try {
            if (dialog != null) {
                dialog!!.dismiss()
            }
        } catch (e: Exception) {
        }
    }
}

사용하기

override fun showLoading(cancelable: Boolean) {
    hideLoading()
    LoadingDialog.displayLoadingWithText(this, resources.getString(R.string.network_wait),cancelable)
}
override fun hideLoading() {
    LoadingDialog.hideLoading()
}

1. 내부저장소 권한 등록하기

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />        <!-- 내부저장소 권한 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />         <!-- 내부저장소 권한 -->

내부저장소는 사용자의 권한요청을 할 필요가 없습니다.

참고 : https://developer.android.com/training/data-storage?hl=ko

 

2. 내부저장소 파일 만들기

fun create(context){
    val filename = "파일명"
    val dir = context.filesDir
    val file = File(dir, filename)
    
    if (!file.exists() && !file.isDirectory) {
        file.createNewFile()  
    }
}

3.  내용 저장하기

fun write(context: Context, msg: String) {
    val msgBuiler = StringBuilder()

    msgBuiler.append('{')
        .append("\"item\" : " + data.getString("key")!!+ ",")
        .append("},")
        
   try {
            val filename = "파일명"
            val fileContents = msgBuiler.toString()
            context.openFileOutput(filename, Context.MODE_APPEND).use {
                it.write(fileContents.toByteArray())
                it.flush()
                it.close()
            }
    } 
    catch (e: Exception) {
        e.printStackTrace()
  	}     
}

4. 내용 지우기

fun clear(context: Context) {
    try {
        val filename = "파일명"
        val fileContents = ""
        context.openFileOutput(filename, Context.MODE_PRIVATE).use {
            it.write(fileContents.toByteArray())
            it.flush()
            it.close()
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

5. 파일 읽어오고 싶을때

fun accessFileUsingStream(context: Context): String {
    val filename = "파일명"
    val ff = context.getFileStreamPath(filename)
    val file: File = File("" + ff)
    if (file.exists()) {
        context.openFileInput(filename).bufferedReader().useLines { lines ->
            lines.fold("") { some, text ->
                "$some\n$text"
            }
        }
        if (context.openFileInput(filename).bufferedReader().readText().isNullOrBlank()) {
            return ""
        }
        var text: String
        text = context.openFileInput(filename).bufferedReader().readText()
        return text
    } else {
        return ""
    }
}

'프로그래밍 > kotlin' 카테고리의 다른 글

루팅 체크 !  (0) 2023.04.03
공용 로딩바 만들기  (0) 2023.03.20
리사이클러뷰 뷰가 꼬일때  (0) 2023.01.05
[kotlin]Handler deprecated  (0) 2022.11.10
[kotlin]locationRequest Deprecated  (0) 2022.11.10
override fun getItemViewType(position: Int): Int {
    return position
}

어뎁터에 이거 추가해주기

 

 

추가 해당 포지션을 바로 받았을때 포지션변경시 아이템 무브에서 스와이프시 한칸씩 칸이 움직일때마다 스와이프가 끊기는 버그가 생김. 해당 코드를 수정함

참조) https://reakwon.tistory.com/93

 

[안드로이드/android] RecyclerView 사용법(Recycler Adpater, View Holder, 이벤트 전달)

RecyclerView RecyclerView는 ListView와 비슷하나 조금 더 진보한 View입니다. RecyclerView는 ListView에 비해서 많은 최적화를 거치게 됐고, 수 많은 데이터를 처리하는데 효과적입니다. 그렇다면 RecyclerView가

reakwon.tistory.com

 private val TYPE_HEADER = 0
 private val TYPE_ITEM = 1
override fun getItemViewType(position: Int): Int {
    if(position==0) return TYPE_HEADER
    return TYPE_ITEM
}

 

'프로그래밍 > kotlin' 카테고리의 다른 글

공용 로딩바 만들기  (0) 2023.03.20
[kotlin]내부저장소 사용하기  (0) 2023.03.17
[kotlin]Handler deprecated  (0) 2022.11.10
[kotlin]locationRequest Deprecated  (0) 2022.11.10
[kotlin] vibrator Deprecated  (0) 2022.11.10
val handler = Handler()
val handler = Handler(Looper.getMainLooper())

위의 내용에 Looper.getMainLooper() 로 변경해주시면 됩니다

 

. -끝-

'프로그래밍 > kotlin' 카테고리의 다른 글

[kotlin]내부저장소 사용하기  (0) 2023.03.17
리사이클러뷰 뷰가 꼬일때  (0) 2023.01.05
[kotlin]locationRequest Deprecated  (0) 2022.11.10
[kotlin] vibrator Deprecated  (0) 2022.11.10
[코틀린] 핸들러  (0) 2022.07.20
  val locationRequest2 = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY,2000) //2초마다 인터발
            .setWaitForAccurateLocation(false)
            .setMinUpdateIntervalMillis(500)
            .setMaxUpdateDelayMillis(1000)
            .build();

/*
        val locationRequest = LocationRequest.create()?.apply {
            priority = LocationRequest.PRIORITY_HIGH_ACCURACY
            interval = 2 * 1000
            fastestInterval = 1 * 1000

        }
*/

주석과같이 쓰시던 내용을 변경해주시면 되겠습니다 -끗0

'프로그래밍 > kotlin' 카테고리의 다른 글

[kotlin]내부저장소 사용하기  (0) 2023.03.17
리사이클러뷰 뷰가 꼬일때  (0) 2023.01.05
[kotlin]Handler deprecated  (0) 2022.11.10
[kotlin] vibrator Deprecated  (0) 2022.11.10
[코틀린] 핸들러  (0) 2022.07.20
/* val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
                    vibrator.vibrate(500)*/

                    val vibrator = if( Build.VERSION.SDK_INT >=Build.VERSION_CODES.S){
                        val vibeManager : VibratorManager = getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager

                        vibeManager.defaultVibrator
                    }else{
                        @Suppress("DEPRECATION")
                       getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
                    }

                    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ // api level 26 이상
                        vibrator.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE))
                    }else {
                        vibrator.vibrate(500)
                    }

기존에 주석처럼 사용하던것을 아래와 같이 버전 체크를 통해 변경해주시면 됩니다. -끗

'프로그래밍 > kotlin' 카테고리의 다른 글

[kotlin]내부저장소 사용하기  (0) 2023.03.17
리사이클러뷰 뷰가 꼬일때  (0) 2023.01.05
[kotlin]Handler deprecated  (0) 2022.11.10
[kotlin]locationRequest Deprecated  (0) 2022.11.10
[코틀린] 핸들러  (0) 2022.07.20

+ Recent posts