게시판 답변

10 글 보임 - 1 에서 10 까지 (총 58 중에서)
  • 글쓴이
  • 답변: [wordpress] astra에서 view count #16919
    mimoon
    키 마스터

      ※ 이 bbpress에서는 대괄호 ‘[‘ ‘]’이 쇼코드로 인식되어 ‘jp_post_view‘이 안 보여서 한참 애먹음 반드시 ‘[jp_post_view]’로 기입할 것

      답변: 비공개: [PHP 8] get Domain & path #16903
      mimoon
      키 마스터
        
        
        /***2024-06-22 for PHP 8 
         * 2024-08-11 update for disable '$HTTP_REFERER = isset($_SERVER['HTTP_REFERER']) ?  trim($_SERVER['HTTP_REFERER']) : '';ㅍ
         * '$_SERVER['HTTP_REFERER']'는 직전 url이므로 글로벌 노드(기본) 모드에서는 $_SERVER['HTTP_REFERER']가 아닌 get current url 코드로 바꿔줘야
        */
        if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
        	$HTTP_REFERER = "https://";  
        	} else  {
        	$HTTP_REFERER = "http://"; 
        	}
        	// Append the host(domain name, ip) to the URL.   
        	$HTTP_REFERER.= $_SERVER['HTTP_HOST'];
        	// Append the requested resource location to the URL   
        	$HTTP_REFERER.= $_SERVER['REQUEST_URI'];
        	/** url or domain 확보 코드 끝 */
        	if (stripos($HTTP_REFERER,'powerbible.be') == false){
        	?>
        	<script>
        	$(document).ready(function(){
        		let agent= navigator.platform + " " + navigator.appVersion; //navigator.userAgent; //navigator.platform;
        		if (agent.length > 40) {
        			agent = agent.substr(0, 40 - 2) + '...';
            	}
        		//document.getElementById("demo").innerHTML=agent;
        		$.ajax({ 
        			url: "../inc/get_connect_info.php",
        			context: document.body,
        			error:function(request, status, error){
        				alert("페이지를 여는 데 실패했습니다. 접속 상태 등 점검이 필요합니다.");
        				history.back()
        			},
        			success: function(response){
        				get_connect_info.innerHTML = "<p style='font-size: 9px; margin-top: -.123em; margin-left: 15px; padding-left: 15px;'>" + response + "경로로 접속하셨습니다. 접속 도구: " + agent + "</p>";		
        			}
            	});
        	});
        	</script>
        	<?php
        	$your_path= "<span id='get_connect_info'>PowerBible engine 3.7a1</span>";
        } else {
        	$your_path= "PowerBible engine 3.7a1";
        }
        
        답변: 비공개: [Swiftui] server error handle #16898
        mimoon
        키 마스터
          mimoon
          키 마스터

            다음에 대해 고려할 것. 현재 먹히던 것이 안 먹힘.

            
            
            /**2024-07-18 Change the default-view of Media Library
             * 참조: 물리적 파일명은 'upload.php'이지만, 사용자 명시는 'admin_footer-' --> 'admin_footer-upload.php' 
             * 그외: add_action( 'restrict_manage_posts', 'media_library_filter_main'); // long.. 무한루프
             * add_action( 'admin_footer-post-new.php', 'media_library_filter' );
             * add_action( 'admin_footer-post.php', 'media_library_filter' );
             */
            add_action( 'admin_footer-upload.php', 'media_library_filter_main' );
            //add_action( 'admin_footer-post.php', 'media_library_filter' ); //에러?
            function media_library_filter_main() { 
            	?>
            	<script type="text/javascript">
            		/*
            		jQuery(document).on("DOMNodeInserted", function(){
            			//2024-07-29 changed 'select.attachment-filters' to '#media-attachment-filters' 
            				//jQuery('select#media-attachment-filters [value="uploaded"]').attr( 'selected', true ).parent().trigger('change');
            				jQuery('select#media-attachment-filters.attachment-filters [value="1"]').attr( 'selected', true ).parent().trigger('change');
            		});
            		*/
            		~function(doc, $) {
            			var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
            			var select = $('select.attachment-filters'); //var select = $('select'); // this is just DOM element, no jQuery
            			var observer = new MutationObserver(function(mutations) {
            				alert(mutations.length + " mutations happened");
            			});
            			// monitor descendant elements – changing <code>selected</code> attr on options
            			observer.observe(select, { subtree: true, attributes: true });
            			// this triggers Observer's reaction, but doesn't update select box UI
            			setTimeout(function () {
            				select.setAttribute('value', '0'); //select.setAttribute('value', 'whoa');
            			}, 1000);
            			
            			// this updates select box UI, but doesn't trigger mutation observer's callback
            			setTimeout(function () {
            				select.value = "0";	//	select.value = "whee";
            			}, 2000);
            			// this also updates the UI, but doesn't trigger mutation observer's callback
            			setTimeout(function () {
            				select.getElementsByTagName('option')[0].selected = true;
            			}, 3000);
            			
            			// neither does manual selecting of options trigger mutation observer unfortunately :(
            		}(document, function(selector) { return document.querySelector(selector); });
            
            		/*
            		function method_DOMNodeInserted() {
            			$('#method').attr('class','old').text('DOMNodeInserted');
            			$('body').on('DOMNodeInserted', '*', function(e){
            				if($(e.target).find('select').length) {
            					$(e.target).find('select').each(function(){
            						apply_select2($(this)); // Not sure why this is called twice
            					});
            				}
            			});
            		}
            		function method_MutationObserver() {
            			$('#method').attr('class','new').text('MutationObserver');
            			var observer = new MutationObserver(function(mutations) {
            				mutations.forEach(function(mutation) {
            					if ( mutation.type == 'childList' ) {
            						if (mutation.addedNodes.length >= 1) {
            							for (var i = 0; i < mutation.addedNodes.length; i++) {
            								$(mutation.addedNodes[i]).find('select').each(function(){
            									apply_select2($(this));
            								});
            							}
            						}
            					}
            				});
            			});
            			//  var observerConfig = { childList: true };
            			var observerConfig = { attributes: true, childList: true, characterData: true, subtree: true };
            			var targetNode = document.body;
            			observer.observe(targetNode, observerConfig);
            		}
            		function apply_select2($theSelect) {
            			$debugMsg = 'Detected newly-added select id: ' + $theSelect.attr('id');
            			$('#feedback').html('<span>'+$debugMsg+'</span>');
            			console.log($debugMsg);
            			// Apply select2 here
            		}
            			*/
            	</script>
            <?php 
            }
            
            답변: [wordpress] astra에서 view count #16688
            mimoon
            키 마스터

              2024-05-04 update: 30이하일 때 배경색 띠 삭제를 위해

              
              /***2024-05-04 for jp_post_view count */
              $jp_post_view_astra = do_shortcode( '' );
              if (strpos($jp_post_view_astra,'👁')) { 
                 echo "<span style='padding-right: 2px;' id='view_count' class='highlight'>&nbsp;".$jp_post_view_astra."&nbsp;</span><br>";
              } else {
                 echo "";
              }
              /***2024-05-04 End of jp_post_view count */
              
              답변: [wordpress] astra에서 view count #16646
              mimoon
              키 마스터

                2024-03-27 change code according to astra theme
                함수명이나 구조가 완전히 달라짐
                파일 구도는 그대로 \astra\Inc\blog\blog.php
                그러나 Line 571~582 쯤 다음 부분에 삽입

                
                case 'single-meta':
                  do_action( 'astra_single_post_banner_meta_before' );
                  $post_meta = astra_get_option( 'ast-dynamic-single-' . $post_type . '-metadata', array( 'comments', 'author', 'date' ) );
                  $output    = '';
                  if ( ! empty( $post_meta ) ) {
                    $output_str = astra_get_post_meta( $post_meta, '/', 'single-post' );
                        if ( ! empty( $output_str ) ) {
                            $output = apply_filters( 'astra_single_post_meta', '<div class="entry-meta">' . $output_str . '</div>' ); // WPCS: XSS OK.
                        }
                   }
                
                  /***2024-03-27 for jp_post_view count */
                  $jp_post_view_astra = do_shortcode( '' );
                  echo "<br><span style='padding: 0 1px 0 2px;' id='view_count' class='highlight'>&nbsp;".$jp_post_view_astra."&nbsp;</span><br>";
                   /***2024-03-27 End of jp_post_view count */
                
                   echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
                   do_action( 'astra_single_post_banner_meta_after' );
                break;
                

                ‘echo $output;’의 바로 앞 줄

                답변: [wordpress] astra에서 view count #15960
                mimoon
                키 마스터

                  post-views-for-jetpack 플러그인의
                  functions.jp-post-views.php 파일 내에
                  다음 두 라인과

                  
                  $num_s = preg_replace("/[^0-9]*/s", "", $views['total']);
                  if ( $num_s < 30 ) { return; }
                  

                  다음 라인

                  
                  '%s view',
                  ' 👁 %s'.'명의 독자가 공감하셨습니다',
                  

                  이 둘을 추가/변경하지 않으면 단순 View(s)로만 게시
                  전자는 30회 이하는 안 보여주는 코드.

                  답변: [wordpress] astra에서 view count #15944
                  mimoon
                  키 마스터

                    최신

                    
                    <!-- .post view count -->
                    <span id='view_count' class="highlight"><?php echo do_shortcode( '' ); ?></span>
                    <!-- .post view count end -->
                    
                    답변: 비공개: [Kotlin] DiffUtil 성공 #15500
                    mimoon
                    키 마스터

                      현재 이 시간 성공한 RoombibleAdapter

                      
                      
                      class RoombibleAdapter : RecyclerView.Adapter<RoombibleAdapter.Holder>(){
                      //class RoombibleAdapter : RecyclerView.Adapter<RoombibleAdapter.ArticleViewHolder>(){
                      //class RoombibleAdapter : ListAdapter<RoomPbible, RoombibleAdapter.Holder>(DiffUtils) {
                      
                          var helper:RoomHelper? = null
                          var bibleData = mutableListOf<RoomPbible>()
                          var selectedExpense = arrayListOf<RoomPbible>()
                      
                          /*
                          private val differCallback = object: DiffUtil.ItemCallback<RoomPbible>(){
                              // 이함수는 oldItem과 new Item이 같은지 확인하는 함수입니다.
                              override fun areItemsTheSame(oldItem: RoomPbible, newItem: RoomPbible): Boolean {
                                  // oldItem과 newItem은 전에 만들었던 article dataclass의 타입을 가지고있음
                                  // 같은아이템인지 확인하려면 두 아이템에 고유ID를 확인해줘야
                                  // 기사마자 다른 url을 가지고있기때문에 data class에서 각 아이템의 url을 확인
                                  return oldItem.rhv == newItem.rhv
                              }
                              @SuppressLint("DiffUtilEquals")
                              override fun areContentsTheSame(oldItem: RoomPbible, newItem: RoomPbible): Boolean {
                                  //둘의 컨텐츠도 비교해줍니다.
                                  return oldItem == newItem
                              }
                          }
                          */
                      
                          // 2021-12-01 Original
                          override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RoombibleAdapter.Holder {
                              val roombibleBinding = ItemRoombibleBinding.inflate(LayoutInflater.from(parent.context), parent, false)
                              return Holder(roombibleBinding)
                          }
                      
                          /*
                          // 2021-12-02 Expense에서 온 것
                          override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
                              Holder(ItemRoombibleBinding.inflate(LayoutInflater.from(parent.context), parent, false))
                           */
                      
                          inner class Holder(private val roombibleBinding: ItemRoombibleBinding) : RecyclerView.ViewHolder(roombibleBinding.root) {
                              private var mRoomBible:RoomPbible? = null
                      
                              /*
                              fun bind(roombible: RoomPbible) {
                                  with(roombibleBinding) {
                                      bibleContent.text = roombible.rhv
                                      bibleCompare.text = roombible.cmv
                                  }
                              }
                              */
                      
                              fun setRoomBible(roombible:RoomPbible) {
                                  //binding.textNo.text = "${memo.no}"
                                  //val str1 = roombible.rhv
                                  //val trimRhv = str1.replace("[0-9\\:]".toRegex(), "")
                                  //val str2 = roombible.cmv
                                  //val trimCmv = str2.replace("[0-9\\:]".toRegex(), "")
                                  roombibleBinding.bibleContent.text = roombible.rhv  //trimRhv
                                  roombibleBinding.bibleCompare.text = roombible.cmv  //trimCmv
                                  //val sdf = SimpleDateFormat("yy/MM/dd hh:mm")
                                  // 날짜 포맷은 SimpleDateFormat으로 설정합니다.
                                  //roombibleBinding.textDatetime.text = sdf.format(roombible.datetime)
                      
                                  this.mRoomBible = roombible
                              }
                      
                          }
                      
                          override fun getItemCount(): Int {
                              return bibleData.size
                          }
                      
                          override fun getItemViewType(position: Int): Int {
                              return position % 2
                          }
                      
                          override fun getItemId(position: Int): Long {
                              //val product: Product = bibleData[position]
                              //return product.pid
                              return position.toLong()
                          }
                      
                          // 2021-12-01 Original에 Expense와 또 하나 섞은 것
                          override fun onBindViewHolder(holder: RoombibleAdapter.Holder, position: Int) {
                              val roombible = bibleData[position]
                              holder.setRoomBible(roombible)
                      
                              // 2021-12-01 실패
                              /*
                              val article = differ.currentList[position]
                              //각 리스트의 구성요소들을 UI에 연결
                              holder.itemView.apply{
                                  //val bibleCompare = g.
                                   = article.rhv
                                  bibleCompare.text = article.cmv
                                  // 각 항목 클릭 가능하게
                                  setOnClickListener{
                                      onItemClickListener?.let{
                                          it(article)
                                      }
                                  }
                              }
                              */
                      
                              // holder.bind(getItem(position))   //2021-12-02 Expense에서 온 것
                      
                          }
                      
                          companion object DiffUtils : DiffUtil.ItemCallback<RoomPbible>() {
                              override fun areItemsTheSame(oldItem: RoomPbible, newItem: RoomPbible): Boolean {
                                  return oldItem.rhv == newItem.rhv
                              }
                              @SuppressLint("DiffUtilEquals")
                              override fun areContentsTheSame(oldItem: RoomPbible, newItem: RoomPbible): Boolean {
                                  return oldItem == newItem
                              }
                          }
                      
                          private var onItemClickListener: ((RoomPbible) -> Unit)? = null
                      
                          fun setOnItemClickListener(listener: (RoomPbible) -> Unit) {
                              onItemClickListener = listener
                          }
                      
                          // 2021-12-02
                          class DiffUtilCallback(
                              private val oldData: List<RoomPbible>,
                              private val newData: List<RoomPbible>
                          ) : DiffUtil.Callback() {
                              override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
                                  val oldItem = oldData[oldItemPosition]
                                  val newItem = newData[newItemPosition]
                                  return oldItem.rhv == newItem.rhv
                                  /*
                                  return if (oldItem is Board && newItem is Board) {
                                      oldItem.rhv == newItem.rhv
                                  } else {
                                      false
                                  }
                                  */
                              }
                              override fun getOldListSize(): Int = oldData.size
                              override fun getNewListSize(): Int = newData.size
                              override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
                                  oldData[oldItemPosition] == newData[newItemPosition]
                          }
                      
                          /*
                          class DiffUtilCallback(
                              private val oldData: List<RoomPbible>,
                              private val newData: List<RoomPbible>
                          ) : DiffUtil.Callback() {
                              override fun areItemsTheSame(oldData: RoomPbible, newData: RoomPbible): Boolean {
                                  return oldData.rhv == newData.rhv
                              }
                              override fun getOldListSize(): Int = oldData.size
                              override fun getNewListSize(): Int = newData.size
                              override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
                                  TODO("Not yet implemented")
                              }
                              override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
                                  oldData[oldItemPosition] == newData[newItemPosition]
                          }
                          */
                      
                          /*
                          // 2021-12-01    보류
                          //viewholder를 만들어줌
                          //inner class ArticleViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
                          inner class ArticleViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
                              var bibleContent : TextView = itemView.findViewById(R.id.bibleContent)
                              var bibleCompare : TextView = itemView.findViewById(R.id.bibleCompare)
                          }
                          */
                      
                          //추가시작  2021-12-01
                          //val differ = AsyncListDiffer(this, differCallback)    // 앞의 것에 달린 것
                          /*
                          override fun onBindViewHolder(holder: ArticleViewHolder, position: Int) {
                              val article = differ.currentList[position]
                              holder.itemView.apply { // apply: reference views directly
                                  holder.bibleContent.text = article.rhv
                                  holder.bibleCompare.text = article.cmv
                                  setOnClickListener { onItemClickListener?.let { it(article) } }
                              }
                          }
                          */
                          /*
                           override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArticleViewHolder {
                              return ArticleViewHolder(
                                  LayoutInflater.from(parent.context).inflate(R.layout.item_roombible, parent,false)
                              )
                          }
                          */
                      
                          /*
                          override fun getItemCount(): Int {
                              //리사이클러뷰에서는 보통 리스트를 받아서 그 리스트 사이즈를 count하지만 리스트를 asynclistdiffer가 관리하기때문에, differ에 item갯수로 연결해주어야합니다.
                              return differ.currentList.size
                          }
                          //추가끝
                          */
                      
                          /*
                          override fun submitList(list: List<Item>?) {
                              super.submitList(list)
                          }
                          */
                      
                          fun removeSelectedExpense() = bibleData.clear()
                          //fun selectBibleSize() = differ.currentList.size
                          fun removeSelectedExpense2() {
                              bibleData.clear()
                              notifyDataSetChanged()
                              //notifyItemRangeRemoved(0, itemCount)
                          }
                          fun unselectBibleData() {
                              val sizex = bibleData.size
                              val handler = Handler(Looper.getMainLooper())
                              Log.d("Room of pentalogia", "선택사이즈 A: $sizex B: $itemCount")
                              handler.postDelayed({
                                  //CoroutineScope(Dispatchers.IO).launch{
                                  for (i in 0 until 30) {
                                      val sizey= bibleData[i].rhv
                                      //bibleData.removeAt(i)
                                      //if(i%2 ==1) {
                                          Log.d("Room of pentalogia", "선택 $sizey")
                                          bibleData.removeAt(i)
                                      //}
                                  }
                                  /*
                                  for (i in bibleData.indices.reversed()) {
                                      val sizey= bibleData[i].rhv
                                      Log.d("Room of pentalogia", "선택 $sizey")
                                      //if (bibleData[i].contains("bad")) {
                                          bibleData.removeAt(i)
                                      //}
                                  }
                                  */
                                 /*
                                  val numberIterator = bibleData.iterator()
                                  while (numberIterator.hasNext()) {
                                      val integer = numberIterator.next()
                                      if (integer < 3) {
                                          numberIterator.remove()
                                      }
                                  }
                                  */
                                  //}
                              },0)
                          }
                      
                          fun refresh(data: List<RoomPbible>) {
                              //val selectedExpense: MutableList<RoomPbible> = mutableListOf()
                              /*
                              // 2021-12-02 Compleate!! Good. but lzay
                              bibleData.clear()
                              bibleData.addAll(data)
                              val handler = Handler(Looper.getMainLooper())
                              handler.postDelayed({
                                  notifyDataSetChanged()
                              }, 0)
                              */
                      
                              /*
                              val oldItem = RoombibleAdapter.areItemsTheSame()
                              //val diffCallback = differCallback(this.)
                              val result = DiffUtil.calculateDiff()
                              bibleData = data as MutableList<RoomPbible>
                              result.dispatchUpdatesTo(this)
                              */
                              val diffCallback = DiffUtilCallback(this.bibleData, data)
                              val diffResult = DiffUtil.calculateDiff(diffCallback)
                              bibleData.clear()
                              bibleData.addAll(data)
                              val handler = Handler(Looper.getMainLooper())
                              handler.postDelayed({
                                  diffResult.dispatchUpdatesTo(this)
                              }, 0)
                          }
                          fun loadFakeData2() {
                              //rbAdapter.bibleData.addAll(helper?.roomPbibleDao()?.getAllPbible() ?: listOf())
                              selectedExpense.addAll(helper?.roomPbibleDao()?.getAllPbible() ?: listOf())
                          }
                      
                      }
                      
                      mimoon
                      키 마스터

                        //completed version
                        // 성공

                        
                        // 2021-11-16
                            private fun startDownload() {
                                //if(Build.VERSION.SDK_INT >= 17){
                                //    val dbPATH = this.applicationInfo.dataDir+"/databases/"
                                //}else {
                                    //this.DB_PATH = "/data/data/"+context.getPackageName()+"/databases/";
                                    val dbPATH = "/data/data/" + applicationContext.packageName + "/databases/"
                                    //Log.e("Path:", DB_PATH);
                                //}
                                val dbNAME = "room_memo.db"
                                val strOutFile = dbPATH + dbNAME
                                val request = DownloadManager.Request(Uri.parse("https://mimoonchurch.net/room_memo.db"))
                                request.setTitle("room_memo.db")
                                request.setDescription("My database is downloading.")
                                request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
                                //request.allowScanningByMediaScanner()
                                request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
                                val filename: String =
                                    URLUtil.guessFileName("https://mimoonchurch.net/room_memo.db", null, MimeTypeMap.getFileExtensionFromUrl("https://mimoonchurch.net/room_memo.db"))
                                request.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, filename)    // to save in cache
                                //request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename)      // to save in public download folder
                                //request.setDestinationInExternalPublicDir(Environment.getDownloadCacheDirectory().toString(), filename)
                                //val manager = getSystemService(DOWNLOAD_SERVICE) as DownloadManager   // to start download
                                //manager.enqueue(request)
                        
                                // to test by written url
                                //val target = File(strOutFile)       // 에뮬레이터에서만 효용
                                val target = File(dbPATH, dbNAME)  // 에뮬레이터에서 효용
                                if (!target.exists()) {
                                    gAlert("내부 저장소(수동 경로 $target)에 파일이 없음을 확인했습니다.")
                                    //target.createNewFile()
                                } else {
                                    val dbSize: Int = java.lang.String.valueOf(target.length() / 1024).toInt()
                                    gAlert("내부 저장소(수동 경로 $target)에 파일(크기: $dbSize)이 이미 존재합니다.")
                                    //target.delete()
                                    //target.createNewFile()
                                    //val manager =  getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
                                    //manager.enqueue(request)
                                }
                        
                                //val currentDBPath = "\\data\\com.w_13567767\\databases\\room_memo.db"
                                val currentDBPath = "/data/data/" + applicationContext.packageName + "/databases/"
                                val currentGetDbPath: File = this.getDatabasePath("room_memo.db")     // 파일 명 포함
                                val outFileName = currentGetDbPath.path
                                //val downloadFolder = File(cacheDir.toString())
                                val downloadFolder = File(Environment.DIRECTORY_DOWNLOADS).toString()
                                //val downloadFolder = Environment.getExternalStorageDirectory()  // 에뮬레이터에서 효용
                                val dataGetExternalStorageDirectory: File = Environment.getExternalStorageDirectory()      // 에뮬레이터에서 효용
                                val dataInternalGetDataDirectory: File = Environment.getDataDirectory()
                                val dataGetDirDnld: File = File(Environment.DIRECTORY_DOWNLOADS)
                                val dataGetDnldCacheDirectory: File = Environment.getDownloadCacheDirectory()
                                val dataDownloadFilesDir = this.filesDir   // 내부 저장소 일반 파일
                                val dataDownloadCacheDir = this.cacheDir
                                val dataDirDnldGetExternalFilesDir = this.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
                                val dataDirDnldExternalStoragePublicDirectory = getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
                                //val dataDirDnld = this.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
                                //val dataDirDnld = this.getDatabasePath(Environment.DIRECTORY_DOWNLOADS)
                                //val dataDirDnld = File(Environment.DIRECTORY_DOWNLOADS).toString()
                                //val data: File = File(cacheDir.toString())
                                //val currentDB = File(currentDBPath)
                                val backupDB = File(downloadFolder, dbNAME)
                                //val strOutFile2 = "$currentDBPath"
                                //gAlert("내부 저장소 절대경로는$strOutFile2")
                        
                                //val target2 = File(strOutFile2)     // 에뮬과 디바이스 모두 안 됨
                                //val target2 = File(currentDBPath)       // 에뮬과 디바이스 모두 됨 (시스템에 의한 절대 경로 얻기)
                               // val target2 = File(outFileName)     // 에뮬레이터에서는 되고 디바이스에서는 안 됨
                                //val target2 = Environment.getDataDirectory()        // 에뮬레이터와 디바이스 모두 효용// 이것은 다운로드 폴더 경로
                                val target2 = File(currentGetDbPath.toString())    // 에뮬레이터에서 됨
                        
                                val target3 = File(downloadFolder, dbNAME)        // 에뮬레이터에서만 효용
                                val targetGetExternalStorageDirectory = File(dataGetExternalStorageDirectory, dbNAME)      // 외장 다운로드 메모리 경로
                                val targetInternalGetDataDirectory = File(dataInternalGetDataDirectory, dbNAME)      // 내장 메모리 다운로드 폴더 경로
                                val targetDirectDownload = File(dataGetDirDnld, dbNAME)      // 내장 다운로드 메모리 경로
                                val targetGetDownloadCacheDirectory = File(dataGetDnldCacheDirectory, dbNAME)        // 에뮬에서 효용
                                val targetDownloadFilesDir = File(dataDownloadFilesDir, dbNAME)
                                val targetDownloadCacheDir = File(dataDownloadCacheDir, dbNAME)
                                val targetDirGetExternalFilesDir = File(dataDirDnldGetExternalFilesDir, dbNAME)
                                val targetDirDnldExternalStoragePublicDirectory = File(dataDirDnldExternalStoragePublicDirectory, dbNAME)
                                //val strOutFile3 = "$data/$backupDBPath"
                                //val target3 = File(strOutFile3)
                                //gAlert("공용 저장소 파일 절대경로는 $target3")
                                //gAlert("내부 저장소 절대경로는$target2")
                                if (target2.exists()) {
                                    val dbSize: Int = java.lang.String.valueOf(target2.length() / 1024).toInt()
                                    gAlert("내장 폴더 절대경로에서 파일(크기: $dbSize) 찾음. $target2")
                                    //target.delete()
                                    //target.createNewFile()
                                    //Log.d("TAG", "==== backUpExists: " + "내장 폴더에서 백업파일 찾음");
                                } else {
                                    gAlert("내장 폴더 절대경로에서 파일 못 찾음. $target2")
                        
                                }
                                when {
                                    targetGetExternalStorageDirectory.exists() -> {
                                        gAlert("외부 저장소getExternalStorageDirectory($targetGetExternalStorageDirectory)에서 파일 찾음.")
                                        targetGetExternalStorageDirectory.delete()
                                        //targetGetExternalStorageDirectory.createNewFile()
                                        //Log.d("TAG", "==== backUpExists: " + "다운로드 폴더에서 백업파일 찾음");
                                    }
                                    targetInternalGetDataDirectory.exists() -> {
                                        gAlert("내부 저장소getDataDirectory($targetInternalGetDataDirectory)에서 파일 찾음.")
                                        targetInternalGetDataDirectory.delete()
                                    }
                                    targetDirectDownload.exists() -> {
                                        gAlert("다운로드 지정했던 함수DIRECTORY_DOWNLOADS($targetDirectDownload)에서 파일 찾음.")
                                        targetDirectDownload.delete()
                                    }
                                    targetGetDownloadCacheDirectory.exists() -> {
                                        gAlert("getDownloadCacheDirectory($targetGetDownloadCacheDirectory)에서 파일 찾음.")
                                        targetGetDownloadCacheDirectory.delete()
                                    }
                                    targetDownloadFilesDir.exists() -> {
                                        val dbSize: Int = java.lang.String.valueOf(targetDownloadFilesDir.length() / 1024).toInt()
                                        gAlert("내부 저장소 FilesDir($targetDownloadFilesDir)에서 파일(크기: $dbSize) 찾음.")
                                        //targetDownloadFilesDir.delete()
                                    }
                                    targetDownloadCacheDir.exists() -> {
                                        gAlert("내부 저장소 CacheDir($targetDownloadCacheDir)에서 파일 찾음.")
                                        targetDownloadCacheDir.delete()
                                    }
                                    targetDirGetExternalFilesDir.exists() -> {
                                        val dbSize: Int = java.lang.String.valueOf(targetDirGetExternalFilesDir.length() / 1024).toInt()
                                        gAlert("외부저장소 DirGetExternalFilesDir ($targetDirGetExternalFilesDir)에서 파일(크기: $dbSize) 찾음.")
                                        //targetDirGetExternalFilesDir.delete()
                                    }
                                    targetDirDnldExternalStoragePublicDirectory.exists() -> {
                                        val dbSize: Int = java.lang.String.valueOf(targetDirDnldExternalStoragePublicDirectory.length() / 1024).toInt()
                                        gAlert("외부 저장소 DirDnldExternalStoragePublicDirectory($targetDirDnldExternalStoragePublicDirectory)에서 파일(크기: $dbSize) 찾음.")
                                        //targetDirDnldExternalStoragePublicDirectory.delete()
                                    }
                                    target3.exists() -> {
                                        gAlert("File(Environment.DIRECTORY_DOWNLOADS)($target3)에서 파일 찾음.")
                                        target3.delete()
                                    }
                                    else -> {
                                        gAlert("아무 곳에서도 파일  못 찾음.")
                                        val manager =  getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
                                        manager.enqueue(request)
                        
                                    }
                                }
                                /*
                                val src: FileChannel = FileInputStream(currentDB).channel
                                val dst: FileChannel = FileOutputStream(backupDB).channel
                                dst.transferFrom(src, 0, src.size())
                                src.close()
                                dst.close()
                                */
                        
                                // 2021-11-20
                                // Make sure we have a path to the file
                                //currentGetDbPath.getParentFile().mkdirs()
                                // Try to copy database file
                                /* Try 부분을 제거해도 이전 가능
                                try {
                                    val inputStream: InputStream = targetDirGetExternalFilesDir.inputStream()       // 작동
                                    //val inputStream: InputStream = currentGetDbPath.inputStream()
                                    //val inputStream: InputStream = getDatabasePath("room_memo.db").inputStream()
                                    val output: OutputStream = FileOutputStream(currentGetDbPath)
                                    //val output: OutputStream = FileOutputStream(getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS))
                                    //val output: OutputStream = FileOutputStream(targetDirDnldExternalStoragePublicDirectory)
                                    //val output: OutputStream = FileOutputStream(targetDownloadFilesDir)     // 작동
                                    //val buffer = ByteArray(8192)
                                    val buffer = ByteArray(1024)
                                    var length: Int
                                    while (inputStream.read(buffer, 0, 1024).also { length = it } > 0) {
                                        output.write(buffer, 0, length)
                                    }
                                    output.flush()
                                    output.close()
                                    inputStream.close()
                        
                                    //val src: FileChannel = FileInputStream(currentGetDbPath).channel
                                    //val dst: FileChannel = FileOutputStream(targetDirDnldExternalStoragePublicDirectory).channel
                                    //dst.transferFrom(src, 0, src.size())
                                    //src.close()
                                    //dst.close()
                        
                                } catch (e: IOException) {
                                    Log.d("pentalogia", "Failed to open file", e)
                                    e.printStackTrace()
                                    //gAlert("복사 실패")
                                }
                        
                                //Try를 제거해도 createFromFile이 수행
                                */ 
                        
                                lifecycleScope.launch(Dispatchers.IO) {
                                    //.allowMainThreadQueries()
                                    // 2021-11-07
                                    //rcAdapter.setHasStableIds(true)
                                    withContext(Dispatchers.IO) {
                                        helper =
                                            Room.databaseBuilder(this@ListviewActivity, RoomHelper::class.java, "room_memo")
                                                .addMigrations(MigrateDatabase.MIGRATE_1_2)
                                                // 2021-11-16
                                                .createFromFile(File(targetDirGetExternalFilesDir.toString()))
                                                      .fallbackToDestructiveMigration()
                                                //.allowMainThreadQueries()
                                                .build()
                                        rcAdapter.helper = helper
                                        rcAdapter.listData.addAll(helper?.roomMemoDao()?.getAll() ?: listOf())
                                    }
                                    laBinding.recyclerMemo.adapter = rcAdapter
                                    laBinding.recyclerMemo.layoutManager = LinearLayoutManager(this@ListviewActivity)
                        
                                    // VerticalItemDecorator
                                    //laBinding.recyclerMemo.addItemDecoration(VerticalItemDecorator(10))
                                    //laBinding.recyclerMemo.addItemDecoration(DividerItemDecoration(this, LinearLayoutManager.VERTICAL))
                        
                                    // 2021-11-09 VerticalItemDecorator kill
                                    /*
                                    val decoDevider = CustomDecoration(3f, 10f, Color.LTGRAY)
                                    laBinding.recyclerMemo.addItemDecoration(decoDevider)
                                    */
                        
                                    (laBinding.recyclerMemo.layoutManager as LinearLayoutManager).reverseLayout = true
                                    (laBinding.recyclerMemo.layoutManager as LinearLayoutManager).stackFromEnd = true
                                    // if empty any data
                                    val emptyView: TextView = laBinding.emptyView
                                    if (rcAdapter.itemCount == 0) emptyView.visibility =
                                        View.VISIBLE else emptyView.visibility = View.GONE
                                    rcAdapter.notifyDataSetChanged()
                                }
                        
                            }
                        
                      10 글 보임 - 1 에서 10 까지 (총 58 중에서)