Mobilna detekcja – lekka i przyjemna z PHP

PHP Mobile Detect

Jeżeli pracujemy nad projektami stron / aplikacji internetowych, które mają być również dostępne na urządzeniach mobilnych, to w 99% przypadków zmuszeni jesteśmy do konkretnej identyfikacji urządzeń. Pozwala nam to dostosować układ strony pod konkretny smartfon, tablet, czy inne urządzenie przenośne. Zwykle chcemy także wiedzieć jakie funkcje dostępne są na danym urządzeniu oraz z jakim oprogramowaniem i w jakiej wersji mamy do czynienia.

Pisałem już wprawdzie o detekcji mobilnej przeglądarki, ale w tym przypadku możemy skorzystać z potężnej biblioteki, jaką jest WURFL (o niej również pisałem WURFL – dodatkowa porcja informacji), ale jest to straszny kombajn, który pozwala na bardzo dużo i tak naprawdę w typowych projektach nie wykorzystamy nawet połowy jego możliwości. Jeżeli zależy nam na “lekkości” oraz prostocie wykorzystywanej biblioteki, to z pewnością warto zwrócić uwagę na Mobile Detect. Samą bibliotekę znalazłem w zakamarkach Githuba – polecam notabene tam zaglądać, bo czasami naprawdę fajne rzeczy można znaleźć.

Przykładowe wykorzystanie

include 'Mobile_Detect.php';
$detect = new Mobile_Detect();

// Check for any mobile device.
if ($detect->isMobile())

// Check for any tablet.
if ($detect->isTablet())

// Check for any mobile device, excluding tablets.
if ($detect->isMobile() && !$detect->isTablet())

I trochę bardziej konkretny przykład kodu

// Alternative to $detect->isAndroidOS()
$detect->is('AndroidOS');

// Batch usage
foreach($userAgents as $userAgent){
  $detect->setUserAgent($userAgent);
  $isMobile = $detect->isMobile();
}

// Version check.
$detect->version('iPad'); // 4.3 (float)

Możecie się także zapoznać z DEMEM, które przedstawia użycie biblioteki, a ją samą pobrać spod adresu: https://github.com/serbanghita/Mobile-Detect

Dobrze, że istnieje Open Source :)

Nokia Lumia 920 – 30 dni przygody

Po zawirowaniach związanych z kończeniem przeze mnie studiów inżynierskich (z sukcesem!), wracam do pisania kolejnych treści. Jakiś czas temu popełniłem wpis na temat aplikacji jaką tworzyłem na platformę Windows Phone, a tym razem chciałbym Wam nieco opowiedzieć o mojej przygodzie ze smartfonem Nokia Lumia 920.

nokia-lumia-920

 

Zadacie pytanie – dlaczego akurat Nokia Lumia 920? Mianowicie udało mi się dostać do programu “Testuj z Orange”, gdzie jako jedna z 150 osób otrzymałem smartfon Nokia Lumia 920 oraz głośnik Nokia Play 360 na 30 dni testów. Przez ten cały czas mogłem zgłębiać tajniki platformy Windows Phone oraz zobowiązany byłem do wykonania 5 serii zadań, gdzie pojawiły się zadania takie jak: porównanie Lumii do swojego obecnego telefonu, filmik przedstawiający “Moje Święta”, a nawet parodia sceny z wybranego filmu z usługi “Telewizja Tu i Tam”.

Co więcej – ktoś docenił moje starania, poświęcenie oraz pracę jaką włożyłem w wykonywanie zadań i udało mi się dostać do grona 70 laureatów i otrzymałem tym samym cały otrzymany zestaw od Orange na własność!

2012-12-19 19.26.50

Mimo tak wielkiego wyróżnienia, nie będę tutaj pisać, że wszystko jest takie kolorowe jak mogłoby się wydawać. Mam na myśli platformę, która tak mocno promowana jest ostatnimi czasy przez Microsoft, a mianowicie Windows Phone 8.

Konkurs “Testuj z Orange” w pierwszej fazie miał być związany mocno z mBankiem oraz usługą NFC, pozwalającą wykonywać między innymi płatności zbliżeniowe za pomocą smartfonu. Okazało się jednak, że błędy w oprogramowaniu obsługującym właśnie tą usługę uniemożliwiają wykonywanie jakichkolwiek płatności! Wyobrażacie sobie? Tak mocno promowana usługa w ogóle nie działa i to na samym początku życia platformy.. :/

Teraz NFC już działa, bo pojawiła się aktualizacja, ale jest / był to niewątpliwie wielki “fuck-up” Microsoftu i nic dodać, nic ująć – kolejny cios dla Nokii.

deezer

Tym samym – konkurs rozpoczął się tydzień później, a z regulaminu zniknęły zapisy odnośnie NFC. Pojawiły się za to informacje, jakoby w ramach całego programu, każdy tester otrzyma kontro Premium usługi Deezer oraz głośnik Nokia Play 360 i 1GB mobilnego Internetu do wykorzystania.

Nokia Lumia 920 jest wspaniałym urządzeniem, które otrzymało jednak brzydkie ubranie w postaci Windows Phone 8. Początek z platformą był bardzo obiecujący i wiele rzeczy bardzo mi się podobało. Przede wszystkim – prostota i szybkość działania. Windows Phone jest jeszcze prostszy niż iOS od Apple. Szybko się jednak rozczarowałem, kiedy to nie mogłem znaleźć swoich ulubionych aplikacji w markecie Windows Store, a których używam na co dzień na moim wysłużonym HTC Desire HD pracującego pod kontrolą Androida w najnowszej wersji. Aplikacje, które znalazłem nie są już tymi samymi aplikacjami, których używam na Androidzie. Są jakby oskubane z wielu ważnych funkcji, a ich jakość wykonania i estetyka znacząco odbiega od tego do czego się przyzwyczaiłem. Jeśli chodzi o szybkość działania, jest to raczej zasługa potężnego wnętrza Lumii niżeli platformy.

Całość zbudowana jest jakby na szybko, bez jakichkolwiek standardów i dogłębnych przemyśleń. Przykładowo – opcje wyboru w menu ustawień pisane są raz z małej, raz z wielkiej litery. Niby drobnostka, a strasznie razi w oczy. Początkowa prostota i intuicyjność przeradza się raczej w zagubienie i odczucie nieporadności.

Muszę być także szczęściarzem, ponieważ smartfon zawiesił mi się tylko raz. Może dlatego, że początkowa ekscytacja przerodziła się w znudzenie i nie korzystałem z Lumii zbyt wiele. Wielu innym testerom i zarówno moim rywalom w konkursie Orange telefon potrafił zawieszać się kilka razy dziennie, a innym zawiesił się na dobre i nie byli oni w stanie wzbudzić go do życia. Totalna porażka. Z Lumii korzystałem jedynie w ramach realizacji zadań konkursowych, wykonywania zdjęć lub filmów oraz słuchania muzyki w połączeniu z otrzymanym głośnikiem i usługą Deezer.

Nokia mimo wszystko zbudowała naprawdę świetny smartfon, który robi rewelacyjne zdjęcia i kręci niesamowite filmy oraz od strony sprzętowej posiada wszystko co potrzeba nowoczesnemu urządzeniu mobilnemu. Sądzę, że gdyby nie Windows Phone 8 byłby to strzał w dziesiątkę i polecałbym ten smartfon każdemu. Sam jednak pozostanę przy moim HTC, który swe lata świetności ma już dawno za sobą, a mimo to wydaje się dla mnie znacznie lepszym wyborem.

Taki mały dodatek na koniec. Jak wspomniałem w poprzednim wpisie – zamierzałem poprawić Naszą Muzę właśnie z wykorzystaniem natywnego testowania na smartfonie. Cała operacja dzięki Lumii przebiegła bardzo sprawnie, a rezultaty możecie zobaczyć na poniższych screenach. Uważam, że to duży sukces aplikacji, która praktycznie bez żadnej reklamy pobrana została dotąd przez prawie 1150 użytkowników z samej tylko Polski (aplikacja targetowana jest wyłącznie na ten rynek z racji polskojęzycznych treści :))

nasza-muza-stats

naszamuza-najlepsze-nowe

Roundup #12 – Mobiscroll, TideSDK, Terrific Composer, iView Slider, Tooltipster, Yeoman, Neat, Prefix free, This Is Responsive

Roundup #12 - Mobiscroll, TideSDK, Terrific Composer, iView Slider, Tooltipster, Yeoman, Neat, Prefix free, This Is Responsive

Mobiscroll

Mobiscroll is a powerful, easy to set-up HTML5 control, that makes selecting values for your smartphone & tablet users a breeze. It is an Open Source control built on solid ground with jQuery. It is your one-stop solution for everything scrollable list. Its customizable and modular nature provides a great foundation you can build on.

Mobiscroll – The customizable HTML5 spinner control for touch devices


TideSDK

Create multi-platform desktop apps with HTML5, CSS3 and JavaScript TideSDK formerly known as Titanium Desktop is the best way to create beautiful, unique desktop apps using your web development skills.

Create Desktop Apps With HTML5, CSS3 And JavaScript With TideSDK


Terrific Composer

Terrific Composer is a Frontend Development Framework specifically designed for building deluxe frontends based on the Terrific concept

Terrific Composer – A framework designed for building deluxe frontends


iView Slider

iView is easy to use jQuery image slider with animated captions, responsive layout and HTML Elements like (Video, iFrame) slider. Easily add unlimited number of slides and captions. Use it as image slider, image gallery, banner rotator, banner ads, or even presentation.

iView Slider – A responsive slider with animated captions


Tooltipster

Tooltipster is a lightweight (4,813 bytes minified) jQuery plugin that enables you to easily create clean, HTML5 validated tooltips.

  • Supports HTML tags inside the tooltip
  • Lightweight and degradable
  • Extremely flexible & fast to set up
  • Easily styled with 100% CSS – no images needed
  • Plays nicely with IE
Good-Looking & Lightweight Tooltips: Tooltipster

Yeoman

Yeoman is a robust and opinionated set of tools, libraries, and a workflow that can help developers quickly build beautiful, compelling web apps.


Neat

Neat is a simple grid framework built on top of Sass and Bourbon using em units and golden ratios. Using Sass 3.2 block mixins, this framework makes it extremely easy to build responsive layouts. Using the breakpoint() mixin, you can change the number of columns in the grid for each media query and store these values in project-wide variables to DRY up your code.

Bourbon Neat – A simple responsive grid framework built on top of Sass and Bourbon


Prefix free

-prefix-free lets you use only unprefixed CSS properties everywhere. It works behind the scenes, adding the current browser’s prefix to any CSS code, only when it’s needed.

Break Free From CSS Prefix with -Prefix-free JS Plugin


This Is Responsive

This Is Responsive. Patterns, resources and news for creating responsive web experiences.

A Place To Find Any Information On Responsive Layouts: This Is Responsive


[1], [2], [3]

Notyfikacje PUSH dla urządzeń z Androidem w PHP – GCM

Google Cloud Messaging for Android

Google Cloud Messaging to usługa uruchomiona przez Google niecały miesiąc temu (wcześniej C2DM). Pozwala ona na wysyłanie powiadomień PUSH na urządzenia z Androidem bezpośrednio z serwera obsługującego aplikację mobilną. Takie rozwiązanie posiadają wszystkie największe platformy – iOS, Windows Phone 7, Blackberry, a sama platforma Android praktycznie od samego początku swojego istnienia. Jednak to urządzenia od Apple cieszą się większą popularnością takiej usługi. Google postanowiło to zmienić i zbudowało od nowa całą usługę, tak by ułatwić deweloperom implementację w swoich projektach, a także obsługę takich notyfikacji po stronie serwera aplikacji. Jako, że w pracy przymierzam się do zadania stworzenia ogólnodostępnego API REST na wiele platform mobilnych, postanowiłem, że zacznę od napisania prostej klasy w PHP, która obsługuje właśnie GCM do Google.

Cała dokumentacja usługi od Google dostępna jest na stronie oficjalnej i nie ma sensu tutaj przytaczać tego co bardzo dobrze opisano właśnie tam. Bibliotekę JAR dla Javy mamy dostępną “od ręki” i możemy wykorzystać ją w swoim projekcie, ale z PHP nie jest już tak wesoło i sami musimy podjąć się implementacji GCM po swojej stronie.

Do napisania poniżej klasy posłużyłem się biblioteką Buzz, która jest niczym więcej jak oprogramowanym cURL’em.

<?php

namespace Service\Gcm;

use Buzz\Browser;
use Buzz\Client\MultiCurl;

class Gcm
{
    /**
     * @var string
     */
    protected $apiUrl = 'https://android.googleapis.com/gcm/send';

    /**
     * @var string
     */
    protected $apiKey;

    /**
     * @var string
     */
    protected $registrationIdMaxCount = 1000;

    /**
     * @var \Buzz\Browser
     */
    protected $browser;

    /**
     * @var array
     */
    protected $responses;

    /**
     * Class constructor
     *
     * @param $apiKey
     * @param null $baseUrl
     */
    public function __construct($apiKey, $apiUrl = null)
    {
        $this->apiKey = $apiKey;

        if ($apiUrl) {
            $this->apiUrl = $apiUrl;
        }

        $this->browser = new Browser(new MultiCurl());
    }

    /**
     * Sends the data to the given registration ID's via the GCM server
     *
     * @param mixed $data
     * @param array $registrationIds
     * @param array $options to add along with message, such as collapse_key, time_to_live, delay_while_idle
     * @return bool
     */
    public function send($data, array $registrationIds, array $options = array())
    {
        $headers = array(
            'Authorization: key='.$this->apiKey,
            'Content-Type: application/json'
        );

        $data = array_merge($options, array(
            'data' => $data,
        ));

        // Chunk number of registration ID's according to the maximum allowed by GCM
        $chunks = array_chunk($registrationIds, $this->registrationIdMaxCount);

        // Perform the calls (in parallel)
        $this->responses = array();
        foreach ($chunks as $registrationIds) {
            $data['registration_ids'] = $registrationIds;
            $this->responses[] = $this->browser->post($this->apiUrl, $headers, json_encode($data));
        }
        $this->browser->getClient()->flush();

        // Determine success
        foreach ($this->responses as $response) {
            $message = json_decode($response->getContent());
            if ($message === null || $message->success == 0 || $message->failure > 0) {
                return false;
            }
        }

        return true;
    }

    /**
     * @return array
     */
    public function getResponses()
    {
        return $this->responses;
    }
}

Prawda, że nie wygląda to skomplikowanie? Jest to tak naprawdę klasa-interfejs, do użycia w naszym kodzie, gdzie z bazy danych będziemy mogli pobrać zapisanie urządzenia oraz wysłać im przygotowane powiadomienia. Brakuje tutaj obsługi błędów, ale to dopiero przede mną :)

WURFL – dodatkowa porcja informacji

WURFL Mobile Detection

W moim poprzednim wpisie – Detekcja mobilnej przeglądarki – zapomniałem wspomnieć o jednej z bibliotek – wręcz “kolosie”, który okazuje się być bardzo pomocnym na naszej mobilnej drodze. Dzięki Ci wielkie Artur, że przypomniałeś mi o niej w swoim komentarzu.

WURFL (Wireless Universal Resource FiLe) skupia się na wykrywania urządzeń mobilnych. Jest zbiorem własnych interfejsów programowania aplikacji (API) i plików konfiguracyjnych w formacie XML, który zawiera informacje o możliwości urządzenia i cechach różnych urządzeń przenośnych.  Do wersji 2.2, WURFL posiadał licencję “open source / public domain”. Od dnia 30 sierpnia 2011, ScientiaMobile WURFL API jest dostępny z licencją AGPL do niekomercyjnego użytku. Aktualna wersja samej bazy danych WURFL nie jest już dostępna na podstawie licencji “open source”.

WURFL pozwala na znacznie więcej niż tylko informacje na temat tego, z jaką przeglądarką mamy do czynienia i czy nie jest ona czasami uruchomiona na urządzeniu mobilnym. Dzięki tej bibliotece jesteśmy w stanie poznać wszystkie cechy oraz funkcje, które oferuje nam dane urządzenie (ściślej – zainstalowana przeglądarka).

WURFL wspiera i może być wykorzystywane przez poniższe technologie:

  • Java (WALL)
  • PHP (Tera-WURFL (database driven), New WURFL PHP API i WALL4PHP)
  • .NET Framework (Visual Basic / C# / .Net API)
  • Perl
  • Ruby
  • Python (Python Tools)
  • XSLT
  • C++
  • Apache Mobile Filter
  • PHP
  • Perl
  • Python
  • JavaScript
  • ActionScript 3 (Flash / Flex / AIR / ECMAScript)

By dowiedzieć się nieco więcej na temat tego co oferuje API WURFL, polecam udać się na oficjalną stronę, gdzie mamy dostępne wszystkie informacje.

Detekcja mobilnej przeglądarki

Mobile Browser DetectionJeżeli chcielibyście przygotować wersję mobilną swojej strony, to z pewnością przyda się Wam prosty skrypt, który pozwoli Wam na identyfikację, czy macie do czynienia z przeglądarką na urządzeniu mobilnym. Dzięki temu, będziecie w stanie dostosować wyświetlaną treść i jej format do odpowiedniej wielkości oraz dodać lub ograniczyć pewne funkcjonalności.

jQuery

var userAgent = navigator.userAgent || navigator.vendor || window.opera;
var isMobile = function (userAgent) {
    return /android.+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|meego.+mobile|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(userAgent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(userAgent.substr(0, 4))
};
console.log(isMobile(userAgent));

PHP

$isMobile = false;
$isBot = false;

$op = strtolower($_SERVER['HTTP_X_OPERAMINI_PHONE']);
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
$ac = strtolower($_SERVER['HTTP_ACCEPT']);
$ip = $_SERVER['REMOTE_ADDR'];

$isMobile = strpos($ac, 'application/vnd.wap.xhtml+xml') !== false
        || $op != ''
        || strpos($ua, 'sony') !== false 
        || strpos($ua, 'symbian') !== false 
        || strpos($ua, 'nokia') !== false 
        || strpos($ua, 'samsung') !== false 
        || strpos($ua, 'mobile') !== false
        || strpos($ua, 'windows ce') !== false
        || strpos($ua, 'epoc') !== false
        || strpos($ua, 'opera mini') !== false
        || strpos($ua, 'nitro') !== false
        || strpos($ua, 'j2me') !== false
        || strpos($ua, 'midp-') !== false
        || strpos($ua, 'cldc-') !== false
        || strpos($ua, 'netfront') !== false
        || strpos($ua, 'mot') !== false
        || strpos($ua, 'up.browser') !== false
        || strpos($ua, 'up.link') !== false
        || strpos($ua, 'audiovox') !== false
        || strpos($ua, 'blackberry') !== false
        || strpos($ua, 'ericsson,') !== false
        || strpos($ua, 'panasonic') !== false
        || strpos($ua, 'philips') !== false
        || strpos($ua, 'sanyo') !== false
        || strpos($ua, 'sharp') !== false
        || strpos($ua, 'sie-') !== false
        || strpos($ua, 'portalmmm') !== false
        || strpos($ua, 'blazer') !== false
        || strpos($ua, 'avantgo') !== false
        || strpos($ua, 'danger') !== false
        || strpos($ua, 'palm') !== false
        || strpos($ua, 'series60') !== false
        || strpos($ua, 'palmsource') !== false
        || strpos($ua, 'pocketpc') !== false
        || strpos($ua, 'smartphone') !== false
        || strpos($ua, 'rover') !== false
        || strpos($ua, 'ipaq') !== false
        || strpos($ua, 'au-mic,') !== false
        || strpos($ua, 'alcatel') !== false
        || strpos($ua, 'ericy') !== false
        || strpos($ua, 'up.link') !== false
        || strpos($ua, 'vodafone/') !== false
        || strpos($ua, 'wap1.') !== false
        || strpos($ua, 'wap2.') !== false;

        $isBot =  $ip == '66.249.65.39' 
        || strpos($ua, 'googlebot') !== false 
        || strpos($ua, 'mediapartners') !== false 
        || strpos($ua, 'yahooysmcm') !== false 
        || strpos($ua, 'baiduspider') !== false
        || strpos($ua, 'msnbot') !== false
        || strpos($ua, 'slurp') !== false
        || strpos($ua, 'ask') !== false
        || strpos($ua, 'teoma') !== false
        || strpos($ua, 'spider') !== false 
        || strpos($ua, 'heritrix') !== false 
        || strpos($ua, 'attentio') !== false 
        || strpos($ua, 'twiceler') !== false 
        || strpos($ua, 'irlbot') !== false 
        || strpos($ua, 'fast crawler') !== false                        
        || strpos($ua, 'fastmobilecrawl') !== false 
        || strpos($ua, 'jumpbot') !== false
        || strpos($ua, 'googlebot-mobile') !== false
        || strpos($ua, 'yahooseeker') !== false
        || strpos($ua, 'motionbot') !== false
        || strpos($ua, 'mediobot') !== false
        || strpos($ua, 'chtml generic') !== false
        || strpos($ua, 'nokia6230i/. fast crawler') !== false;

..i przykładowe użycie:

if ($isMobile) {
   header('Location: http://m.mrzepinski.pl' . urlencode($_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']));
   exit();
}

Apache

RewriteEngine On
RewriteBase /

RewriteCond %{HTTP_USER_AGENT} android.+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge\ |maemo|meego.+mobile|midp|mmp|netfront|opera\ m(ob|in)i|palm(\ os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows\ (ce|phone)|xda|xiino [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^(1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a\ wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r\ |s\ )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1\ u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp(\ i|ip)|hs\-c|ht(c(\-|\ |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac(\ |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt(\ |\/)|klon|kpt\ |kwc\-|kyo(c|k)|le(no|xi)|lg(\ g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-|\ |o|v)|zz)|mt(50|p1|v\ )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v\ )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-|\ )|webc|whit|wi(g\ |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-) [NC]
RewriteRule ^/(.*)$ http://m.mrzepinski.pl/$1 [R,L]

Tłumaczenie ze zdjęć w nowym Google Translate na Androida!

Google Translate AndroidTłumacz Google (Google Translate) jest to serwis internetowy Google umożliwiający tłumaczenie tekstów, plików tekstowych oraz całych stron internetowych na różne języki. W przypadku wpisania tekstu, serwis tłumaczy go w czasie rzeczywistym (bez potrzeby klikania w przycisk “tłumacz”). Po wpisaniu w okienko translatora pojedynczego słowa działa on jak słownik – podając zwykle kilka lub kilkanaście propozycji tłumaczenia.

W najnowszej wersji Google Translate dodano nową opcję, jaką jest tłumaczenie ze zrobionego za pomocą mobilnego urządzenia zdjęcia. Wystarczy, że w aplikacji wybierzemy opcję robienia zdjęcia i dokonamy tego, fotografując zdanie, dokument, okładkę itp. Następnie, na zrobionym zdjęciu zaznaczamy palcem, który fragment chcemy aby aplikacja dla nas przetłumaczyła i.. gotowe!

Google Translate Image Example

Z pewnością takie rozwiązanie jest znacznie szybsze niż tradycyjne przepisywanie tekstu ręcznie, a na pewno niezbędne dla osób podróżujących chociażby do krajów, gdzie alfabetem są tzw. “krzaczki”. Mam tutaj na myśli kraje takie jak Chiny, Japonia itp.

Co myślicie o takim rozwiązaniu? Mi, nowa funkcja bardzo się podoba i zachęcam do aktualizowania swoich aplikacji na urządzeniach z Androidem.