<?xml version="1.0" encoding="utf-8" ?><rss version="2.0" xmlns:tt="http://teletype.in/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Sora Nai</title><generator>teletype.in</generator><description><![CDATA[Sora Nai]]></description><image><url>https://teletype.in/files/cd/4a/cd4a1cbe-9bb9-41bc-ac2a-a74a248c75e5.jpeg</url><title>Sora Nai</title><link>https://teletype.in/@hikkidev</link></image><link>https://teletype.in/@hikkidev?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=hikkidev</link><atom:link rel="self" type="application/rss+xml" href="https://teletype.in/rss/hikkidev?offset=0"></atom:link><atom:link rel="next" type="application/rss+xml" href="https://teletype.in/rss/hikkidev?offset=10"></atom:link><atom:link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></atom:link><pubDate>Sat, 04 Apr 2026 06:41:46 GMT</pubDate><lastBuildDate>Sat, 04 Apr 2026 06:41:46 GMT</lastBuildDate><item><guid isPermaLink="true">https://teletype.in/@hikkidev/arch-install-btrfs</guid><link>https://teletype.in/@hikkidev/arch-install-btrfs?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=hikkidev</link><comments>https://teletype.in/@hikkidev/arch-install-btrfs?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=hikkidev#comments</comments><dc:creator>hikkidev</dc:creator><title>Unencrypted Arch Linux + BTRFS as ROOT + rEFInd</title><pubDate>Tue, 15 Oct 2024 21:26:17 GMT</pubDate><category>Arch Linux</category><description><![CDATA[<img src="https://img1.teletype.in/files/c9/0a/c90a6d03-154d-4207-94fa-7782ec08556b.png"></img>]]></description><content:encoded><![CDATA[
  <h3 id="JZgw">Пред-условия этой заметки</h3>
  <ul id="TkZt">
    <li id="ShEt">Наличие установочного USB (Bootable USB drive: <a href="https://archlinux.org/download/" target="_blank">Arch Linux</a>, <a href="https://rufus.ie" target="_blank">Rufus</a>)</li>
    <li id="MqT5">Motherboard boot mode: x64 UEFI</li>
    <li id="oEzq">ОС на одном диске (будет 2 раздела)</li>
    <ul id="IuEQ">
      <li id="HVNY">1Gb под загрузчик</li>
      <li id="33O4">Оставшееся пространство под систему</li>
    </ul>
    <li id="yqB8">Без шифрования и secure-boot </li>
  </ul>
  <hr />
  <h2 id="Eizz">Ну че, народ, погнали! </h2>
  <blockquote id="Cnv8"><a href="https://coub.com/view/9juiz80" target="_blank">https://coub.com/view/9juiz80</a></blockquote>
  <ol id="6hiE">
    <li id="Cl7p">Выполнить шаги с 1.1 по 1.8 из официальной <a href="https://wiki.archlinux.org/title/Installation_guide" target="_blank">инструкции</a> до пункта о разметке диска</li>
  </ol>
  <h3 id="39Lm">1. Выбрать диск</h3>
  <ul id="zZky">
    <li id="XH4Q">ВНИМАТЕЛЬНО, выбрать диск на накоторый будет установлена система. Для просмотра дисков можно использовать утилиты: <code>lsblk</code>, <code>blkid</code>, <code>fdisk -l</code></li>
    <li id="K0jN">Пусть целевым диском будет SSD <code>nvme0n1</code>, тогда сохранить диск в переменную окружения: <code>export DISK=&quot;/dev/nvme0n1&quot;</code></li>
  </ul>
  <h3 id="ymaM">2. Удалить старую разметку (желательно, на всякий случай)</h3>
  <pre id="ePvb" data-lang="bash">wipefs -af $DISK
sgdisk --zap-all --clear $DISK
partprobe $DISK</pre>
  <h3 id="PI9U">3. Выполнить разметку</h3>
  <pre id="31Q2" data-lang="bash">parted -s $DISK mklabel gpt
parted -s $DISK mkpart primary fat32 1MiB 1025MiB
parted -s $DISK set 1 esp on
parted -s $DISK mkpart primary $FILESYSTEM 1025MiB 100%</pre>
  <h3 id="MZXO">4. Форматировать разделы </h3>
  <blockquote id="Ojt9">Предупреждение: разделы для SSD имеют префикс &#x60;p&#x60;, SATA как правило не имеют; проверьте одной из утилит, например <code>fdisk -l</code></blockquote>
  <p id="08VG">Загрузочный раздел под FAT32</p>
  <pre id="067a" data-lang="bash">mkfs.fat -F32 ${DISK}p1</pre>
  <p id="BDrs">Второй раздел под BTRFS</p>
  <pre id="XQk0" data-lang="bash">mkfs.btrfs -f ${DISK}p2</pre>
  <p id="N90O"></p>
  <h3 id="11oc">5. Сконфигурировать разделы BTRFS</h3>
  <p id="Z01l">Примонтировать раздел диска в папку <code>/mnt</code></p>
  <pre id="zTUy" data-lang="shell">mount ${DISK}p2 /mnt</pre>
  <p id="zwrN">Создать корневой раздел BTRFS (<code>/</code>)</p>
  <pre id="PBXV" data-lang="shell">btrfs subvolume create /mnt/@</pre>
  <p id="4oBz">Создать под-разделы</p>
  <pre id="PBXV" data-lang="shell">btrfs subvolume create /mnt/@snapshots
btrfs subvolume create /mnt/@home
btrfs subvolume create /mnt/@libvirt
btrfs subvolume create /mnt/@cache
btrfs subvolume create /mnt/@log
btrfs subvolume create /mnt/@tmp</pre>
  <p id="RfkI">Структура под-раздел : точка монтирования</p>
  <ul id="w8Js">
    <li id="05MQ"><code>@snapshots</code> : <code>/.snapshots</code></li>
    <li id="burr"><code>@home</code> : <code>/home</code></li>
    <li id="pOzU"><code>@libvirt</code> : <code>/var/lib/libvirt</code> (виртуальные машины)</li>
    <li id="tJsX"><code>@cache</code> : <code>/var/cache</code></li>
    <li id="TUOv"><code>@log</code> : <code>/var/log</code></li>
    <li id="ChtW"><code>@tmp</code> : <code>/var/tmp</code></li>
  </ul>
  <p id="3TnD">Исключение <code>@tmp</code> и <code>@log</code> облегчит последующую работу в &quot;recovery mode&quot; после отката всей системы (корневого раздела <code>/</code>)</p>
  <p id="kGN7">Размонтировать для последующей работы с созданными разделами</p>
  <pre id="nqDq" data-lang="bash">umount /mnt</pre>
  <p id="beok"></p>
  <h3 id="htb6">6. Монтировать разделы</h3>
  <p id="xrzh">Основной раздел</p>
  <pre data-lang="bash" id="pxWh">export MY_OPT=&quot;rw,noatime,compress-force=zstd,space_cache=v2&quot;</pre>
  <pre data-lang="bash" id="Qc4n">mount -o ${MY_OPT},subvol=@ ${DISK}p2 /mnt</pre>
  <pre data-lang="bash" id="6udu">mkdir -p /mnt/{.snapshots,home,var/lib/libvirt,var/cache,var/log,var/tmp}</pre>
  <pre data-lang="bash" id="HCFE">mount -o ${MY_OPT},subvol=@snapshots ${DISK}p2 /mnt/.snapshots
mount -o ${MY_OPT},subvol=@home ${DISK}p2 /mnt/home
mount -o ${MY_OPT},subvol=@libvirt ${DISK}p2 /mnt/var/lib/libvirt
mount -o ${MY_OPT},subvol=@cache ${DISK}p2 /mnt/var/cache
mount -o ${MY_OPT},subvol=@log ${DISK}p2 /mnt/var/log
mount -o ${MY_OPT},subvol=@tmp ${DISK}p2 /mnt/var/tmp</pre>
  <p id="YAj6">Загрузочный раздел</p>
  <pre id="nFLV" data-lang="bash">mkdir -p /mnt/boot/efi
mount ${DISK}p1 /mnt/boot/efi</pre>
  <p id="HNuA"></p>
  <h3 id="VfwU">7. Установить систему</h3>
  <pre data-lang="bash" id="k6RA">pacstrap /mnt base base-devel btrfs-progs linux-lts linux-lts-headers linux-firmware networkmanager sudo</pre>
  <p id="DmHm"></p>
  <h2 id="nekq">Конфигурация</h2>
  <h3 id="lttU">1. Сгенерировать fstab</h3>
  <pre id="qmlH" data-lang="shell">genfstab -U /mnt &gt;&gt; /mnt/etc/fstab</pre>
  <p id="REEn"></p>
  <h3 id="gDkF">2. arch-chroot</h3>
  <p id="qVVO">Выполнить шаги 3.1 - 3.6 из официальной <a href="https://wiki.archlinux.org/title/Installation_guide" target="_blank">инструкции</a></p>
  <p id="2g38">Моя краткая выжимка:</p>
  <pre id="gEfZ"># Тайм-зона
export TIMEZONE=&quot;Europe/Amsterdam&quot; &lt;- заменить на свою
ln -sf /usr/share/zoneinfo/$TIMEZONE /etc/localtime
hwclock --systohc

# Локализация, английский приоритетный

export locale=&quot;ru_RU.UTF-8 UTF-8&quot;
sed -i &quot;s/^#\(${locale}\)/\1/&quot; /etc/locale.gen

export locale=&quot;en_US.UTF-8 UTF-8&quot;
sed -i &quot;s/^#\(${locale}\)/\1/&quot; /etc/locale.gen

echo &quot;LANG=${locale}&quot; &gt; /etc/locale.conf
locale-gen

# Установить имя машины
echo $HOSTNAME &gt; /etc/hostname

# Пароль root пользователя
passwd

# Создать пользователя
export USERNAME=&quot;hikkidev&quot; &lt;- заменить на свой
useradd -m -G wheel -s /bin/bash $USERNAME
passwd $USERNAME

# Привилегии sudo для группы wheel
echo &quot;%wheel ALL=(ALL) ALL&quot; &gt; /etc/sudoers.d/wheel

# Заводим интернет
systemctl enable NetworkManager</pre>
  <p id="ErX0">Экстра-софт:</p>
  <pre id="AqIX">pacman -S refind efibootmgr tree btop bat eza tree</pre>
  <p id="lCel"></p>
  <h3 id="WW9O">3. Настройка загрузчика <a href="https://wiki.archlinux.org/title/REFInd" target="_blank">rEFInd</a></h3>
  <p id="zD2Z"><strong>Определить</strong> <code>PARTUUID</code> основного раздела, <u>куда установлена система</u>, в данном случае это <code>${DISK}p2</code>:</p>
  <pre id="VQlH" data-lang="bash">blkid -s PARTUUID /dev/nvme0n1p2 -o value</pre>
  <p id="Cya0">Сохранить значение в переменную:</p>
  <pre id="o04B" data-lang="bash">export MYUUID=$(blkid -s PARTUUID /dev/nvme0n1p2 -o value)</pre>
  <p id="p5Ea"></p>
  <p id="hGBn"><a href="https://wiki.archlinux.org/title/REFInd#Installation_with_refind-install_script" target="_blank">Установить</a> загрузчик</p>
  <pre id="BKaF">refind-install</pre>
  <p id="jU13"></p>
  <p id="OR8q"><strong><u>Отредактировать</u></strong> основные <a href="https://wiki.archlinux.org/title/REFInd#Configuration" target="_blank">параметры</a> загрузчика в <code>refind.conf</code>, файл как правило находится где-то в <code>esp/EFI/refind/</code></p>
  <pre id="NABZ">/boot/EFI/refind/refind.conf
/boot/efi/EFI/BOOT/refind.conf</pre>
  <ul id="rTrG">
    <li id="d6aI">Включить поддержку схемы именования ядер Arch Linux для их автоматического обнаружения, раскоментировав или дописав:</li>
  </ul>
  <pre id="lYja">extra_kernel_version_strings &quot;linux,linux-lts,linux-zen,linux-rt,linux-rt-lts,linux-hardened&quot;</pre>
  <ul id="3bgC">
    <li id="k8VS">Включить автоматическое <a href="https://wiki.archlinux.org/title/REFInd#Auto_detection" target="_blank">обнаружение ядра на под-разделе BTRFS</a>, раскоментировав или дописав:</li>
  </ul>
  <pre id="yUX4">also_scan_dirs +,boot,@/boot</pre>
  <ul id="SFAL">
    <li id="o2eK">Удалить или закоментировать примеры manual stanza в конце файла</li>
    <li id="5Yhp">Дописать в конце файла (<a href="https://wiki.archlinux.org/title/REFInd#For_manual_boot_stanzas" target="_blank">что такое manual stanza</a>):</li>
  </ul>
  <pre id="iQbh">include stanzas.conf</pre>
  <p id="gNMY"></p>
  <p id="GoTS"><strong><u>Cоздать</u></strong> файл <code>stanzas.conf</code> в папке с <code>refind.conf</code>  (<a href="https://wiki.archlinux.org/title/REFInd#Manual_boot_stanza" target="_blank">подробнее</a>):</p>
  <pre id="Fqwg" data-lang="bash">cat &gt; stanzas.conf &lt;&lt;EOF
menuentry &quot;Arch Linux LTS&quot; {
    icon /EFI/refind/icons/os_arch.png
    volume primary
    loader /@/boot/vmlinuz-linux-lts
    initrd /@/boot/initramfs-linux-lts.img
    options &quot;root=PARTUUID=$MYUUID rw rootflags=subvol=@&quot;
    submenuentry &quot;Boot - fallback&quot; {
        initrd /@/boot/initramfs-linux-lts-fallback.img
    }
}
EOF</pre>
  <pre id="JTN8" data-lang="bash">mv stanzas.conf &lt;path to refind&gt;/</pre>
  <p id="dJRV"></p>
  <p id="fCOI"><strong><u>Отредактировать</u></strong> параметры ядра поумолчанию в <a href="https://wiki.archlinux.org/title/REFInd#refind_linux.conf" target="_blank">refind_linux.conf </a>для автоматически обнаруженных ядер.</p>
  <p id="Z5mr">Как правило файл лежит тут: <code>/boot/refind_linux.conf</code></p>
  <pre id="vw1R" data-lang="bash">echo &quot;\&quot;Boot DEFAULT\&quot;  \&quot;root=PARTUUID=$MYUUID rw rootflags=subvol=@ initrd=@\boot\initramfs-%v.img\&quot;&quot; &gt; /boot/refind_linux.conf</pre>
  <p id="B07Q"></p>
  <p id="Lxve">Убедиться, что запись rEFInd была добавлена в загрузчик UEFI первой, выполнив:</p>
  <pre data-lang="bash" id="6hcu">efibootmgr</pre>
  <p id="PfF4">Если все ок - перезагрузка</p>
  <pre data-lang="bash" id="KR0T">exit
umount -R /mnt
reboot</pre>
  <p id="MLGg"></p>
  <h2 id="relo">Вход в систему + Snapper</h2>
  <p id="Jizy">После входа в систему рекомендую настроить BTRFS snapshots сразу</p>
  <pre data-lang="bash" id="PZBv">sudo pacman -S snapper snap-pac</pre>
  <pre data-lang="bash" id="Tdbe">sudo umount /.snapshots
sudo rm -rf /.snapshots</pre>
  <pre data-lang="bash" id="llLm">sudo snapper -c root create-config /</pre>
  <pre data-lang="bash" id="8qyV">sudo btrfs subvolume delete /.snapshots</pre>
  <pre data-lang="bash" id="NAlF">sudo mkdir /.snapshots
sudo mount -a
sudo chmod 750 /.snapshots
sudo chown :wheel /.snapshots</pre>
  <pre data-lang="bash" id="vvyb">sudo snapper -c root create -d &quot;Clean system install&quot;</pre>
  <p id="b1AK">Редактировать конфиг здесь: <code>/etc/snapper/configs/root</code></p>
  <p id="w6VZ">Включить systemd таймеры для автоматического запуска снимков и периодической очистки старых:</p>
  <pre data-lang="bash" id="0JsK">sudo systemctl enable --now snapper-timeline.timer
sudo systemctl enable --now snapper-cleanup.timer</pre>
  <h2 id="tRpl">Источники</h2>
  <ul id="O5kG">
    <li id="0BK4"><a href="https://wiki.archlinux.org/title/Installation_guide" target="_blank">https://wiki.archlinux.org/title/Installation_guide</a></li>
    <li id="oCv7"><a href="https://wiki.archlinux.org/title/REFInd" target="_blank">https://wiki.archlinux.org/title/REFInd</a></li>
    <li id="3elJ"><a href="https://www.dwarmstrong.org/archlinux-install" target="_blank">https://www.dwarmstrong.org/archlinux-install</a></li>
    <li id="OXVV"><a href="https://www.dwarmstrong.org/btrfs-snapshots-rollbacks" target="_blank">https://www.dwarmstrong.org/btrfs-snapshots-rollbacks</a></li>
  </ul>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@hikkidev/simple-android-permissions</guid><link>https://teletype.in/@hikkidev/simple-android-permissions?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=hikkidev</link><comments>https://teletype.in/@hikkidev/simple-android-permissions?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=hikkidev#comments</comments><dc:creator>hikkidev</dc:creator><title>Разрешения в Android</title><pubDate>Sun, 21 Apr 2024 11:07:35 GMT</pubDate><media:content medium="image" url="https://img2.teletype.in/files/17/23/172364fa-d95c-4a2b-88c8-32677f3b65ea.png"></media:content><description><![CDATA[<img src="https://img4.teletype.in/files/b7/dc/b7dc731f-c5fc-4ec3-8a6d-360be5f8747c.png"></img>Разрешения приложений в операционной системе Android - это механизм контроля доступа к данным и функциям вашего устройства.]]></description><content:encoded><![CDATA[
  <nav>
    <ul>
      <li class="m_level_1"><a href="#czBo">Введение</a></li>
      <li class="m_level_1"><a href="#Kfxv">Зачем это нужно?</a></li>
      <li class="m_level_1"><a href="#S39P">Запрос разрешений</a></li>
      <li class="m_level_2"><a href="#gSho">Примеры разрешений:</a></li>
      <li class="m_level_1"><a href="#e6PJ">Изменить разрешения через системные Настройки</a></li>
      <li class="m_level_1"><a href="#uFCP">Изменить разрешения через контекстное меню</a></li>
    </ul>
  </nav>
  <h2 id="czBo">Введение</h2>
  <p id="mzCK">Разрешения приложений в операционной системе Android - это механизм контроля доступа к данным и функциям вашего устройства. </p>
  <figure id="i0yt" class="m_column" data-caption-align="center">
    <img src="https://img4.teletype.in/files/b7/dc/b7dc731f-c5fc-4ec3-8a6d-360be5f8747c.png" width="1800" />
    <figcaption>Источник изображения - <a href="https://www.android.com/intl/ru_ru/safety/privacy/#safety-privacy-permissions" target="_blank">android.com</a></figcaption>
  </figure>
  <p id="A8fF">Вы можете позволить приложениям использовать различные функции устройства, например камеру или список контактов. </p>
  <h2 id="Kfxv">Зачем это нужно?</h2>
  <ul id="cTNV">
    <li id="4KIn"><strong>Защита приватности</strong>: Разрешения позволяют защищать вашу личную информацию. Например, приложение для обмена сообщениями может просить доступ к контактам, чтобы вы могли отправлять сообщения друзьям, но ему по умолчанию не дан доступ к вашим фотографиям или местоположению.</li>
    <li id="7JLV"><strong>Безопасность данных</strong>: Ограничение доступа приложений к определённым функциям и данным предотвращает возможные утечки информации. Это предотвращает сценарии, когда вредоносное приложение может скрытно собирать данные без вашего знания.</li>
    <li id="so0V"><strong>Регулирование функционала</strong>: Разрешения помогают обеспечить, чтобы приложения не использовали ресурсы устройства (например, камеру или микрофон) без ведома пользователя, что также может улучшать производительность устройства и его автономную работу.</li>
  </ul>
  <p id="SfHC"></p>
  <h2 id="S39P">Запрос разрешений</h2>
  <figure id="GBja" class="m_column" data-caption-align="center">
    <img src="https://img1.teletype.in/files/48/dc/48dc81bb-4306-4a48-a615-5c580145d7bc.png" width="1200" />
    <figcaption>Источник изображения - <a href="https://www.android.com/intl/ru_ru/safety/privacy/#safety-privacy-permissions" target="_blank">android.com</a></figcaption>
  </figure>
  <p id="Rzb2">Когда приложение впервые пытается получить доступ, система отображает диалог, и пользователь может выбрать, выдать разрешение или отказать. Если отказать, то приложение не сможет использовать данные или запрашиваемую функцию, что повлияет на его работу. В лучшем случае запрет ограничит возможности приложения, в худшем сделает приложение неработоспособным. </p>
  <p id="iQGD">Рассмотрим на примере приложения &quot;Камера&quot;. Для полноценной работы приложения необходимо выдать три разрешения к физическим датчикам устройства: <strong>камера</strong>, <strong>микрофон</strong> и <strong>местоположение</strong>.</p>
  <figure id="NRb8" class="m_column" data-caption-align="center">
    <iframe src="https://www.youtube.com/embed/Tg50GNkcgN0?autoplay=0&loop=1&mute=1&playlist=Tg50GNkcgN0"></iframe>
    <figcaption>Демонстрация запроса разрешений самим приложением.</figcaption>
  </figure>
  <p id="Wv1k">В данном случае очевидно, что доступ к <strong>Камере </strong>обязателен, в противном случае  приложение не сможет снимать фото и видео. Доступ к <strong>Микрофону </strong>нужен, чтобы записывать звук при съемке видео. А вот местоположение уже необязательное разрешение, и необходимо только для добавления сведений о месте съемки, подробнее что это такое, можно <a href="https://support.google.com/photos/answer/6153599?hl=ru&co=GENIE.Platform%253DAndroid" target="_blank">почитать здесь</a>.</p>
  <p id="CfMV"></p>
  <h3 id="gSho">Примеры разрешений:</h3>
  <ul id="Sacj">
    <li id="HCoY"><u>Физические датчики устойства</u></li>
    <ul id="W8OD">
      <li id="ZZyS"><strong>Микрофон</strong> – запись аудио.</li>
      <li id="j6gz"><strong>Камера</strong> – съемка фото и видео.</li>
      <li id="lZp6"><strong>Местоположение</strong> – доступ к данным о местоположении вашего устройства. </li>
    </ul>
    <li id="5eC6"><u>Телефония</u></li>
    <ul id="9Zw1">
      <li id="e63r"><strong>Телефон</strong> – совершение вызовов и управление ими.</li>
      <li id="h7IM"><strong>Список вызовов</strong> – просмотр списка вызовов на телефоне и создание записей в нем.</li>
      <li id="jNjy"><strong>Контакты</strong> – доступ к списку контактов.</li>
      <li id="1rAs"><strong>SMS</strong> – отправка и просмотр SMS-сообщений.</li>
    </ul>
    <li id="kCNu"><u>Хранилище, данные на устройстве</u></li>
    <ul id="QrSq">
      <li id="kMqw"><strong>Файлы</strong> – доступ ко всем файлам на вашем устройстве.</li>
      <li id="aUup"><strong>Фото и видео</strong> – доступ к фото и видео на вашем устройстве.</li>
      <li id="nhoI"><strong>Музыка и аудио</strong> – доступ к музыке и другим аудиофайлам на устройстве.</li>
    </ul>
    <li id="dkJo"><u>Другие разрешения</u></li>
    <ul id="u9Yd">
      <li id="yIxf"><strong>Уведомления</strong> – отправление уведомлений.</li>
      <li id="aZgJ"><strong>Календарь</strong> – доступ к вашему календарю.</li>
    </ul>
  </ul>
  <p id="5OHM">Полный список разрешений можно найти <a href="https://support.google.com/android/answer/9431959#types&zippy=%252C%D1%82%D0%B8%D0%BF%D1%8B-%D1%80%D0%B0%D0%B7%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B9" target="_blank">по данной ссылке</a>.</p>
  <p id="4R3z"></p>
  <h2 id="e6PJ">Изменить разрешения через системные Настройки</h2>
  <p id="dLY5">В любой момент можно зайти в настройки Android, проверить выданные разрешения для приложений и изменить их по своему усмотрению. </p>
  <p id="F5xI"></p>
  <p id="qWNa">1) Откройте на устройстве приложение &quot;<strong>Настройки</strong>&quot; и нажмите на раздел <strong>Приложения</strong>.</p>
  <figure id="K9cl" class="m_custom" data-caption-align="center">
    <img src="https://img1.teletype.in/files/48/8f/488f70af-5f5b-49c2-a0ba-f70bb7b4ea6d.png" width="321.89761625635015" />
    <figcaption>Главный экран системных Настроек</figcaption>
  </figure>
  <p id="PYto">2) Выберите нужное приложение. Если его нет в списке &quot;Недавно открывавшиеся приложения&quot;, нажмите <strong>Показать все приложения</strong>, и затем выберите нужное.</p>
  <figure id="bUSf" class="m_custom" data-caption-align="center">
    <img src="https://img2.teletype.in/files/9e/30/9e308037-13b2-438e-8ebb-80ff89dcfc99.png" width="321.232121922626" />
    <figcaption>Раздел &quot;Приложения&quot; в Настройках.</figcaption>
  </figure>
  <p id="M6OZ">3) В правом верхнем углу подраздела есть кнопка с лупой. Нажмите на нее,чтобы войти в режим поиска по имени приложения. </p>
  <figure id="Kol3" class="m_custom" data-caption-align="center">
    <img src="https://img4.teletype.in/files/fd/fc/fdfc560b-8cc1-4424-83a5-355236371511.png" width="319.8276670574444" />
    <figcaption>Подраздел &quot;Все приложения&quot; раздела &quot;Приложения&quot; в Настройках.</figcaption>
  </figure>
  <p id="hq4b">3.1) Выберете приложение</p>
  <figure id="4W52" class="m_custom" data-caption-align="center">
    <img src="https://img1.teletype.in/files/0d/90/0d903ba9-98eb-4ac7-9bc3-e7b09bf221b6.png" width="319.99999999999994" />
    <figcaption>Поиск приложения &quot;Камера&quot; в списке всех приложений.</figcaption>
  </figure>
  <p id="ipNJ">4) В разделе &quot;О приложении&quot; выберите <strong>Разрешения</strong>.</p>
  <figure id="za4i" class="m_custom" data-caption-align="center">
    <img src="https://img2.teletype.in/files/13/f4/13f44b78-9318-426d-aef5-e356c05c6f0c.png" width="322" />
    <figcaption>Информация о приложении &quot;Камера&quot;.</figcaption>
  </figure>
  <p id="YI2z">5) Откроется список разрешений приложения.</p>
  <figure id="NoK4" class="m_custom" data-caption-align="center">
    <img src="https://img1.teletype.in/files/49/71/49719eb6-d8d6-4797-9dff-f1fd17b1fb28.png" width="321.00000000000006" />
    <figcaption>Все разрешения приложения &quot;Камера&quot;.</figcaption>
  </figure>
  <p id="OwbR">6) Чтобы изменить настройки определенного разрешения, нажмите на него и выберите из списка.</p>
  <figure id="6iUB" class="m_custom" data-caption-align="center">
    <img src="https://img1.teletype.in/files/4f/37/4f374976-99e5-4ebe-aa17-0f192baef94e.png" width="320.1254396248534" />
    <figcaption>Выбор разрешения для доступа к камере.</figcaption>
  </figure>
  <p id="iyIs">Как правило возможны следующие варианты предоставления доступа:</p>
  <ul id="ouqJ">
    <li id="5hz9"><strong>Всегда</strong> (применимо только для доступа к данным о местоположении) – разрешение действует все время, даже когда приложение не используется.</li>
    <li id="I0MP"><strong>Разрешить только во время использования приложения</strong> – разрешение действует, пока вы пользуетесь приложением.</li>
    <li id="w8do"><strong>Всегда спрашивать</strong> – приложение будет запрашивать разрешение каждый раз, когда вы им пользуетесь. Разрешение будет действовать, пока вы не закроете приложение.</li>
    <li id="GxCD"><strong>Запретить</strong> – приложение не сможет пользоваться разрешением даже во время работы.</li>
  </ul>
  <p id="VXiz">Подробнее можно <a href="https://support.google.com/android/answer/9431959" target="_blank">почитать здесь</a>.</p>
  <p id="DqSo"></p>
  <h2 id="uFCP">Изменить разрешения через контекстное меню</h2>
  <p id="uYDv">Альтернативный вариант настройки разрешений возможен через вызов контекстного меню &quot;О приложении&quot;. Оно несколько меняется в зависимости от версии операционной системы Android и пользовательской оболочки, но общий принцип следующий:</p>
  <ol id="M8nP">
    <li id="WQ7T"><strong>Долгое нажатие на иконку приложения</strong>: На главном экране или в панели приложений нажмите и удерживайте иконку приложения, для которого вы хотите изменить разрешения.</li>
    <li id="INmm"><strong>Открытие контекстного меню</strong>: После долгого нажатия появится контекстное меню. Ищите пункт, как правило, названный &quot;О приложении&quot; или &quot;Информация о приложении&quot;. В некоторых случаях это может быть иконка с символом &quot;i&quot; в маленьком кружке.</li>
    <li id="KkNu"><strong>Переход к настройкам разрешений:</strong> Коснитесь &quot;О приложении&quot; и в открывшемся окне информации о приложении найдите раздел &quot;Разрешения&quot;.</li>
    <li id="y4et"><strong>Настройка разрешений</strong>: В разделе &quot;Разрешения&quot; вы увидите список всех запрашиваемых приложением разрешений. Здесь вы сможете изменять разрешения, активируя или деактивируя доступ для каждого из них.</li>
  </ol>
  <p id="pfYC"></p>
  <figure id="CrzZ" class="m_column" data-caption-align="center">
    <iframe src="https://www.youtube.com/embed/5guul1zap_0?autoplay=0&loop=1&mute=1&playlist=5guul1zap_0"></iframe>
    <figcaption>Видео демонстрация.</figcaption>
  </figure>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@hikkidev/kotlin-java-interop</guid><link>https://teletype.in/@hikkidev/kotlin-java-interop?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=hikkidev</link><comments>https://teletype.in/@hikkidev/kotlin-java-interop?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=hikkidev#comments</comments><dc:creator>hikkidev</dc:creator><title>Kotlin-Java interop: 'companion object' and 'private' visibility modifier</title><pubDate>Tue, 02 Apr 2024 13:19:32 GMT</pubDate><media:content medium="image" url="https://img1.teletype.in/files/c5/c0/c5c01923-c4cf-403c-8e70-d0646a3fb5c2.png"></media:content><category>Kotlin</category><description><![CDATA[<img src="https://img1.teletype.in/files/4e/e1/4ee120fa-620c-4d7d-9557-f74f1eaf0e46.jpeg"></img>Пост представляет собой ответ на частый вопрос &quot;почему ты использовал  private companion object с вложенными private const val?&quot;]]></description><content:encoded><![CDATA[
  <blockquote id="9Fh1">Заметка: данный пост представляет собой небольшое объяснение на частый вопрос &quot;почему используешь  <code>private companion object</code> с вложенными <code>private const val</code>?&quot;</blockquote>
  <p id="jkDv"><strong>Оглавление</strong></p>
  <hr />
  <h2 id="NiPo">Дано</h2>
  <p id="xYzx">Рассмотрим пример с полями в <code>companion object</code>:</p>
  <pre id="NfzR" data-lang="kotlin">class KotlinClassSample {

    companion object {
        @JvmField
        val PUBLIC_STATIC_FIELD  = emptyList()
        val publicNonStaticField = emptyList()
        const val PUBLIC_STATIC_PRIMITIVE_FIELD = 0

        // JvmField has no effect on a private property
        private val privateField = emptyList()
        private const val PRIVATE_STATIC_PRIMITIVE_FIELD = 0
    }
}</pre>
  <p id="R08m">Проверим доступ к <code>KotlinClassSample</code> коду из Java и Kotlin:</p>
  <pre id="WHoa" data-lang="java">class JavaClassAccessTest {

    void callingKotlinFromJava() {
        // OK
        KotlinClassSample.PUBLIC_STATIC_FIELD;
        KotlinClassSample.PUBLIC_STATIC_PRIMITIVE_FIELD;
        KotlinClassSample.Companion.getPublicNonStaticField();
    }
}</pre>
  <pre id="gH9g" data-lang="kotlin">class KotlinClassAccessTest {

    fun callingKotlinFromKotlin() {
        // OK
        KotlinClassSample.PUBLIC_STATIC_FIELD
        KotlinClassSample.PUBLIC_STATIC_PRIMITIVE_FIELD
        KotlinClassSample.publicNonStaticField
    }
}</pre>
  <p id="T6e3">Ожидаемое поведение на основе модификатора доступа <code>public</code> у <code>companion object</code> подтвердилось. </p>
  <p id="Gjsa">Теперь сменим модификатор на <code>private</code> и можем наблюдать следующее:</p>
  <pre id="iQT8" data-lang="java">class JavaClassAccessTest {

    void callingKotlinFromJava() {
        // OK
        KotlinClassSample.PUBLIC_STATIC_FIELD;
        KotlinClassSample.PUBLIC_STATIC_PRIMITIVE_FIELD;

        // Error: &#x27;Companion&#x27; has private access in &#x27;KotlinClassSample&#x27;
        KotlinClassSample.Companion.getPublicNonStaticField(); // inaccessible
    }
}</pre>
  <pre id="P7H0" data-lang="kotlin">class KotlinClassAccessTest {

    fun callingKotlinFromKotlin() {
        // Error: Cannot access &#x27;Companion&#x27;: it is private in &#x27;KotlinClassSample&#x27;
        KotlinClassSample.PUBLIC_STATIC_FIELD           // inaccessible
        KotlinClassSample.PUBLIC_STATIC_PRIMITIVE_FIELD // inaccessible
        KotlinClassSample.publicNonStaticField          // inaccessible
    }
}</pre>
  <p id="BiDa">В голове у непосвященного человека может возникнуть резонный вопрос:</p>
  <figure id="tqxm" class="m_custom" data-caption-align="center">
    <iframe src="https://www.youtube.com/embed/hZYkVIEM_4A?autoplay=0&loop=1&mute=0&playlist=hZYkVIEM_4A"></iframe>
    <figcaption>Почему так?⁠⁠</figcaption>
  </figure>
  <h2 id="9e59">Решение</h2>
  <p id="Qh3N">Чтобы понять &quot;почему&quot;, декомпилируем <code>KotlinClassSample</code> c <code>public companion object</code>:</p>
  <pre id="d5FA" data-lang="java">public final class KotlinClassSampleDecompiled {
    public static final CompanionObject Companion = new CompanionObject();

    public  static final int  PUBLIC_STATIC_PRIMITIVE_FIELD = 0;
    public  static final List PUBLIC_STATIC_FIELD  = EmptyList();
    private static final List publicNonStaticField = EmptyList();
    
    private static final int  PRIVATE_STATIC_PRIMITIVE_FIELD = 0;
    private static final List privateField = EmptyList();


    public static final class CompanionObject {

        public List getPublicNonStaticField() {
            return KotlinClassSampleDecompiled.publicNonStaticField;
        }
    }
}</pre>
  <p id="HquM">И декомпилируем <code>KotlinClassSample</code>  c <code>private companion object</code>:</p>
  <pre id="xEj6" data-lang="java">public final class KotlinClassSampleDecompiled {
    private static final CompanionObject Companion = new CompanionObject();

    public  static final int  PUBLIC_STATIC_PRIMITIVE_FIELD = 0;
    public  static final List PUBLIC_STATIC_FIELD  = EmptyList();
    private static final List publicNonStaticField = EmptyList();

    private static final int  PRIVATE_STATIC_PRIMITIVE_FIELD = 0;
    private static final List privateField = EmptyList();


    private static final class CompanionObject {

        public List getPublicNonStaticField() {
            return KotlinClassSampleDecompiled.publicNonStaticField;
        }
    }
}</pre>
  <blockquote id="DLWY">Заметка: содержимое <code>Decompiled</code> классов упрощено для повышения читабельности.</blockquote>
  <p id="lEEr">Как можно видеть, применение модификатора <code>private</code> к <code>companion object</code>  изменило видимость только у класса <code>CompanionObject</code>, поля <code>Companion</code>, и как следствие геттера <code>CompanionObject#getPublicNonStaticField</code>.</p>
  <h2 id="pezX">Ответ</h2>
  <p id="K8Cx">В общем-то магии никакой нет, и статические свойства объявленные в Kotlin через <code>@JvmField</code> или <code>const val</code> компилируются в Java как <code>static final</code> поля <u>родительского класса</u>, в который вкладывается сгенерированный класс <code>CompanionObject</code>. </p>
  <p id="kcjb">Поэтому  использование  <code>private companion object</code> с вложенными <code>private const val</code> следует воспринимать нормально, возможно даже более &quot;верно&quot;. Другое дело, если проект написан только на Kotlin, то <code>private companion object</code> будет достаточно для ограничения видимости.</p>
  <blockquote id="ObGG">Заметка: на последующих этапах компиляции применяются оптимизации и базовые типы объявленные через <code>const</code> будут подставленны в место их вызова, как шаблоны в C++, но это отдельная тема :)</blockquote>
  <hr />
  <p id="SbUk"><strong>Дополнительно </strong>прилагаю пример с методами, вывод аналогичен - статические функции\методы компилируются к <u>родительскому классу</u>, см. декомпилированный код внизу.</p>
  <p id="VPlJ">Дано:</p>
  <pre id="NpXi" data-lang="kotlin">class KotlinClassSample {

    companion object {
        @JvmStatic
        fun publicStaticFun() = Unit
        fun publicNonStaticFun() = Unit

        @JvmStatic
        private fun privateStaticFun() = Unit
        private fun privateNonStaticFun() = Unit
    }
}</pre>
  <p id="7Vrz">Проверяем доступ к <code>KotlinClassSample</code> коду из Java и Kotlin:</p>
  <pre id="cjhk" data-lang="java">class JavaClassAccessTest {

    void callingKotlinFromJava() {
        // OK
        KotlinClassSample.publicStaticFun();
        KotlinClassSample.Companion.publicStaticFun();
        KotlinClassSample.Companion.publicNonStaticFun();
    }
}</pre>
  <pre id="MBDr" data-lang="kotlin">class KotlinClassAccessTest {

    fun callingKotlinFromKotlin() {
        // OK
        KotlinClassSample.publicStaticFun()
        KotlinClassSample.publicNonStaticFun()
    }
}</pre>
  <p id="zN2V">Изменим модификатор доступа у <code>companion object</code> на <code>private</code> и посмотрим, что изменилось:</p>
  <pre id="lIjS" data-lang="java">class JavaClassAccessTest {

    void callingKotlinFromJava() {
        // OK
        KotlinClassSample.publicStaticFun();

        // Error: &#x27;KotlinClassSample.Companion&#x27; has private access
        KotlinClassSample.Companion.publicStaticFun();    // inaccessible
        KotlinClassSample.Companion.publicNonStaticFun(); // inaccessible
    }
}</pre>
  <pre id="HTem" data-lang="kotlin">class KotlinClassAccessTest {

    fun callingKotlinFromKotlin() {
        // Error: Cannot access &#x27;Companion&#x27;: it is private in &#x27;KotlinClassSample&#x27;
        KotlinClassSample.publicStaticFun()    // inaccessible
        KotlinClassSample.publicNonStaticFun() // inaccessible
    }
}</pre>
  <p id="b8IP">Декомпилированный <code>KotlinClassSample</code> c <code>public companion object</code>:</p>
  <pre id="T8bp" data-lang="java">public final class KotlinClassSampleDecompiled {
 
    public static final CompanionObject Companion = new CompanionObject();

    public static void publicStaticFun() {
        Companion.publicStaticFun();
    }

    private static void privateStaticFun() {
        Companion.privateStaticFun();
    }

    public static final class CompanionObject {
  
        public void publicStaticFun() {}

        public void publicNonStaticFun() {}
        
        private void privateStaticFun() {}

        private void privateNonStaticFun() {}
    }
}</pre>
  <p id="uU3W">Декомпилированный <code>KotlinClassSample</code>  c <code>private companion object</code>:</p>
  <pre id="H6SH" data-lang="java">public final class KotlinClassSampleDecompiled {

    private static final CompanionObject Companion = new CompanionObject();

    public static void publicStaticFun() {
        Companion.publicStaticFun();
    }

    private static void privateStaticFun() {
        Companion.privateStaticFun();
    }

    private static final class CompanionObject {

        public void publicStaticFun() {}

        public void publicNonStaticFun() {}

        private void privateStaticFun() {}

        private void privateNonStaticFun() {}
    }
}</pre>
  <p id="rPMo"></p>
  <h2 id="49az">Литература</h2>
  <ul id="klBg">
    <li id="wLuR"><a href="https://kotlinlang.org/docs/java-to-kotlin-interop.html#static-fields" target="_blank">https://kotlinlang.org/docs/java-to-kotlin-interop.html#static-fields</a></li>
    <li id="A186"><a href="https://kotlinlang.org/docs/java-to-kotlin-interop.html#static-methods" target="_blank">https://kotlinlang.org/docs/java-to-kotlin-interop.html#static-methods</a></li>
    <li id="dtC4"><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/-jvm-field" target="_blank">https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/-jvm-field</a></li>
  </ul>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@hikkidev/memo-ifecycle-runtime-ktx-and-kotlin-flow</guid><link>https://teletype.in/@hikkidev/memo-ifecycle-runtime-ktx-and-kotlin-flow?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=hikkidev</link><comments>https://teletype.in/@hikkidev/memo-ifecycle-runtime-ktx-and-kotlin-flow?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=hikkidev#comments</comments><dc:creator>hikkidev</dc:creator><title>Памятка: как подписываться на Kotlin Coroutines Flow с lifecycle-runtime-ktx версии 2.4.0 и выше</title><pubDate>Tue, 21 Mar 2023 02:52:39 GMT</pubDate><description><![CDATA[<img src="https://img1.teletype.in/files/0b/bb/0bbb9ba9-efdd-4142-b857-4039aa362d76.png"></img>
Рассмотрим поведение на примере с отображением некоторых данных на пользовательский интерфейс (UI).]]></description><content:encoded><![CDATA[
  <nav>
    <ul>
      <li class="m_level_1"><a href="#NIbn">Введение</a></li>
      <li class="m_level_1"><a href="#N6Hk">Подписка на Flow для версии lifecycle-runtime-ktx ниже 2.4.0</a></li>
      <li class="m_level_1"><a href="#ZViM">Что за viewLifecycleOwner.lifecycleScope ?</a></li>
      <li class="m_level_1"><a href="#DTpO">Подписка на Flow для версии lifecycle-runtime-ktx 2.4.0 и выше</a></li>
    </ul>
  </nav>
  <h3 id="NIbn">Введение</h3>
  <p id="T3Im"><br />Рассмотрим поведение на примере с отображением некоторых данных на пользовательский интерфейс (UI).</p>
  <p id="WRbl">Пусть дан фрагмент:</p>
  <pre id="yedk" data-lang="kotlin">class SampleFragment : BindingFragment(R.layout.fragment_sample) {
    override val binding by viewBinding&lt;FragmentSampleBinding&gt;()
    override val viewModel by viewModelFactory&lt;SampleViewModel&gt;()
}</pre>
  <p id="7vB5">где функции <code>viewBinding</code> и <code>viewModelFactory</code> являются некоторыми <a href="https://kotlinlang.org/docs/delegated-properties.html" target="_blank">PropertyDelegate</a>.</p>
  <p id="l09E">Цель - <strong>перезапускать</strong> подписку на <code>Flow</code> только в те моменты, когда пользовательский интерфейс <strong>виден</strong>. Использование функций <code>launchWhen*</code> неподходит, так как корутина <strong>приостанавливает</strong> своё выполнение.</p>
  <ul id="9G3S">
    <li id="I0nO"><code><a href="https://developer.android.com/reference/androidx/fragment/app/Fragment#onStart()" target="_blank">Fragment.onStart()</a></code> срабатывает, когда <code>Fragment</code> становится видимым для пользователя без взаимодействия. Это хорошее место, чтобы начать рисовать визуальные элементы, запускать анимацию и т.д.</li>
    <li id="wbCm"><code><a href="https://developer.android.com/reference/androidx/fragment/app/Fragment#onStop()" target="_blank">Fragment.onStop()</a></code> вызывается, когда <code>Fragment</code> перестает быть видимым для пользователя. Это хорошее место для прекращения обновления пользовательского интерфейса, отмены анимации и других визуальных действий.</li>
  </ul>
  <hr />
  <h3 id="N6Hk">Подписка на Flow для версии lifecycle-runtime-ktx ниже 2.4.0</h3>
  <p id="rSjD"><br />Если требуется выполнить подписку только для одного <code>Flow</code>, то достаточно вызвать <code>Flow.collect()</code> в рамках начальной корутины <code>uiChangesJob</code>:</p>
  <pre id="SRGT" data-lang="kotlin">import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collect  
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
...
import androidx.lifecycle.lifecycleScope

class SampleFragment : BindingFragment(R.layout.fragment_sample) {
	...
    private var uiChangesJob: Job? = null
	
	override fun onStart() {
	    super.onStart()
	    uiChangesJob = viewLifecycleOwner.lifecycleScope.launch {
	        // Делаем свою магию, например подписка
	        viewModel.screenState
		        .onEach { state -&gt; render(state) }
		        .collect()
	    }
	}
	
	override fun onStop() {
	    uiChangesJob?.cancel()
	    super.onStop()
	}
}</pre>
  <p id="wtBW">Однако если требуется выполнить подписку для нескольких <code>Flow</code> параллельно, то необходимо подписываться на каждый Flow в разных корутинах. В этом случае эффективнее использовать <code><a href="https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/launch-in.html" target="_blank">Flow.launchIn()</a></code>:</p>
  <pre id="EQ2s" data-lang="kotlin">uiChangesJob = viewLifecycleOwner.lifecycleScope.launch {

	viewModel.screenTitleFlow
		.onEach { text -&gt; binding.titleView.text = text }
		.launchIn(this)
	
	viewModel.buttonStateFlow
		.onEach { isEnabled -&gt; binding.buttonView.isEnabled = isEnabled }
		.launchIn(this)
	...
}</pre>
  <hr />
  <h3 id="ZViM">Что за <code>viewLifecycleOwner.lifecycleScope</code> ?</h3>
  <p id="xU42"><br />Начнём с того, что <code><a href="https://developer.android.com/reference/androidx/fragment/app/Fragment#getViewLifecycleOwner%28%29" target="_blank">viewLifecycleOwner</a></code> - это <code>LifecycleOwner</code>, который описывает жизненный цикл представления <code><a href="https://developer.android.com/reference/androidx/fragment/app/Fragment#onCreateView(android.view.LayoutInflater,android.view.ViewGroup,android.os.Bundle)" target="_blank">Fragment.onCreateView()</a></code>. </p>
  <p id="41VA">Далее <code><a href="https://developer.android.com/topic/libraries/architecture/coroutines#lifecyclescope" target="_blank">LifecycleScope</a></code>  -  это <code><a href="https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/" target="_blank">CoroutineScope</a></code> жизненного цикла, который определен для каждого объекта <code>Lifecycle</code>. <br />По умолчанию экземпляр <code>LifecycleScope</code> <u>создается <strong>только</strong> в момент доступа</u> к свойству <code>LifecycleOwner.lifecycleScope</code>. <br /><br />Поскольку <code>androidx.fragment.app.Fragment</code> является объектом <code>Lifecycle</code>, то</p>
  <ul id="rgnu">
    <li id="ommw">корутины объявленные во <code>Fragment.lifecycleScope</code> могут существовать                                   после вызова первичного конструктора <code>Fragment()</code> и до вызова <code>Fragment.onDestroy()</code>.</li>
    <li id="yRc0">корутины объявленные во <code>Fragment.viewLifecycleOwner.lifecycleScope</code> могут существовать от вызова <code>Fragment.onViewStateRestored()</code> до вызова <code>Fragment.onDestroyView()</code>.</li>
  </ul>
  <p id="HCF5"></p>
  <figure id="w1kq" class="m_retina" data-caption-align="center">
    <img src="https://img1.teletype.in/files/0b/bb/0bbb9ba9-efdd-4142-b857-4039aa362d76.png" width="928" />
    <figcaption>Диаграмма сопоставления состояний ЖЦ <code>Lifecycle</code> и обратных вызовов <code>Fragment</code></figcaption>
  </figure>
  <p id="M1ks"></p>
  <blockquote id="2iTz">Для эффективного использования ресурсов устройства разработчику необходимо (но недостаточно) понимать тонкости работы жизненного цикла и особенностей Coroutines. Все зависит от целей использования, главное понимание границ!</blockquote>
  <hr />
  <h3 id="DTpO">Подписка на Flow для версии lifecycle-runtime-ktx 2.4.0 и выше</h3>
  <p id="dXVC"><br />Тут все гораздо проще. Теперь API предоставляет специальную функцию, которая избавляет разработчика писать <a href="https://ru.wikipedia.org/wiki/%D0%A8%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BA%D0%BE%D0%B4" target="_blank">шаблонный код</a> с подписками/отписками. </p>
  <blockquote id="uZfC">Данный поход является официальной рекомендацией к использованию.</blockquote>
  <p id="2sdS">Если требуется выполнить подписку только для одного <code>Flow</code>, то достаточно вызвать <code><a href="https://developer.android.com/reference/kotlin/androidx/lifecycle/package-summary#(kotlinx.coroutines.flow.Flow).flowWithLifecycle(androidx.lifecycle.Lifecycle,androidx.lifecycle.Lifecycle.State)" target="_blank">Flow.flowWithLifecycle()</a></code> в рамках начальной корутины:</p>
  <pre id="ckOc" data-lang="kotlin">import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collect  
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
...
import androidx.lifecycle.lifecycleScope

class SampleFragment : BindingFragment(R.layout.fragment_sample) {
	...
	
	override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
	    viewLifecycleOwner.lifecycleScope.launch {
	        viewModel.screenState
		        .flowWithLifecycle(viewLifecycleOwner.lifecycle,Lifecycle.State.STARTED)
		        .collect { state -&gt; render(state) }
	    }
	}
}</pre>
  <p id="6rQb">Однако если требуется выполнить подписку для нескольких <code>Flow</code> параллельно, то необходимо подписываться на каждый <code>Flow</code> в разных корутинах. В этом случае эффективнее использовать <code><a href="https://developer.android.com/reference/kotlin/androidx/lifecycle/package-summary#(androidx.lifecycle.LifecycleOwner).repeatOnLifecycle(androidx.lifecycle.Lifecycle.State,kotlin.coroutines.SuspendFunction1)" target="_blank">LifecycleOwner.repeatOnLifecycle()</a></code>:</p>
  <pre id="hAuQ" data-lang="kotlin">viewLifecycleOwner.lifecycleScope.launch {
    // Можно вставить код, который исполнится до состояния ЖЦ STARTED
	viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
	    // repeatOnLifecycle запускает блок в новой короутине каждый раз, когда
		// жизненный цикл находится в состоянии STARTED (или выше)
		// и отменяет его, когда он STOPPED.
		viewModel.screenTitleFlow
			.onEach { text -&gt; binding.titleView.text = text }
			.launchIn(this)
		
		viewModel.buttonStateFlow
			.onEach { isEnabled -&gt; binding.buttonView.isEnabled = isEnabled }
			.launchIn(this)
	}
}</pre>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@hikkidev/yubikey-as-login-pam</guid><link>https://teletype.in/@hikkidev/yubikey-as-login-pam?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=hikkidev</link><comments>https://teletype.in/@hikkidev/yubikey-as-login-pam?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=hikkidev#comments</comments><dc:creator>hikkidev</dc:creator><title>The Yubikey as a Login device on local Arch Linux</title><pubDate>Fri, 07 Oct 2022 16:00:10 GMT</pubDate><media:content medium="image" url="https://img1.teletype.in/files/0e/da/0edacf72-f2a8-4292-9112-bec39de11faf.png"></media:content><category>Arch Linux</category><description><![CDATA[<img src="https://img3.teletype.in/files/e7/9f/e79f928b-e3bf-4450-b3b5-c67cb49f8207.png"></img>Note: Recommended specifying the actual hostname into the environment variableHOST. Keep in mind that in the command above, the actual hostname is picked from the file /etc/hostname.]]></description><content:encoded><![CDATA[
  <h3 id="mx03">1) Installing the <a href="https://archlinux.org/packages/community/x86_64/pam-u2f/" target="_blank">PAM module</a></h3>
  <pre id="JT3S">sudo pacman -S pam-u2f</pre>
  <hr />
  <h3 id="HzJl">2) Associating the U2F Key with Your Account</h3>
  <ul id="1Aon">
    <li id="0MW9">Insert your U2F Key</li>
    <li id="ULgR">Run command below. When your device begins flashing, touch the metal contact to confirm the association.</li>
  </ul>
  <pre id="VIJO">HOST=$(cat /etc/hostname) pamu2fcfg -o pam://$HOST -i pam://$HOST &gt; u2f_keys &amp;&amp; sudo mkdir -vp /etc/Yubico &amp;&amp; sudo mv -v u2f_keys /etc/Yubico</pre>
  <p id="hHnK"><strong>Note:</strong> Recommended specifying the actual hostname into the environment variable<code>HOST</code>. Keep in mind that in the command above, the actual hostname is picked from the file <code>/etc/hostname</code>.</p>
  <hr />
  <h3 id="pIT7">3) Configuring the System to use the U2F Keys</h3>
  <p id="mC43">Open the <code>system-login</code> file and add the following <strong>debug</strong> or <strong>release</strong> line to the top of the <code>auth</code> section. </p>
  <pre id="90Gf">sudo $EDITOR /etc/pam.d/system-login</pre>
  <p id="nMs5"><strong>MODE: Debug</strong></p>
  <pre id="fI8W">auth  sufficient  pam_u2f.so  debug debug_file=/var/log/pam_u2f.log authfile=/etc/Yubico/u2f_keys cue</pre>
  <p id="f5Yf"><strong>MODE: Release</strong></p>
  <pre id="Xx4T">auth  sufficient  pam_u2f.so  authfile=/etc/Yubico/u2f_keys cue</pre>
  <p id="Qxoj"><strong>Notes:</strong> </p>
  <ul id="eZhE">
    <li id="IJ3K">The reason that the <code>sufficient</code> line is there is that if the u2f-key is messed up, then you&#x27;ll be able to log on via password.</li>
    <li id="JxeZ">The option <code>cue</code> is set to provide indication of what to do, i.e. <code>Please touch the device</code>.</li>
  </ul>
  <figure id="YPlA" class="m_column" data-caption-align="center">
    <img src="https://img3.teletype.in/files/e7/9f/e79f928b-e3bf-4450-b3b5-c67cb49f8207.png" width="859" />
    <figcaption>An example of the content of &#x60;system-login&#x60; with a release line.</figcaption>
  </figure>
  <p id="aK8v"><strong>Note:</strong> You can select another PAM-stack:</p>
  <blockquote id="ZnJ0">The <code>/etc/pam.d/</code> path is exclusive for the PAM configuration to link the applications to the individual systems&#x27; authentication schemes. </blockquote>
  <blockquote id="JEG6">The different configuration files of the base installation link together and are stacked during runtime. For example, on a local user logon, the <em>login</em> application sources the <code>system-local-login</code> policy, which in turn sources others:</blockquote>
  <pre id="imEP">/etc/pam.d/
----------------------------------------------------------
login -&gt; system-local-login -&gt; system-login -&gt; system-auth</pre>
  <p id="jqrl">Source: <a href="https://wiki.archlinux.org/title/PAM" target="_blank">https://wiki.archlinux.org/title/PAM</a></p>
  <hr />
  <h3 id="izZx">4) Reboot the computer or exit from your session.</h3>
  <h3 id="eUxq">5) When the login screen is loaded, it should ask you to touch the device.</h3>
  <hr />
  <h2 id="3kPx"></h2>
  <h2 id="vSnT">References</h2>
  <ol id="JCfr">
    <li id="3Iqw"><a href="https://wiki.archlinux.org/title/PAM" target="_blank">https://wiki.archlinux.org/title/PAM</a></li>
    <li id="arWT"><a href="https://wiki.archlinux.org/title/Universal_2nd_Factor" target="_blank">https://wiki.archlinux.org/title/Universal_2nd_Factor</a></li>
    <li id="JMB0"><a href="https://wiki.archlinux.org/title/YubiKey#Linux_user_authentication_with_PAM" target="_blank">https://wiki.archlinux.org/title/YubiKey#Linux_user_authentication_with_PAM</a></li>
    <li id="tMk1"><a href="https://support.yubico.com/hc/en-us/articles/360016649099-Ubuntu-Linux-Login-Guide-U2F" target="_blank">https://support.yubico.com/hc/en-us/articles/360016649099-Ubuntu-Linux-Login-Guide-U2F</a></li>
    <li id="TSON"><a href="https://jamesthebard.net/archlinux-and-u2f-login/" target="_blank">https://jamesthebard.net/archlinux-and-u2f-login/</a></li>
  </ol>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@hikkidev/android-studio-logcat-config</guid><link>https://teletype.in/@hikkidev/android-studio-logcat-config?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=hikkidev</link><comments>https://teletype.in/@hikkidev/android-studio-logcat-config?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=hikkidev#comments</comments><dc:creator>hikkidev</dc:creator><title>View Logs with Logcat (Android Studio Dolphin и ниже)</title><pubDate>Wed, 13 Apr 2022 15:56:31 GMT</pubDate><media:content medium="image" url="https://img4.teletype.in/files/38/50/38509653-b7d4-492a-80fe-fcf1efdb05d7.png"></media:content><category>Android Studio</category><description><![CDATA[<img src="https://img2.teletype.in/files/1e/d0/1ed03ca1-be26-4c23-8080-336c8408213f.png"></img>Обновленный Logcat -&gt; https://alexzh.com/new-logcat-5-features-for-effective-android-app-debugging/]]></description><content:encoded><![CDATA[
  <p id="CgEb">В версии Android Studio Electric Eel | 2022.1.1 (Jan 2023) был включен новый Logcat, чтобы упростить анализ, запросы и отслеживание журналов. Поэтому данная актуальна только для старых версий Android Studio: Dolphin и ниже.<br /></p>
  <p id="kXDH">Обновленный Logcat -&gt; <a href="https://alexzh.com/new-logcat-5-features-for-effective-android-app-debugging/" target="_blank">https://alexzh.com/new-logcat-5-features-for-effective-android-app-debugging/</a><br /></p>
  <nav>
    <ul>
      <li class="m_level_1"><a href="#x0BA">Что такое Logcat</a></li>
      <li class="m_level_1"><a href="#XCU7">Просмотр журнала (View your app logs)</a></li>
      <li class="m_level_1"><a href="#RIzT">Основные функции 1-9 в окне Logcat</a></li>
      <li class="m_level_2"><a href="#1rHO">Формат сообщения Logcat</a></li>
      <li class="m_level_1"><a href="#e6jr">Установка цветовой схемы</a></li>
      <li class="m_level_1"><a href="#jMRF">Фильтрация сообщений Logcat</a></li>
      <li class="m_level_1"><a href="#WvLs">Global-Filter (E)</a></li>
      <li class="m_level_2"><a href="#kPDu">Добавление новых фильтров</a></li>
      <li class="m_level_2"><a href="#tMi9">Исключить сообщения ОС из Logcat</a></li>
      <li class="m_level_2"><a href="#HSYA">Log level (описание)</a></li>
      <li class="m_level_1"><a href="#pvQU">Search Filter (D)</a></li>
      <li class="m_level_2"><a href="#T5k5">Поиск в логах</a></li>
    </ul>
  </nav>
  <hr />
  <h2 id="x0BA" data-align="center">Что такое Logcat</h2>
  <p id="2Ehm">Окно Logcat в Android Studio отображает системные сообщения (Логи) в режиме реального времени и хранит историю, чтобы вы могли просматривать более старые сообщения. Например, когда приложение выдает исключение, logcat показывает сообщение, за которым следует соответствующая трассировка стека, содержащая ссылки на строку кода.</p>
  <p id="C645">Чтобы отображать только интересующую информацию, вы можете создавать фильтры, изменять объем информации, отображаемой в сообщениях, устанавливать уровни приоритета, отображать сообщения, созданные только кодом приложения, и выполнять поиск в журнале. </p>
  <p id="EeMg">По умолчанию logcat показывает выходные данные журнала, относящиеся только к последнему запущенному приложению.</p>
  <hr />
  <h2 id="XCU7">Просмотр журнала (View your app logs)</h2>
  <p id="y6Oh">Чтобы отобразить сообщения журнала для приложения:</p>
  <ol id="hTwG">
    <li id="ho3C">Запустите приложение</li>
    <li id="Ck7G">Нажмите <strong>View &gt; Tool Windows &gt; Logcat</strong> (или нажмите Logcat на панели инструментов)</li>
  </ol>
  <figure id="WJHM" class="m_original" data-caption-align="center">
    <img src="https://img2.teletype.in/files/1e/d0/1ed03ca1-be26-4c23-8080-336c8408213f.png" width="407" />
    <figcaption>Рисунок 1. Скриншот из Android Studio</figcaption>
  </figure>
  <p id="I2yC">В окне Logcat отображаются сообщения журнала для выбранного приложения, как показано на рисунке 2.</p>
  <hr />
  <h2 id="RIzT" data-align="center">Основные функции 1-9 в окне Logcat</h2>
  <figure id="gRXH" class="m_retina" data-caption-align="center">
    <img src="https://img2.teletype.in/files/93/a3/93a38503-834b-479b-b725-1557a0d856ce.png" width="1108" />
    <figcaption>Рисунок 2. Окно Logcat.</figcaption>
  </figure>
  <p id="GyNh">Рассмотрим боковые функции 1-9:</p>
  <ol id="cHV1">
    <li id="N6Oh"><strong>Очистка:</strong> Нажмите, чтобы очистить видимый журнал.</li>
    <li id="ujfQ"><strong>Прокрутка в конец: </strong>нажмите, чтобы перейти к нижней части журнала и просмотреть последние сообщения журнала. Если затем щелкнуть строку в журнале, представление приостановит прокрутку в этой точке.</li>
    <li id="3BNB"><strong>Вверх и Вниз</strong> по трассировке стека: Нажмите, чтобы перемещаться вверх и вниз по трассировке стека в журнале, выбирая последующие имена файлов (и просматривая соответствующие номера строк в редакторе), которые появляются в печатных исключениях. Это то же самое поведение, что и при нажатии на имя файла в журнале.</li>
    <li id="uKGz">Использовать<strong> мягкие переносы</strong>: нажмите, чтобы включить перенос строк и запретить горизонтальную прокрутку (хотя любые неразрывные строки по-прежнему требуют горизонтальной прокрутки).</li>
    <li id="Ixpc"><strong>Печать</strong>: Нажмите, чтобы распечатать сообщения logcat. После выбора настроек печати в появившемся диалоговом окне вы также можете сохранить файл в формате PDF.</li>
    <li id="VgGA"><strong>Перезапустить</strong>: нажмите, чтобы очистить журнал и перезапустить logcat. В отличие от кнопки «Очистить logcat», эта кнопка восстанавливает и отображает предыдущие сообщения журнала, поэтому наиболее полезна, если Logcat перестает отвечать на запросы и вы не хотите терять сообщения журнала.</li>
    <li id="1ubH"><strong>Заголовок Logcat:</strong> нажмите, чтобы открыть диалоговое окно «Настройка заголовка Logcat», в котором можно настроить внешний вид каждого сообщения logcat, например указать, показывать ли дату и время (Рисунки 3-4.)</li>
    <li id="a7R6"><strong>Снимок </strong>экрана: нажмите, чтобы сделать снимок экрана.</li>
    <li id="WUjf"><strong>Запись </strong>экрана: Нажмите, чтобы записать видео с устройства (максимум 3 минуты).</li>
  </ol>
  <figure id="G72W" class="m_original" data-caption-align="center">
    <img src="https://img2.teletype.in/files/da/c7/dac73c58-8d57-4f48-8633-4d6ac05e6bd9.png" width="830" />
    <figcaption>Рисунок 3.  Настройка заголовка Logcat.</figcaption>
  </figure>
  <figure id="S0DI" class="m_original" data-caption-align="center">
    <img src="https://img3.teletype.in/files/e3/4b/e34bf816-f109-4de8-b381-5501979be0f2.png" width="830" />
    <figcaption>Рисунок 4. Рекомендую следующие настройки для повышения читабельности.</figcaption>
  </figure>
  <p id="MSbc"></p>
  <h3 id="1rHO">Формат сообщения Logcat</h3>
  <p id="hTj8">Все сообщения журнала Android имеют определенный формат:</p>
  <pre id="hK6r">Date Time PID-TID/package priority/tag: message </pre>
  <p id="aw9c">На рисунках 3-4, можно наблюдать пример настройки отображения данного формата. Подробнее <a href="https://developer.android.com/studio/debug/am-logcat#format" target="_blank">https://developer.android.com/studio/debug/am-logcat#format</a></p>
  <hr />
  <h2 id="e6jr" data-align="center">Установка цветовой схемы</h2>
  <ol id="qvrD">
    <li id="kU7s">В Android Studio нажмите <strong>File &gt; Settings </strong>(Рисунок 5)<strong>.</strong></li>
    <li id="PxGp">В окне настроек откройте раздел <strong>Editor &gt; Color Scheme &gt; Android Logcat.</strong></li>
    <li id="7nFJ"><a href="https://mega.nz/file/oY1yBIrY#gKM4LgOjnFBAGYY6z-FciMeQZuMiFNgRT2oWF3j2MtE" target="_blank">Скачайте </a>файл настроек цветовой схемы.</li>
    <li id="cwt9">Импортируйте и примените цветовую схему (Рисунок 6).</li>
  </ol>
  <figure id="sCU1" class="m_original" data-caption-align="center">
    <img src="https://img4.teletype.in/files/3a/05/3a057152-4cf6-4759-82c1-2be0b428423a.png" width="295" />
    <figcaption>Рисунок 5. Настройки Android Studio.</figcaption>
  </figure>
  <figure id="6gwP" class="m_column" data-caption-align="center">
    <img src="https://img3.teletype.in/files/2d/c8/2dc8cd41-5e8c-475f-8286-bd762faa2b36.png" width="984" />
    <figcaption>Рисунок 6. Импортирование цветовой схемы для Logcat.</figcaption>
  </figure>
  <p id="tI8L">Теперь логи относящиеся к разным типа сообщений будут иметь различные цвета, что упростит навигацию.</p>
  <hr />
  <h2 id="jMRF" data-align="center">Фильтрация сообщений Logcat</h2>
  <figure id="Fx0G" class="m_retina" data-caption-align="center">
    <img src="https://img2.teletype.in/files/93/a3/93a38503-834b-479b-b725-1557a0d856ce.png" width="1108" />
    <figcaption>Рисунок 7. Окно Logcat.</figcaption>
  </figure>
  <p id="yPan">Перейдем к основным функциям A-E:</p>
  <ul id="GcpS">
    <li id="ZZW2"><strong>A) Current-Device:</strong> Выбор устройства к которому подключится adb. По клику отобразится список доступных устройств (те у которых включен <a href="https://docs.microsoft.com/ru-ru/mem/intune/user-help/you-need-to-turn-off-usb-debugging-android" target="_blank">режим отладки</a> в <a href="https://www.google.com/search?q=android+%D1%80%D0%B5%D0%B6%D0%B8%D0%BC+%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA%D0%B0&ei=Me1WYoDFHaiorgTsw5qgBw&start=0&sa=N&ved=2ahUKEwjAoaGmrpH3AhUolIsKHeyhBnQ4ChDy0wN6BAgBEDw&biw=1718&bih=1200&dpr=1" target="_blank">настройках разработчика</a>)</li>
    <li id="tZoV"><strong>B) Current-Application:</strong> Выбор приложения для отладки к которому подключится Logcat. По клику отобразится список запущенных приложений для отладки. Приложение должно быть скомпилировано в режиме  отладки (DEBUG). По умолчанию выбирается последнее запущенное приложение, <strong>если </strong>это возможно.</li>
    <li id="IMu8"><strong>C) <a href="#HSYA">Log-Level</a>-Filter:</strong> Верхне уровневый фильтр по типу сообщения.</li>
    <li id="B50d"><strong>D) <a href="#pvQU">Search-Filter</a>:</strong> Для поиска сообщений, отображаемых в данный момент в Logcat (При необходимости выберите Regex, если вы хотите использовать шаблон поиска <a href="https://ru.wikipedia.org/wiki/%D0%A0%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D0%B5_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F" target="_blank">регулярного выражения</a>)</li>
    <li id="Jk5v"><strong>E) <a href="#WvLs">Global-Filter</a>:</strong> Верхне уровневый фильтр, применяется ко всей вашей истории Logcat, а не только к тем сообщениям, которые в данный момент отображаются в logcat.</li>
  </ul>
  <p id="v7Hc"></p>
  <hr />
  <h2 id="WvLs">Global-Filter (E)</h2>
  <p id="UspL"><a href="https://developer.android.com/studio/debug/am-logcat#filtering" target="_blank">Оригинал</a></p>
  <p id="oO7Y">В меню фильтра выберите параметр фильтра:</p>
  <figure id="qAzK" class="m_original" data-caption-align="center">
    <img src="https://img2.teletype.in/files/11/70/117078d6-dc35-47a7-bb43-4ff8aa3e56dc.png" width="324" />
    <figcaption>Рисунок 8. Меню выбора настроек для глобального фильтра.</figcaption>
  </figure>
  <ul id="GLCf">
    <li id="N8VL"><strong>Show only selected application</strong>: отображать только сообщения, созданные кодом приложения (по умолчанию). Logcat фильтрует сообщения журнала, используя PID активного приложения.</li>
    <li id="iCVO"><strong>No filters:</strong> не применять фильтры. Logcat отображает все сообщения журнала с устройства, независимо от того, какой процесс вы выбрали.</li>
    <li id="QXAO"><strong>Edit Filter Configuration: </strong>Создайте или измените пользовательский фильтр. Например, вы можете создать фильтр для одновременного просмотра сообщений журнала из двух приложений.</li>
  </ul>
  <h3 id="kPDu">Добавление новых фильтров</h3>
  <p id="SNGd">Чтобы создать новый фильтр, нажмите <strong>Edit Filter Configuration</strong> в списке (Рис. 8).</p>
  <figure id="cUxK" class="m_original" data-caption-align="center">
    <img src="https://img2.teletype.in/files/9b/9e/9b9eee35-b55d-4808-a19a-6a7904532a38.png" width="570" />
    <figcaption>Рисунок 9. Диалоговое окно создания фильтра.</figcaption>
  </figure>
  <p id="r97r">Укажите параметры фильтра в диалоговом окне Create New Logcat Filter:</p>
  <ul id="iHUz">
    <li id="KOc2"><strong>Filter Name:</strong> введите название фильтра или выберите его на левой панели, чтобы изменить существующий фильтр. Имя может содержать только символы нижнего регистра, символы подчеркивания и цифры.</li>
    <li id="Dzsc"><strong>Log Tag:</strong> При необходимости укажите тег. Тег определяется разработчиком, например это может быть название класса.</li>
    <li id="SLis"><strong>Log Message:</strong> При необходимости укажите текст сообщения.</li>
    <li id="6C6k"><strong>Package Name:</strong> При необходимости укажите <a href="https://support.google.com/admob/answer/9972781?hl=ru" target="_blank">название пакета приложения</a>.</li>
    <li id="bLp5"><strong>PID: </strong>При необходимости укажите идентификатор процесса.</li>
    <li id="eI8r"><strong>Log Level:</strong> При необходимости выберите <a href="#HSYA">log-level</a>.</li>
    <li id="1cxP"><strong>Regex:</strong> выберите этот параметр, чтобы использовать синтаксис <a href="https://ru.wikipedia.org/wiki/%D0%A0%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D0%B5_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F" target="_blank">регулярного выражения</a> для этого параметра.</li>
  </ul>
  <blockquote id="xnLA">Примечание: Имейте ввиду, что параметры фильтрации (tag, message, PID и т.д.) определены в <a href="#1rHO">формате вывода логов</a> как сообщалось ранее.</blockquote>
  <h3 id="tMi9">Исключить сообщения ОС из Logcat</h3>
  <p id="8c6U">В журнале отображается очень много мусора, который в 90% случаев не важен, решение: создайте новый фильтр с регулярным выражением</p>
  <pre id="dWtQ">^(?!.*(BtGatt|dalvik|Environment|DataRouter|FA|art|Wifi|ServiceManager|Atfwd|tnet|MDnsDS|Download|Bluetooth|slim|QSEECOMAPI|WVCdm|QC-time|sensors|nanohub|Drm|Babel|Dropbox|gsamlab|Cryptd|Vold|QC_|Conscrypt|Dns|sound|NetWork|OpenGL|TLog|GMPM|Microphone|Process|Dynamite|cr_|VideoCapabilities|libEGL|NetdEventListenerService|Sensors|Netd|audit|Zygote|Watchdog|ity|memtrack|fb4a|LoadedApk|ImsAdaptorImpl|EPDG|CursorWindow|tworkdiagnosti|PackageManager))</pre>
  <figure id="0npu" class="m_original" data-caption-align="center">
    <img src="https://img3.teletype.in/files/26/36/26364a44-abfc-42f6-b3f8-d55f61aee957.png" width="570" />
    <figcaption>Рисунок 10. Создание нового фильтра для Logcat.</figcaption>
  </figure>
  <p id="P0ee">А затем выберете его из списка фильтров:</p>
  <figure id="Km2j" class="m_original" data-caption-align="center">
    <img src="https://img1.teletype.in/files/ce/b6/ceb69217-2ff6-4b0d-93f6-18d5853addec.png" width="237" />
    <figcaption>Рисунок 11. Список доступных фильтров.</figcaption>
  </figure>
  <p id="2vO2">Вы также можете добавить новое ключевое слово\тег, который хотите игнорировать, с помощью «|» как разделитель.</p>
  <p id="LONE">Автор: <a href="https://medium.com/zinuzoid/if-you-developing-android-application-1bdff0a96205" target="_blank">https://medium.com/zinuzoid/if-you-developing-android-application-1bdff0a96205</a></p>
  <p id="RuGX"></p>
  <h3 id="HSYA">Log level (<a href="https://developer.android.com/studio/debug/am-logcat#level" target="_blank">описание</a>)</h3>
  <p id="6Gg9">В меню Уровень журнала выберите одно из следующих значений: </p>
  <ul id="EdaU">
    <li id="PW8j"> <strong>Verbose</strong>: показать все сообщения журнала (по умолчанию). </li>
    <li id="zyKC"> <strong>Debug</strong>: Показать сообщения журнала отладки, которые полезны только во время разработки, а также уровни сообщений ниже в этом списке. </li>
    <li id="TF2Y"> <strong>Info</strong>: Показать ожидаемые сообщения журнала для регулярного использования, а также уровни сообщений ниже в этом списке. </li>
    <li id="YGai"> <strong>Warn</strong>: показывать возможные проблемы, которые еще не являются ошибками, а также уровни сообщений ниже в этом списке. </li>
    <li id="Wv2Q"> <strong>Error</strong>: Показать проблемы, вызвавшие ошибки, а также уровень сообщения ниже в этом списке. </li>
    <li id="wiER"><strong>Assert</strong>: Показать проблемы, которые, по мнению разработчика, никогда не должны возникать.</li>
  </ul>
  <hr />
  <h2 id="pvQU">Search Filter (D)</h2>
  <p id="mqEa">Данный тип фильтрации используется как уточнение для Global-Filter. Поскольку его удобно менять &quot;на ходу&quot;. Его <strong>отличие от Global-Filter</strong> заключается в том, что <strong>поисковый запрос распространяется на сообщение целиком</strong>, а не на определенный параметр(tag, level, PID, message) как это указывается при создании фильтра.</p>
  <p id="rCKa">В качестве поискового запроса можно использовать шаблон <a href="https://ru.wikipedia.org/wiki/%D0%A0%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D0%B5_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F" target="_blank">регулярного выражения.</a></p>
  <figure id="bPLj" class="m_original" data-caption-align="center">
    <img src="https://img2.teletype.in/files/93/47/934717e8-fdd3-49e7-b17a-b04ab4e458d9.png" width="494" />
    <figcaption>Фильтр поисковой строки.</figcaption>
  </figure>
  <figure id="8gTq" class="m_column" data-caption-align="center">
    <img src="https://img1.teletype.in/files/c0/55/c055e640-11a0-4a6b-974d-7f2ad67eea87.png" width="1189" />
    <figcaption>Результаты фильтрации: Вывод всех строк, где встречается слово &quot;connection&quot;.</figcaption>
  </figure>
  <p id="Zjxa">Примеры фильтрации поиска: в качестве запроса укажу пакет приложения <strong>id.apps.tachyo</strong></p>
  <figure id="qLaj" class="m_original" data-caption-align="center">
    <img src="https://img4.teletype.in/files/34/f9/34f9d4d5-dfe8-456a-bfb7-8e0f652717c5.png" width="1096" />
    <figcaption>Результаты фильтрации: Вывод всех строк, где встречается текст &quot;id.apps.tachyo:&quot;</figcaption>
  </figure>
  <figure id="fqNp" class="m_original" data-caption-align="center">
    <img src="https://img3.teletype.in/files/21/58/2158da94-52c5-4ff4-aa13-61781b64e983.png" width="1098" />
    <figcaption>Результаты фильтрации: Вывод всех строк, где встречается текст &quot;id.apps.tachyo:&quot; c Log-Level = Error</figcaption>
  </figure>
  <figure id="K42P" class="m_original" data-caption-align="center">
    <img src="https://img3.teletype.in/files/69/80/6980a594-f516-45da-88da-32397c036925.png" width="1096" />
    <figcaption>Результаты фильтрации: Вывод всех строк, где встречается текст &quot;id.apps.tachyo:&quot; c Log-Level = Warn</figcaption>
  </figure>
  <p id="ZG6m">Тот же самый результат, если добавить в поисковый результат Tag &quot;W&quot;, который отображает log-level.</p>
  <figure id="seYZ" class="m_original" data-caption-align="center">
    <img src="https://img2.teletype.in/files/1b/80/1b80f83d-394e-4a9d-8d2d-928775783463.png" width="981" />
    <figcaption>Результаты фильтрации: Вывод всех строк, где встречается текст &quot;W/id.apps.tachyo:&quot;</figcaption>
  </figure>
  <hr />
  <h3 id="T5k5">Поиск в логах</h3>
  <p id="IoBV">Также, если нажать в окно вывода, а затем <strong>Ctrl+F</strong>, то откроется поисковая строка, которая позволяет не фильтруя Logcat искать в нем нужный текст. Это бывает удобно, например если нужно подсветить ключевые фразы и видеть остальные логи.</p>
  <figure id="zX02" class="m_original" data-caption-align="center">
    <img src="https://img2.teletype.in/files/1f/b6/1fb6628c-4c4a-4e91-98a3-1b0ab6b6af23.png" width="991" />
    <figcaption>Поиск слова &quot;hidden&quot; в журнале.</figcaption>
  </figure>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@hikkidev/software-win</guid><link>https://teletype.in/@hikkidev/software-win?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=hikkidev</link><comments>https://teletype.in/@hikkidev/software-win?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=hikkidev#comments</comments><dc:creator>hikkidev</dc:creator><title>Windows 10 Software Pack 2022</title><pubDate>Sat, 19 Sep 2020 11:17:42 GMT</pubDate><description><![CDATA[Note: [⮋] - direct download, platform x64; [⚠] - manual download; ✅ - open source]]></description><content:encoded><![CDATA[
  <blockquote id="07BS">Note: [⮋] - direct download, platform x64; [⚠] - manual download; ✅ - open source</blockquote>
  <p id="HJKQ"></p>
  <h2 id="Haaj">UX</h2>
  <ul id="1Hhk">
    <li id="dgQW"><a href="https://download.mozilla.org/?product=firefox-devedition-stub&os=win" target="_blank">[⮋]</a> <a href="https://www.mozilla.org/ru/firefox/developer/" target="_blank">Firefox Browser Developer Edition</a> ✅</li>
    <li id="ECyf"><a href="https://www.google.com/chrome/" target="_blank">[⚠]</a> <a href="https://www.google.com/chrome/" target="_blank">Chrome</a></li>
    <li id="a5rb"><a href="https://www.torproject.org/download/" target="_blank">[⚠]</a> <a href="https://www.torproject.org/" target="_blank">Tor Browser</a> ✅</li>
  </ul>
  <hr />
  <ul id="tIXn">
    <li id="4S7o"><a href="https://discordapp.com/api/download?platform=win" target="_blank">[⮋]</a> <a href="https://discordapp.com" target="_blank">Discord</a> ✅</li>
    <li id="8kIs"><a href="https://telegram.org/dl/desktop/win" target="_blank">[⮋]</a> <a href="https://telegram.org" target="_blank">Telegram</a> ✅</li>
  </ul>
  <hr />
  <ul id="qXep">
    <li id="BtOr"><a href="https://www.audacityteam.org/download/windows/" target="_blank">[⚠]</a> <a href="https://www.audacityteam.org/" target="_blank">Audacity</a> ✅ - Audio editor \ recorder</li>
    <li id="V9JN"><a href="https://vault.bitwarden.com/download/?app=desktop&platform=windows" target="_blank">[⮋]</a> <a href="https://bitwarden.com/" target="_blank">Bitwarden ✅ </a>- Password Manager</li>
    <li id="CD1r"><a href="https://sourceforge.net/projects/qbittorrent/files/latest/download" target="_blank">[⮋]</a> <a href="https://www.qbittorrent.org" target="_blank">qBitTorrent</a> ✅</li>
    <li id="YvFK"><a href="https://www.videolan.org/vlc/index.ru.html" target="_blank">[⚠]</a> <a href="https://www.videolan.org/vlc/" target="_blank">VLC</a> ✅</li>
    <li id="ZK2v"><a href="https://www.spotify.com/download/windows/" target="_blank">[⮋]</a> <a href="https://www.spotify.com" target="_blank">Spotify</a></li>
    <li id="sAKX"><a href="https://steamcdn-a.akamaihd.net/client/installer/SteamSetup.exe" target="_blank">[⮋]</a> <a href="https://store.steampowered.com/" target="_blank">Steam</a></li>
    <li id="kjvs"><a href="https://www.screentogif.com/downloads" target="_blank">[⚠]</a> <a href="https://www.screentogif.com/" target="_blank">ScreenToGif</a> ✅ - Tool to record\edit</li>
    <li id="QqaZ"><a href="https://www.voidtools.com/downloads/" target="_blank">[⚠]</a> <a href="https://www.voidtools.com/" target="_blank">Everything </a>- Instantly search by name</li>
    <li id="UaDa"><a href="https://www.7-zip.org/download.html" target="_blank">[⚠]</a> <a href="https://www.7-zip.org/" target="_blank">7-Zip</a> ✅</li>
    <li id="dR3Y"><a href="https://download.wireguard.com/windows-client/wireguard-installer.exe" target="_blank">[⮋]</a> <a href="https://www.wireguard.com" target="_blank">Wireguard</a> ✅ - VPN</li>
  </ul>
  <h2 id="m5UB">Development</h2>
  <ul id="hLVI">
    <li id="dBwx"><a href="https://dl.pstmn.io/download/latest/win64" target="_blank">[⮋]</a> <a href="https://www.postman.com/" target="_blank">Postman </a>- Quickly and easily send requests</li>
    <li id="Ig85"><a href="https://gpg4win.org/thanks-for-download.html" target="_blank">[⮋]</a> <a href="https://gpg4win.org/" target="_blank">GPG4win</a> ✅ - GNU Privacy Guard</li>
    <li id="iFG3"><a href="https://git-scm.com/download/win" target="_blank">[⚠]</a> <a href="https://git-scm.com" target="_blank">Git</a> ✅</li>
    <li id="wI8s"><a href="https://code.visualstudio.com/docs/?dv=win64user" target="_blank">[⮋]</a> <a href="https://code.visualstudio.com" target="_blank">Visual Studio Code</a> ✅</li>
  </ul>
  <hr />
  <ul id="Lwnn">
    <li id="K1Za"><a href="https://www.jetbrains.com/toolbox-app/download/download-thanks.html?platform=windows" target="_blank">[⮋]</a> <a href="https://www.jetbrains.com/toolbox-app/" target="_blank">JetBrains Toolbox App</a> - Manage IDEs</li>
    <li id="phoS"><a href="https://www.java.com/en/download/manual.jsp" target="_blank">[⚠]</a> <a href="https://www.java.com/en/download/faq/whatis_java.xml" target="_blank">JRE</a></li>
    <li id="SPeV"><a href="https://www.oracle.com/java/technologies/javase-downloads.html#javasejdk" target="_blank">[⚠]</a> <a href="https://www.java.com/en/download/faq/develop.xml" target="_blank">JDK</a></li>
    <li id="fv6I"><a href="https://github.com/Genymobile/scrcpy/releases/" target="_blank">[⚠]</a> <a href="https://github.com/Genymobile/scrcpy/" target="_blank">scrcpy</a> ✅ - Display\control of Android devices</li>
  </ul>
  <hr />
  <ul id="xehm">
    <li id="7g4u"><a href="https://www.anaconda.com/products/individual#Downloads" target="_blank">[⚠]</a> <a href="https://www.anaconda.com/" target="_blank">Anaconda Project</a></li>
    <li id="ot0x"><a href="https://www.python.org/downloads/" target="_blank">[⚠]</a> <a href="https://www.python.org/" target="_blank">Python</a> ✅</li>
    <li id="7eHD"><a href="https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html" target="_blank">[⚠]</a> <a href="https://www.putty.org/" target="_blank">PuTTY</a> ✅</li>
  </ul>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@hikkidev/z5PPVTo6</guid><link>https://teletype.in/@hikkidev/z5PPVTo6?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=hikkidev</link><comments>https://teletype.in/@hikkidev/z5PPVTo6?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=hikkidev#comments</comments><dc:creator>hikkidev</dc:creator><title>Android studio 4.x configuration</title><pubDate>Sun, 05 Jul 2020 13:41:08 GMT</pubDate><media:content medium="image" url="https://teletype.in/files/1e/35/1e35b84b-5e41-477a-b25c-db8225dfe05f.png"></media:content><category>Android Studio</category><description><![CDATA[<img src="https://teletype.in/files/d4/77/d47729c9-b31d-44d6-bebc-6d8e122562e8.png"></img>1) Disable line numbers]]></description><content:encoded><![CDATA[
  <h3 id="U4wC">Settings</h3>
  <p id="Yv3G">1) Disable line numbers</p>
  <figure id="wHSR" class="m_original" data-caption-align="center">
    <img src="https://teletype.in/files/d4/77/d47729c9-b31d-44d6-bebc-6d8e122562e8.png" width="674" />
    <figcaption>Switch to OFF</figcaption>
  </figure>
  <p id="zBNy">2) Disable tabs</p>
  <figure id="IdMh" class="m_original" data-caption-align="center">
    <img src="https://teletype.in/files/fb/e6/fbe698ff-c310-40ab-a6df-0f18a3fb9f7e.png" width="674" />
    <figcaption>Switch <strong>None </strong>placement to ON</figcaption>
  </figure>
  <p id="XAs6">3) Enable auto-scroll</p>
  <figure id="imlr" class="m_original" data-caption-align="center">
    <img src="https://teletype.in/files/08/9e/089ec71c-1df2-404e-a812-32433e0d8f56.png" width="674" />
    <figcaption>Switch to ON</figcaption>
  </figure>
  <p id="LWh4">4) Enable Semantic Highlighting</p>
  <figure id="1dC1" class="m_original" data-caption-align="center">
    <img src="https://teletype.in/files/1d/11/1d118d9b-dd19-4b1a-98b5-78ecadb07d36.png" width="984" />
    <figcaption>Toggle checkbox</figcaption>
  </figure>
  <h3 id="FFpU">Plugins</h3>
  <ul id="lwzH">
    <li id="cyKq"><a href="https://plugins.jetbrains.com/plugin/8580-cpu-usage-indicator" target="_blank">.</a><a href="https://plugins.jetbrains.com/plugin/7495--ignore" target="_blank">ignore</a></li>
    <li id="CVRk"><a href="https://plugins.jetbrains.com/plugin/2162-string-manipulation" target="_blank">String manipulation</a></li>
    <li id="lwD5"><a href="https://plugins.jetbrains.com/plugin/10080-rainbow-brackets" target="_blank">Rainbow Brackets</a></li>
    <li id="5zjc"><a href="https://plugins.jetbrains.com/plugin/8579-translation" target="_blank">Translation</a></li>
  </ul>
  <h3 id="Td39">Keymap</h3>
  <p id="gnc1">Double Shift, Ctrl+Space, Alt+Enter - our all</p>
  <p id="GfvG">Ctrl+E - Recent files (Ctrl+Tab - quick version)</p>
  <figure id="istF" class="m_original" data-caption-align="center">
    <img src="https://teletype.in/files/17/7e/177e9fbf-baab-4098-a1e7-fdcba5210f1f.png" width="500" />
    <figcaption>Example usage</figcaption>
  </figure>
  <p id="ehVo">Ctrl+P - Show params | Ctrl + Shift + P - Show data type</p>
  <figure id="VsXi" class="m_original" data-caption-align="center">
    <img src="https://teletype.in/files/a0/cb/a0cb4f00-8f72-4db7-b403-36338b857a66.png" width="626" />
    <figcaption>Example usage</figcaption>
  </figure>
  <p id="qq9t">Ctrl+Q - Quick documentation</p>
  <figure id="8YBF" class="m_original" data-caption-align="center">
    <img src="https://teletype.in/files/56/9c/569cd70e-6878-4fd7-bda0-f323f4a27478.png" width="338" />
    <figcaption>Example usage</figcaption>
  </figure>
  <p id="NlAs">Ctrl+Shift+I - Quick definition</p>
  <figure id="LbYj" class="m_original" data-caption-align="center">
    <img src="https://teletype.in/files/e2/78/e278c729-6e6d-4e7f-86f9-bc4fc4adc05e.png" width="618" />
    <figcaption>(Rebind keymap to Shift+Q)</figcaption>
  </figure>
  <p id="LhQg">Quick navigation</p>
  <figure id="IB4z" class="m_original" data-caption-align="center">
    <img src="https://teletype.in/files/31/9f/319f0d90-7d08-4a24-8fa8-d25ee34a81c1.png" width="746" />
    <figcaption>Keymap </figcaption>
  </figure>
  <p id="V8kS">Ctrl+F12 - Show structure</p>
  <figure id="DDLh" class="m_original" data-caption-align="center">
    <img src="https://teletype.in/files/98/e2/98e23f7d-f516-48f5-a925-203460cc544f.png" width="572" />
    <figcaption>Example usage</figcaption>
  </figure>
  <p id="zwcc">Ctrl+Alt+F7 - Show usages</p>
  <figure id="yEwc" class="m_original" data-caption-align="center">
    <img src="https://teletype.in/files/0f/e9/0fe9a248-e79e-4795-b57c-2110615c1680.png" width="669" />
    <figcaption>Example usage</figcaption>
  </figure>
  <p id="K2cb">Ctrl+Alt+Shift+T - Show refactor menu</p>
  <figure id="vzLQ" class="m_original" data-caption-align="center">
    <img src="https://teletype.in/files/01/d4/01d415fd-baf9-4428-b048-545536256452.png" width="311" />
    <figcaption> (Rebind keymap to Ctrl+T)</figcaption>
  </figure>
  <p id="CIjQ">Alt+ins - Generate menu</p>
  <figure id="pcLg" class="m_original" data-caption-align="center">
    <img src="https://teletype.in/files/5c/43/5c4399fc-f0fc-4e59-86a2-aec8c584c1e9.png" width="201" />
    <figcaption>Example usage</figcaption>
  </figure>
  <p id="vAit">Al+J -&gt; J -&gt; J -&gt; etc...  - Sequential selection with cursor positioning</p>
  <figure id="k8br" class="m_original" data-caption-align="center">
    <img src="https://teletype.in/files/cf/20/cf20c4c7-803c-4565-8afe-c88aab1d5fc2.png" width="805" />
    <figcaption>Example usage</figcaption>
  </figure>

]]></content:encoded></item></channel></rss>