Debian 9: jak nastavit IPv6

Pokud váš poskytovatel připojení internetu nabízí IPv6, zde je ukázka nastavení. Tato konfigurace se provede i po restartu serveru.

vim /etc/network/interfaces

    iface eth0 inet6 static
        address 2001:db8::c0ca:1eaf
        netmask 64
        gateway 2001:db8::1ead:ed:beef
        dns-nameservers 2001:4860:4860::8844 2001:4860:4860::8888

Aby se změna projevila, je nutné restartovat interface

/etc/init.d/networking restart

Pokud jsme přihlášeni přes Putty, bude spojení přerušeno a je nutné se znovu připojit.

Správnou konfiguraci zjistíme příkazem:

ip address show

Správné nastavení ověříme pingem:

ping6 ipv6.google.com

 

Debian 9 (stretch) – instalace php 7.1

V poslední verzi Debianu Stretch je defaultně php 7.0, pokud potřebujete novější 7.1, je možné jej bez kompilace zdrojových kódů nainstalovat přes balíčky:

apt-get install apt-transport-https lsb-release ca-certificates
wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list
apt-get update
apt-get install php7.1

Stejným způsobem nainstalujeme PHP7.2:

apt install php7.2 php7.2-cli php7.2-common php7.2-json php7.2-opcache php7.2-mysql php7.2-zip php7.2-fpm php7.2-mbstring 

Jak jsem nasadil Let’s Encrypt

Dnes si prakticky ukážeme jak zprovoznit Let’s Encrypt na vlastním serveru s Debianem a Apache. Let’s Encrypt je továrna na certifikáty zdarma.

Instalace Let’s Encrypt

git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt

Zastavíme Apache

/etc/init.d/apache2 stop
#nebo

systemctl stop apache2.service

Přesvědčíme se že na portu 80 nic neposlouchá:

netstat -na | grep ':80.*LISTEN'

Vygenerování certifikátu

cd /opt/letsencrypt
./letsencrypt-auto certonly --standalone
  1. zadáme email
  2. souhlasíme s podmínkami
  3. zadáme doménová jména pro která chceme certifikát (example.com, www.example.com, app.example.com)
IMPORTANT NOTES:
 - If you lose your account credentials, you can recover through
   e-mails sent to vencax@gmail.com.
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/www.meducina.cz/fullchain.pem. Your cert will
   expire on 2016-04-14. To obtain a new version of the certificate in
   the future, simply run Let's Encrypt again.
 - Your account credentials have been saved in your Let's Encrypt
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Let's
   Encrypt so making regular backups of this folder is ideal.
 - If you like Let's Encrypt, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Opět spustíme Apache

/etc/init.d/apache2 start

Certifikáty byly vytvořeny do složky:

ls -al /etc/letsencrypt/live/www.your_domain_name.com

Do Apache pak stačí pouze přidat (základní nejjdnodužší nastavení):

vim meducina.cz-ssl.conf:

<VirtualHost *:443>
    ServerAdmin webhosting@ukaztese.cz
    ServerName  meducina.cz
    ServerAlias *.meducina.cz
    DocumentRoot /var/www/meducina.cz/web/www/www

    SSLEngine on
    SSLCertificateFile "/etc/letsencrypt/live/www.meducina.cz/cert.pem"
    SSLCertificateKeyFile "/etc/letsencrypt/live/www.meducina.cz/privkey.pem"
</VirtualHost>

Přidáme tuto konfiguraci:

cd /etc/apache2/sites-enabled
a2ensite meducina.cz-ssl

Restartovat Apache a je to 🙂

Ovšem doporučuji Apache nastavit pořádně. K tomu pomůže Generator Mozilla Security (musel jsem povolit a2enmod headers). Takto mi to funguje

#Listen 443
<VirtualHost *:443>
    ServerAdmin webhosting@ukaztese.cz
    ServerName  meducina.cz
    ServerAlias *.meducina.cz
    DocumentRoot /var/www/meducina.cz/web/www/www

    SSLEngine on
    SSLCertificateFile      "/etc/letsencrypt/live/www.meducina.cz/cert.pem"
    SSLCertificateKeyFile   "/etc/letsencrypt/live/www.meducina.cz/privkey.pem"
    SSLCACertificateFile    "/etc/letsencrypt/live/www.meducina.cz/fullchain.pem"

    # HSTS (mod_headers is required) (15768000 seconds = 6 months)
    Header always set Strict-Transport-Security "max-age=15768000"
</VirtualHost>



# intermediate configuration, tweak to your needs
SSLProtocol             all -SSLv3
SSLCipherSuite          ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
SSLHonorCipherOrder     on
    SSLCompression          off
#    SSLSessionTickets       off   #WTF - why don't work?

    # OCSP Stapling, only in httpd 2.3.3 and later
    SSLUseStapling          on
    SSLStaplingResponderTimeout 5
    SSLStaplingReturnResponderErrors off
SSLStaplingCache        shmcb:/var/run/ocsp(128000)

Přesměrování na https

Veškerý traffic přesměrujeme na http

<VirtualHost *:80>

#...
    #redirect to https
    RewriteCond %{HTTPS} off
    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
#...

</VirtualHost>

 

Obnova certifikátů

Doporučuji si udělat symlink aby příkaz letsencrypt-auto fungoval kdekoliv z příkazové řádky:

ln -s /opt/letsencrypt/letsencrypt-auto /usr/local/bin/letsencrypt-auto

Certifikáty jsou vystavené pouze s platností 90 dnů! Zároveň je doporučováno je každých 60 dnů obnovit. Aktualizace certifikátů zatím stále není k dispozici, ale certifikát obnovíme opětovným spuštěním příkazů uvedených výše.

 

Pravidelná aktualizace certifikátů

Abychom nemuseli myslet na pravidelnou aktualizaci certifikátů, přidáme záznam do cornu, který nám je bude automaticky aktualizovat:

crontab -e

Obnovu certifikátů budeme spouštět každý první den v sudém měsíci ve 4:00 ráno:

0 4 1 */2 * cd /opt/letsencrypt && ./letsencrypt-auto certonly --apache --renew-by-default --apache -d www.meducina.cz >> /var/log/letsencrypt/meducina.cz-renew.log 2>&1
0 4 1 */2 * cd /opt/letsencrypt && ./letsencrypt-auto certonly --apache --renew-by-default --apache -d www.vhazovani.cz >> /var/log/letsencrypt/meducina.cz-renew.log 2>&1
0 4 1 */2 * letsencrypt-auto certonly --apache --renew-by-default --apache -d www.protivinsko.cz >> /var/log/letsencrypt/protivinsko.cz-renew.log 2>&1

To je vše. Není nutné restartovat Apache

Ovšem lepší je dát do cronu pouze 1 script, který bude automaticky obnovovat certifikáty:

0 4 1 */2 * /root/letsencrypt-renew

vim /root/letsencrypt-renew

#!/bin/bash

/opt/letsencrypt/letsencrypt-auto certonly --apache --renew-by-default --apache -d www.meducina.cz >> /var/log/letsencrypt/meducina.cz-renew.log 2>&1

/opt/letsencrypt/letsencrypt-auto certonly --apache --renew-by-default --apache -d www.vhazovani.cz >> /var/log/letsencrypt/vhazovani.cz-renew.log 2>&1

/opt/letsencrypt/letsencrypt-auto certonly --apache --renew-by-default --apache -d www.protivinsko.cz >> /var/log/letsencrypt/protivinsko.cz-renew.log 2>&1

/opt/letsencrypt/letsencrypt-auto certonly --apache --renew-by-default --apache -d www.mamejidlo.cz >> /var/log/letsencrypt/mamejidlo.cz-renew.log 2>&1

Nastavit oprávnění pro spouštění:

chmod oug+x letsencrypt-renew

 

Bower + Grunt + Colorbox

Dnes vám naznačím jak do projektů přidávám knihovny třetích stran  a jak spojuji css a js soubory, které následně minifukuji. Ukážeme se to na pluginu Colorbox který používám pro zobrazení detailu fotek v pop-up okně.

Nainstalujeme Colorbox přes bower:

bower install jquery-colorbox --save-dev

Grunt task pro Colorbox

Pro zkopírování souborů používám balíček grunt-contrib-copy a pro minifikaci css do jednoho souboru grunt-contrib-cssmin:

npm install grunt-contrib-copy --save-dev
npm install grunt-contrib-cssmin --save-dev
npm install grunt-contrib-concat --save-dev

Nejdůležitější část souboru Gruntfile.js:

        copy: {
            colorbox: {
                expand: true,
                flatten: true,
                src: './bower_components/jquery-colorbox/example3/images/*',
                dest: 'www/css/images'
            }
        },
        cssmin: {
            target: {
                files: {
                    'www/css/main.min.css': [
                        'www/css/main.css',
                        'bower_components/jquery-colorbox/example3/colorbox.css',
                    ]
                }
            }
        },
        concat: {
            js: {
                src: ['bower_components/jquery/dist/jquery.min.js',
                    'bower_components/bootstrap/dist/js/bootstrap.min.js',
                    'bower_components/jquery-colorbox/jquery.colorbox-min.js',
                    'www/js/main.js'
                ],
                dest: 'www/js/compiled.min.js'
            }
        },

Tím se nakopírují ohrají obrázky obrázky z ./bower_components/jquery-colorbox/example3/images/ do www/css/image, soubor bower_components/jquery-colorbox/example3/colorbox.css se zmnifikuje a připojí k souboru www/css/main.css a soubor bower_components/jquery-colorbox/jquery.colorbox-min.js připojíme k zminifikovanému souboru www/js/compiled.min.js

Do souboru s JS přidáme inicializaci Colorboxu (v mém případě main.js):

$('.colorbox').colorbox({rel:'gal'});

Parametr {rel:’gal‘} označuje že se jedná o galerii. Pokud bude více odkazů s class=“colorbox“ půjde mezi fotkami přepínat a nebude se muset pop-up okno zavírat.

Odkazu s obrázkem přidáme classu colorbox:

<a href="{$pubPhoto->photo}" class="colorbox">
   <img src="{$pubPhoto->photoSmall}" alt="{$pubPhoto->title}">
</a>

A je to 🙂

Android: jak na responzivní zobrazení komponent na celou výšku displeje

Pokud budete chtít zobrazit komponenty rovnoměrně na celou výšku displeje, můžete využít ConstraintLayout. Jedná se o nový layout, který je dostupný v Android Studiu. Nezapomeňte ošetřit malé displeje, aby se komponenty na displej vešly.

constraint-layout

Kód pro inspiraci:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="cz.vencax.constraintlayout.MainActivity">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView2"
        app:layout_constraintBottom_toBottomOf="@+id/textView3"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@+id/textView1"
        app:layout_constraintVertical_bias="0.5" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView3"
        app:layout_constraintBottom_toBottomOf="@+id/textView4"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@+id/textView2"
        app:layout_constraintVertical_bias="0.5" />

    <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView4"
        app:layout_constraintBottom_toBottomOf="@+id/textView5"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@+id/textView3"
        app:layout_constraintVertical_bias="0.5" />

    <TextView
        android:id="@+id/textView5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView5"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

</android.support.constraint.ConstraintLayout>

 

WordPress jak na shortcode

Namotivován ze včerejší WPkonference sedám ke stroji a jdu vylepšit můj plugin pro fotogalerii rajče. Plugin nyní zobrazuje naposledy vytvořené galerie s úvodní fotkou. Rozhodl jsem se použít shortcode pro zobrazení celé galerie.

Shortcode je příkaz který na svém místě zavolá funkci a zobrazí html kód. Například následující shortcode by zobrazil fotogalerii [forogalerie]. Shortcode můžeme používat ve stránce i příspěvku.

Jak použít shortcode

Pro zpracování takto definovaného shorcode:

[rajce-galerie url="http://sdh-zabori.rajce.idnes.cz/Stedry_den_v_hospode_20.12.2015/"]

Použijeme nejjednodušší metodu:

// [rajce-galerie id="123" size="medium"]
function rajceGalleryFunc( $atts ) {
    $attsArray = shortcode_atts( array(
        'url' => NULL
    ), $atts );

    $return = "<div class=\"rajce-gallery\">";

    if($attsArray['url'] != "") {
       $return.= "RAJCE GALERIE URL: {$a['url']}";
    }

    $return.= "</div>";

    return $return;
}
add_shortcode( 'rajce-galerie', 'rajceGalleryFunc' );

Příkazem add_shorcode definujeme nový shortcode. První parametr označuje název shortoce ( [rajce-galerie … ) a druhý parametr je název funkce, která se zavolá pro tento shortcode.

Ve funkci si můžeme sáhnout na parametry uvedené u shortcode, kde definujeme defaultní hodnotu, pokud parametr není uveden. V mím případě NULL:

    $attsArray = shortcode_atts( array(
        'url' => NULL
    ), $atts );

Pak už si s parametry můžeme dělat co chceme 🙂

Leptání plošného spoje v domácích podmínkách

Již pěknou řádku let mi doma leží chemikálie pro leptání plošných spojů. Největší překážka pro mne byl osvit desky UV zářením. Při použití UV trubic pro mne byl výsledek vždy nejistý. Proto jsem investoval do trochu sofistikovanějšího řešení a koupil osvitovou jednotku na plošné spoje, se kterou je výroba plošných spojů v domácích podmínkách jednoduchá.

Desky pro plošný spoj máchám v plastových krabičkách na potraviny. Tyto krabičky jsou levné a mají výhodu, že se nechají uzavřít.

Osvit plošného spoje

Vytištěný plošný spoj (tisknu klasicky, žádné otáčení) na obyčejném papíře nastříkám sprejem Transparent 21. Správně otočím a plošný spoj a ozařuji 9minut 30 vterin (defaultní nastavení UV jednotky). Pokud leptám větší plochu spoje, klidně postříkám papír přímo na desce (osvit trvá docela dlouho a Transparent 21 se rychle odpařuje). Pro větší plošné spoje je ovšem nutné vytisknout plošný spoj na fólii – nemusí se stříkat sprejem Transparent 21 a výsledek je lepší.

Vývojka

Vývojku používám kupovanou již naředěnou: Vývojka obsahuje hydroxid sodný 1,5%

Vyvolávám v roztoku při pokojové teplotě. Roztoku mám v nádobě cca 0,5cm. Okamžitě po vložení do čerstvého roztoku (mědí nahoru) se začnou zobrazovat cestičky plošného spoje. Za 3 minuty by mělo být hotovo. Ovšem já vyčkávám déle, dokud neuvidím všechny cestičky bez šumu. Čekám cca 6 minut. A kádinkou občas pohybuji aby se k destičce dostala nenasycená vývojka a odplavily nečistoty. V úplně čistém roztoku 3minuty stačí, možná až moc (některé písmo je hůře vidět).  Jakmile se už nic neodpouští, pryč s tím. Udělal jsem pokus a za minutu vyndal, i to je asi moc 🙂 I ve starším roztoku 0,5 minuty stačí.

K manipulaci s destičkou plošného spoje používám fotografické kleště. Nikdy nesahejte to roztoků rukou bez jakéhokoliv nástroje! Destičku vyndám, omyji pod tekoucí studenou vodou a do sucha osuším.

Leptání v chloridu železitém FeCl3

Chlorid železitý FeCl3 není nebezpečný ale zanechává obtížně odstranitelné hnědé skvrny, které se na oblečení po čase změní v díry. Rukama do roztoku nesajte. Ani nedoporučuji železné kleště/nůžky pro manipulaci s destičkou plošného spoje. Po práci ruce důkladně umyjeme a ošetříme krémem.

K destičce plošného spoje udělám z elekrikářské lepenky madla pro snadnější manipulaci. Leptám v leptacím roztoku.

Leptám s použitím fotografické misky do které naliji cca 0,5 cm chloridu železitého. Plošný spoj za madla položím na hladinu (mědí dolů). Nejprve položím 1 hranu a postupně celý spoj aby pod ním nevznikla „bublina“. Suchý plošný spoj plave na hladině. Rozpuštěná měď klesá ke dnu.

Leptání v žádném případě neurychlujte štětcem! Doporučuji občas kontrolovat v jakém stavu se nachází leptání.

Leptám při pokojové teplotě (čím vyšší teplota tím rychlejší leptání). V čerstvém chloridu železitém trvá leptání cca 20 minut. Ke konci leptání je vidět prosvítání motivu. Leptám do té doby než zmizí „červené“ pozadí.

Mytí & finální úprava

Vyleptaný plošný spoj důkladně omyjeme vodou a mýdlem abychom odstranili zbytky leptacího roztoku. Poté desku osušíme. Měděné plošky potřeme štětečkem s lihem (Aceton 700ml) a umyjeme pastou na nádobí Toro. Po těchto procedurách je neprodleně nutné nanést ochranný lak aby nedošlo k oxidaci mědi. Lak nanáším štětečkem. Mnohonásobně jednoduší (ale samozřejmě dražší než ochranný lak nanášený štětečkem) než nanášení laku štětečkem je použít sprej FLUX SK10

Jak publikovat Windows 10 aplikaci do Store

Povedlo se mi publikovat mou první aplikaci ve Windows Store 🙂 Jedná se o můj klasický HelloWorld 🙂 https://www.microsoft.com/cs-cz/store/apps/motor-cb/9nblggh4v9ft

Tady jsou mé poznámky a poznatky k celému procesu.

Nejprve je nutné se přihlásit Microsoftím účtem: https://dev.windows.com/cs-cz

V řídícím panelu klikneme na tlačítko Vytvořit novou aplikaci :  (https://dev.windows.com/cs-cz/registration/AccountInfo). Při prvním spuštění toho kroku je nutné vyplnit údaje o autorovi aplikace a zaplatit jednorázový poplatek 365,-Kč (částka se ještě navýší o daň = cca 77,-Kč). Celkem tedy 442Kč. Platbu je možné provést přes kreditní kartu nebo PayPal.

Vytvořenou UWP (Universal Windows Platform) aplikaci a vyexportujeme ji přímo z Visual Studia. Klikneme na projekt pravým tlačítkem a vybereme Store ->Create App Packages … :

store1

store2

Poté je ještě nutné spustit App Certification Kit – jedná se o testy, které se samy vykonají a otestují základní funkčnost aplikace. Po dokončení těchto kroků máme k dispozici soubor s aplikací:

Documents\Visual Studio 2015\Projects\MotorCB\MotorCB\AppPackages\MotorCB_1.1.6.0_x86_x64_arm_bundle.appxupload

Ten nahrajeme na https://developer.microsoft.com/cs-cz/dashboard/overview a doplníme povinné údaje.

store3

A pak už jen čekat 🙂 Mou první aplikaci schválili za necelé 2 dny. Při tomto procesu se opět na aplikaci spouští testy.

Každý další upgrade aplikace je většinou schválen do 24hodin a do dalších 24 hodin se změny projeví ve Windows Store.

store4

Záseky při publikování aplikací

Šipka zpět

Tohle jsem nepochopil, ale programátor si musí ošetřit funkčnost šipky zpět 🙂 Úprava spočívá v přidání těchto řádků:

 namespace MotorCB
 {
     /// <summary>
     /// Provides application-specific behavior to supplement the default Application class.
     /// </summary>
     sealed partial class App : Application
     {
         /// <summary>
         /// Initializes the singleton application object.  This is the first line of authored code
         /// executed, and as such is the logical equivalent of main() or WinMain().
         /// </summary>
         public App()
         {
             Microsoft.ApplicationInsights.WindowsAppInitializer.InitializeAsync(
                 Microsoft.ApplicationInsights.WindowsCollectors.Metadata |
                 Microsoft.ApplicationInsights.WindowsCollectors.Session);
             this.InitializeComponent();
             this.Suspending += OnSuspending;
         }
 
         /// <summary>
         /// Invoked when the application is launched normally by the end user.  Other entry points
         /// will be used such as when the application is launched to open a specific file.
         /// </summary>
         /// <param name="e">Details about the launch request and process.</param>
         protected override void OnLaunched(LaunchActivatedEventArgs e)
         {
 #if DEBUG
             if (System.Diagnostics.Debugger.IsAttached)
             {
                 this.DebugSettings.EnableFrameRateCounter = false;
             }
 #endif
             Frame rootFrame = Window.Current.Content as Frame;
 
             // Do not repeat app initialization when the Window already has content,
             // just ensure that the window is active
             if (rootFrame == null)
             {
                 // Create a Frame to act as the navigation context and navigate to the first page
                 rootFrame = new Frame();
 
                 rootFrame.NavigationFailed += OnNavigationFailed;
+                rootFrame.Navigated += OnNavigated;
 
                 if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
                 {
                     //TODO: Load state from previously suspended application
                 }
 
                 // Place the frame in the current Window
                 Window.Current.Content = rootFrame;
+
+                // Register a handler for BackRequested events and set the
+                // visibility of the Back button
+                SystemNavigationManager.GetForCurrentView().BackRequested += OnBackRequested;
+
+                SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
+                    rootFrame.CanGoBack ?
+                    AppViewBackButtonVisibility.Visible :
+                    AppViewBackButtonVisibility.Collapsed;
             }
 
             if (e.PrelaunchActivated == false)
             {
                 if (rootFrame.Content == null)
                 {
                     // When the navigation stack isn't restored navigate to the first page,
                     // configuring the new page by passing required information as a navigation
                     // parameter
                     rootFrame.Navigate(typeof(MainPage), e.Arguments);
                 }
                 // Ensure the current window is active
                 Window.Current.Activate();
             }
         }
 
         /// <summary>
         /// Invoked when Navigation to a certain page fails
         /// </summary>
         /// <param name="sender">The Frame which failed navigation</param>
         /// <param name="e">Details about the navigation failure</param>
         void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
         {
             throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
         }
 
+        private void OnNavigated(object sender, NavigationEventArgs e)
+        {
+            // Each time a navigation event occurs, update the Back button's visibility
+            SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
+                ((Frame)sender).CanGoBack ?
+                AppViewBackButtonVisibility.Visible :
+                AppViewBackButtonVisibility.Collapsed;
+        }
+
         /// <summary>
         /// Invoked when application execution is being suspended.  Application state is saved
         /// without knowing whether the application will be terminated or resumed with the contents
         /// of memory still intact.
         /// </summary>
         /// <param name="sender">The source of the suspend request.</param>
         /// <param name="e">Details about the suspend request.</param>
         private void OnSuspending(object sender, SuspendingEventArgs e)
         {
             var deferral = e.SuspendingOperation.GetDeferral();
             //TODO: Save application state and stop any background activity
             deferral.Complete();
         }
+
+
+        private void OnBackRequested(object sender, BackRequestedEventArgs e)
+        {
+            Frame rootFrame = Window.Current.Content as Frame;
+
+            if (rootFrame.CanGoBack)
+            {
+                e.Handled = true;
+                rootFrame.GoBack();
+            }
+        }
     }
 }

Otevření URL ve webovém prohlížeči

String url = "http://blog.venca-x.cz"
await Launcher.LaunchUriAsync(new Uri(url));

 

Android: layout pro různá zařízení

Pokud si přejete zobrazit různý layout pro telefon, 7″ tablet a 10″ tablet určitě vám pomohou tyto poznámky.

Starý a již nepreferovaný způsob:

  • layout výchozí složka – v té máte základní layout
  • layout-large pro 7″ tablet (funguje pro emulátor Nexus 7)
  • layout-xlarge pro 10″ tablet (funguje pro emulátor Galaxy Tab 10.1)

Nový preferovaný způsob je vybrání layoutu podle hodnoty dp

Jednotka dp (density independent piuxel) vyjadřuje fyzickou velikost displeje. a je definován vztahem:

1dp = 160px/dpi
  • 320dp: typické rozlišení pro telefon (240×320 ldpi, 320×480 mdpi, 480×800 hdpi, atd.).
  • 480dp: phablet – něco mezi telefonem a tabletem (480×800 mdpi).
  • 600dp: 7” tablet (600×1024 mdpi).
  • 720dp: 10” tablet (720×1280 mdpi, 800×1280 mdpi, atd)

Šablony pro zůzně velká zařízení

  • sw600dp = nejmenší rozměr (smallestWidth) 600dp – použije se pokud nejmenší rozměr displeje je alespoň 600dp – bez ohledu na to zda je to šířka nebo výška
  • w600dp = šířka displeje 600dp
  • h600dp = výška displeje 600dp

Příklad: Nexus 6 se má velikost displeje 5,96″ a Quad HD v rozlišení 2560 x 1440 (493 ppi). To odpovídá ~ 730 x 410 dp

Vaše zařízení můžete dohledat na adrese http://www.emirweb.com/ScreenDeviceStatistics.php

Typická zařízení

  • Nexus 7: 1280 x 800 px (961 x 600 dp) / tvdpi / Large screen
  • Nexus 10: 2560 x 1600 px (1280 x 800 dp) / xhdpi / XLarge screen

Pokud tedy chci layout pro Nexus 7, založím ve složce app\src\main\res\layout-w600dp\ požadovaný layout

Pro Nexus 10 založím v app\src\main\res\layout-w720dp\ požadovaný layout

Windows 10: automatické zapnutí Num Lock po zapnutí

Ve Windows 10 je defaulně po zapnutí PC vypnutý Num Lock. Pokud máte v hesle číslo, příhlásíte se až na druhý pokus 🙂

Jak zapnout Num Lock po startu PC?

Tuto vlastnost je nutné změnit v registru. Zmáčkněte klávesu Win+R pro spuštění programu a do okna zadejte regedit. Potvdíte klávesou ENTER.

Ve stromu jděte na následující umístění: HKEY_USERS\.DEFAULT\Control Panel\Keyboard kde upravíte InitialKeyboardIndicators na Údaj hodnoty: 80000002 . Někdy může původní řetězec nabývat hodnoty 2147483648, v tom případě ho změňte na: 2147483650.
Stejným způsobem změňte umístění HKEY_CURRENT_USER\Control Panel\Keyboard  upravíme InitialKeyboardIndicators na hodnotu: 80000002

Po restartování je Num Lock zapnutý 🙂 Případně na přihlašovací obrazovce stiskněte Num lock a znovu počítač restartujte.

Stále nefunguje?

Pokud toto nezabralo, jděte do nabídky Start -> vyhledejte Ovládací panely ve kterých pokračujte do Hardware a Zvuk -> Možnosti napájení.
Vlevo zvolte Nastavení tlačítek napájení a nahoře klikněte na Změnit nastavení, které není k dispozici.
V otevřeném okně odškrtněte položku Zapnout rychlé spuštění (doporučeno).

w10-numlock

Podle vaší zpětné vazby tento postup nefunguje všem…