Wirtualne Zacisze utak3ra

utak3r's virtual shelter

?>

Gra w karty podobna do bakarata

  1. automaty do gier dla zabawy 2023 na stronie kasyna: W 10bet Casino możesz grać w ponad 1000 automatów i gier stołowych, więcej gier niż w przeciętnym kasynie online.
  2. gra w ruletkę online w kasynie internetowym - Innym czynnikiem może być skłonność do blefowania.
  3. graj w automat do gier hazardowych online na prawdziwe pieniądze: Po osiągnięciu rundy bonusowej możesz grać o trzy różne jackpoty, z których każdy oferuje inną sumę pieniędzy, jeśli zdobędziesz zwycięską linię wypłat.

Najczęściej trafiane liczby w keno

jakie są darmowe bonusy dostępne w kasynie na rok 2023 i jak je zdobyć
Zapewniając niezliczone godziny rozrywki dla gości każdego dnia, jest to naturalne, że doświadczenie jest teraz powielane na stronach internetowych kasyn w Kanadzie.
kasyno online oferujące free spiny bez konieczności dokonania depozytu
Podobnie jak Bakarat i blackjack, jest to proces, który jest w toku, ale nie został jeszcze dostarczony.
Premierpunt jest przystający do Bookee, ponieważ ma automaty Elk Studios i automaty Spinmatic plus ma porównywalne najlepsze gry kasynowe, takie jak Fairies Forest, Sirens Serenade by 1x2 Gaming i Cashsplash 5 Reel.

Minimalny depozyt kasyno

kasyno online z największą liczbą wygranych w 2023 roku
Wiele krajów nakłada przepisy dotyczące tego, ile można wypłacić z bankomatu w dowolnym momencie.
najlepsze sloty do gier w winnicach dostępne online 2023
Ale co się dzieje, gdy przychodzi czas na wypłatę gotówki z powrotem na kartę, bank lub portfel internetowy.
nowe automaty online dostępne za darmo bez rejestracji w 2023 roku

Pluginy aplikacji Qt5

Tworzenie systemu pluginów aplikacji działającej na różnych systemach wymagało zawsze wielokrotnej implementacji tego samego – dla każdego systemu oddzielnie, głównie z powodu sposobu dynamicznego ładowania bibliotek. W Qt jednak jest inaczej – framework ten udostępnia bardzo sprawnie działający system pluginów.

Na początek zdefiniujmy interfejs (API):

#ifndef DESIGNLAYER_API_H
#define DESIGNLAYER_API_H

#include 
#include 

namespace apophysis
	{		
	class DesignLayerAPI
		{
		public:
			virtual ~DesignLayerAPI() {};
			virtual QString getName() = 0;
		};
	}

#define DesignLayerAPI_iid "org.apophysis.DesignLayerAPI"

Q_DECLARE_INTERFACE(apophysis::DesignLayerAPI, DesignLayerAPI_iid)

#endif // DESIGNLAYER_API_H

Widzimy tu wirtualną klasę, definiującą metodę getName(). Po definicji API, następuje definicja interfejsu, po którym Qt będzie rozpoznawać nasze pluginy, implementujące te API.

Czas na plugin. Deklarujemy klasę implementującą API:

#ifndef DESIGNLAYER_IMAGE_H
#define DESIGNLAYER_IMAGE_H

#include 
#include 
#include 

class designLayerImage : public QObject, apophysis::DesignLayerAPI
	{
	Q_OBJECT
		Q_PLUGIN_METADATA(IID "org.apophysis.DesignLayerAPI" FILE "designLayerImage.json")
		Q_INTERFACES(apophysis::DesignLayerAPI)

	public:
		designLayerImage();
		QString getName() Q_DECL_OVERRIDE;
	private:
		QString theName;
	};

#endif // DESIGNLAYER_IMAGE_H

Oprócz deklaracji metod zadeklarowanych w interfejsie, widzimy tu jeszcze jedną rzecz: definicję metadanych. Po co to? Metadane pluginu można odczytać bez faktycznego ładowania biblioteki. Zapisujemy je w pliku JSON, np:

{
"type"			:	"Layer",
"name"			:	"Image layer plugin",
"shortname"		:	"ImageLayer",
"version"		:	"0.1",
"author"		:	"Apophysis internal",
"description"	:	"Used mainly for backgrounds: solid colour, gradients, images, etc."
}

Właściwa implementacja jest oczywista, żadnej magii tu nie ma:

#include "designLayerImage.h"

designLayerImage::designLayerImage()
	:
	theName(QLatin1Literal("Unnamed image layer"))
	{
	}

QString designLayerImage::getName()
	{
	return theName;
	}

OK, mamy plugin. Jak go użyć? Na szczęście, to również jest proste (i przenośne! Na pewno działa bez zmian pod Windows i Linux, pod OSX nie sprawdzałem).

Najpierw sprawdzimy w działaniu system metadanych. Załóżmy, że pluginy mamy w podkatalogu plugins (niespodzianka!):

#include 
#include 

void listPlugins()
	{
	QDir pluginsDir(qApp->applicationDirPath());
	pluginsDir.cd(QLatin1Literal("plugins"));
	foreach(QString fileName, pluginsDir.entryList(QDir::Files, QDir::Name))
		{
		QString libExt;
#if defined(Q_OS_WIN)
		libExt = QLatin1Literal("dll");
#elif defined(Q_OS_MAC)
		libExt = QLatin1Literal("bundle");
#elif defined(Q_OS_LINUX)
		libExt = QLatin1Literal("so");
#endif
		if (QFileInfo(fileName).suffix().toLower() == libExt)
			{
			QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
			qDebug() << "File:" << fileName;
			QJsonObject jsonMetaData = pluginLoader.metaData().value(QLatin1Literal("MetaData")).toObject();
			qDebug() << jsonMetaData.value(QLatin1Literal("type")).toString();
			qDebug() << jsonMetaData.value(QLatin1Literal("name")).toString();
			qDebug() << jsonMetaData.value(QLatin1Literal("shortname")).toString();
			qDebug() << jsonMetaData.value(QLatin1Literal("version")).toString();
			qDebug() << jsonMetaData.value(QLatin1Literal("author")).toString();
			qDebug() << jsonMetaData.value(QLatin1Literal("description")).toString();
			}
		}
	}

W zasadzie moglibyśmy się obejść bez sekcji sprawdzania rozszerzenia plików, ale używam tego w razie, gdyby w katalogu były jeszcze jakieś inne pliki (ot, chociażby PDB).

OK, czas na crème de la crème, czyli stworzenie instancji klasy zaimplementowanej w pluginie:

void apophysis::Design::addLayer(const QString & aLayerType)
	{
	QDir pluginsDir(qApp->applicationDirPath());
	pluginsDir.cd(QLatin1Literal("plugins"));
	foreach(QString fileName, pluginsDir.entryList(QDir::Files, QDir::Name))
		{
		QString libExt;
#if defined(Q_OS_WIN)
		libExt = QLatin1Literal("dll");
#elif defined(Q_OS_MAC)
		libExt = QLatin1Literal("bundle");
#elif defined(Q_OS_LINUX)
		libExt = QLatin1Literal("so");
#endif
		if (QFileInfo(fileName).suffix().toLower() == libExt)
			{
			QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
			QString plugintype = pluginLoader.metaData().value(QLatin1Literal("MetaData")).toObject().value(QLatin1Literal("type")).toString();
			QString pluginshortname = pluginLoader.metaData().value(QLatin1Literal("MetaData")).toObject().value(QLatin1Literal("shortname")).toString();
			if ((plugintype == QLatin1Literal("Layer")) && (pluginshortname == aLayerType))
				{
				QObject *plugin = pluginLoader.instance();
				if (plugin)
					{
					apophysis::DesignLayerAPI *layer = qobject_cast(plugin);
					if (layer)
						theLayers.append(layer);
					}
				}
			}
		}
	}

Jak widać, zarówno tworzenie, jak i używanie pluginów w tym systemie jest trywialne - i jest całkowicie przenośne.

Happy coding!

Git a automatyczne budowanie Jenkinsem

Do tej pory, na cele Continuous Integration, w Jenkinsie miałem ustawione sprawdzanie repozytorium Git (opcja SCM polling) co 15 minut. W zasadzie to działało, ale bywały momenty, że owe 15 minut było okresem zbyt długim. Można oczywiście (nikt nie broni…) ustawić okres sprawdzania na * * * * *, czyli sprawdzanie co minutę, ale to również nie jest dobre rozwiązanie, z oczywistych powodów. Dlatego też postanowiłem powiesić akcję odpytywania Gita przez Jenkinsa na haku, żeby automagicznie każdy push od developera powodował start Jenkinsa.

Oczywiście, Jenkins musi być wyposażony we wtyczkę Git.

Zaczynamy od próby ręcznego zdalnego wywołania Jenkinsa. Otóż wtyczka Git otwiera takową drogę właśnie na okoliczność notyfikacji o nowym commicie. Jak czytamy w dokumentacji wtyczki, można powiadomić Jenkinsa o konkretnym commicie, ale ja na cele Continuous Integration i tak chcę pobrać najnowsze w danej chwili źródła, aby sprawdzić integrację poszczególnych prac właśnie. Dlatego użyjemy najprostszej formy wywołania wtyczki, która spowoduje wymuszenie odpytania repozytorium o zmiany.

Na początek, w konfiguracji zadania Jenkinsowego, usuwamy wszelkie terminarze, jakie mieliśmy – ale samą opcję Poll SCM musimy pozostawić włączoną (ale pustą):

Jenkins SCM Polling

Następnie, będąc na serwerze gitowym, instalujemy pakiet curl, jeśli go tam jeszcze nie ma. Gdy już go mamy, wywołujemy testową komendę:

curl http://moj.jenkins.com:8080/git/notifyCommit?url=git@moj.git.com:WspanialeRepo

Ścieżka do repozytorium powinna być dokładnie taka sama, jaką podajemy przy jego klonowaniu. Jeśli wszystko pójdzie dobrze, przeczytamy, że zostało zlecone odpytanie repozytorium. Sprawdzamy w logach Jenkinsa Git Polling Log, czy rzeczywiście tak było.

Jeśli wszystko zadziałało, czas ten proces zautomatyzować. Aby wywołać jakąś akcję po każdym pushu od developera, musimy zdefiniować hak post-receive. W katalogu repozytorium znajduje się podkatalog hooks. Tworzymy nowy plik i nadajemy mu właściwe uprawnienia:

touch post-receive
chown git:git post-receive
chmod 775 post-receive

i edytujemy go:

#!/bin/sh
curl http://moj.jenkins.com:8080/git/notifyCommit?url=git@moj.git.com:WspanialeRepo

Od tej pory, za każdym razem, gdy developer zrobi pusha, Jenkins wykona swoją robotę 🙂 A my cieszymy się z Continuous Integration 😉

Google Nik Collection test drive

Google Nik Collection za darmo!

Wczoraj Google uderzyło z przepięknym prezentem Wielkanocnym – pakiet Google Nik Collection został pakietem… darmowym! 🙂

Jeśli jest ktoś (interesujący się fotografią), kto nie zna jeszcze tego pakietu, ten musi czym prędzej nadrobić zaległości. Pakiet składa się z:

  • Analog Efex Pro
  • Color Efex Pro
  • Silver Efex Pro
  • Viveza
  • HDR Efex Pro

oraz dwóch najważniejszych:

  • Sharpener Pro
  • Dfine

Jako szybki test, wziąłem moje niedawno wykonane zdjęcie na tapetę. Trzy zdjęcia, bracketowane co 2EV. Najpierw przepuściłem je przez RAW Pre-Sharpenera, następnie połączyłem w HDR Efex i na końcu wygładziłem w Dfine. Żadnej więcej obróbki nie stosowałem, poza eksportem do JPEGa, oczywiście 😉 Efekt poniżej.


Zachęcam do zapoznania się z pakietem, warto.

Sigma UC ZOOM 70-210mm with Sony a6000

Obiektyw Sigma UC ZOOM 70-210mm 1:4-5.6

Jako, że zbliża się wielkimi krokami nowy sezon występów tanecznych mojej córki, Natalki, a także wiedząc, jak wielką porażką (przynajmniej wg mnie samego) fotograficzną z tego tytułu był sezon poprzedni, postanowiłem rozejrzeć się za nowym obiektywem. Oczywiście, rozmawiamy o cenach dla ludzi, dla których fotografia to tylko hobby. Wiem, że za 2-4 tysiące mógłbym mieć wspaniałe szkło, no ale… wystarczy, że aparat tyle kosztował 😉  Jeszcze gwoli uzupełnienia tematu, ostatnio zakupiłem również monopod, który przyda się na tego typu imprezy, gdzie ze statywem nie ma się jak pchać.

Po kilku tygodniach polowań udało mi się wygrać aukcję, na której wytargałem Sigmę UC ZOOM 70-210mm 1:4-5.6 na bagnecie pentaksa za jedyne 91 zł 🙂 Zbyt wiele od niego nie oczekiwałem… dzisiaj przyszedł, więc po pracy wybrałem się z nim nad wody Odry (wystarczy wyjść z biura i już tam jestem 😉 ).

Na pierwszy ogień poszedł test bokeh. Tutaj nie miałem zbyt wielkich oczekiwań – raz, że zoom, dwa, że dość ciemny jednak (pełna dziura to zaledwie f4). I… mocno się zdziwiłem. Obiektyw ma przepiękny bokeh!

Potem poszedł test ostrości… dzisiaj, jako że z ręki strzelałem, na krótkim końcu i w okolicach (tak 70-90mm). Tutaj również obiektyw zdał test. Wychodzi na to, że za 90 zł udało mi się dostać całkiem udane szkiełko 🙂  duże toto co prawda, no i oczywiście w pełni manualne, ale mi to akurat w ogóle nie przeszkadza (gdy się uczyłem fotografii, nie istniał autofokus 😉 ).

Reasumując: za mniej, niż 100zł mam szkiełko, które potrafi dać sporo radości 🙂 czego i Wam życzę. A za dwa tygodnie dam znać, jak się toto spisuje w trudnych warunkach oświetleniowych…

dogwood52week5

Dogwood 52 Week Photography Challenge

Z początkiem tego roku, trafiłem na ciekawy projekt fotograficzny: Dogwood 52 Week Photography Challenge. Projekt polega na tym, że są ustalone 52 tematy zdjęć, które należy wykonywać tydzień po tygodniu. Za każdym razem należy wykonać nowe zdjęcie, specjalnie na potrzeby owego projektu. W ten sposób, w miarę egzekucji, powinniśmy rozwinąć nasze zdolności postrzegania świata dookoła nas, a także wzmocnić umiejętności czysto techniczne, nauczyć się planowania fotografii itd.

Stwierdziłem, że taki projekt to ciekawa sprawa – no i przystąpiłem do niego 🙂 Aktualnie ukończyłem tydzień szósty i już myślę nad tygodniem siódmym. Poniżej możecie obejrzeć moje wypociny. Galeria poniżej będzie uaktualniana w miarę postępów.

Oprócz opisu, dostępnego pod linkiem powyżej, można znaleźć w sieci kilka miejsc, gdzie ludzie wykonujący ów challenge, publikują swoje prace, pomagając sobie nawzajem. Przekrój umiejętności uczestników jest ogromny, od totalnych początkujących, do półprofesjonalistów. Jest oficjalna grupa na Facebooku, jest półoficjalna grupa na Flickr, są i inne miejsca.

 

Jack Reacher

Nadgoniłem w końcu i uzupełniłem stan przeczytania serii książek Lee Childa o Jacku Reacherze. Na tę chwilę w Polsce na serię składa się 19 tomów, ale za miesiąc ma się ukazać najnowszy, dwudziesty tom (oryginał ukazał się latem tego roku).

Zmuś mnie (Make me)

Jeśli ktoś nie czytał jeszcze (są tacy?) to proponuję zrobić to samo, co i mi poleciła zrobić moja bibliotekarka: zacząć serię od tomu ósmego (“Nieprzyjaciel”) i dopiero powrócić do tomu pierwszego (“Poziom pierwszy”). Tom ósmy to retrospekcja, w którym poznajemy również brata Reachera i jego matkę, co okazało się być dość wygodne w świetle wydarzeń tomu pierwszego.

Jak się czyta Reachera? Część powieści pisana jest w pierwszej osobie, część (większość) w trzeciej. Dziwny zabieg  . Przestrzeń czasowa między powieściami początkowo była dość duża (co najmniej kilka-kilkanaście miesięcy), później zaczęła maleć. Zapewne Lee Child zorientował się, że seria “nieco” urośnie i życia Reachera mu zabraknie w tym tempie  . Rozkręcanie akcji zazwyczaj nie przebiega zbyt długo i dość szybko wskakujemy w główny nurt wydarzeń. Trzeba też przyznać, że całość jest dość spójna – nawet w ujęciu całej serii. No, może jakoś tak bez wyraźnego powodu zniknęła z radarów postać Jodie Garber.

Poza tym, mi osobiście postać Reachera bardzo przypadła do gustu, mogę go w swoim rankingu postawić na równi z Seanem Dillonem Higginsa  . Akcja jest zawsze wartka i dość ciekawa. Czas przy lekturze spędza się miło. Z czystym sumieniem mogę polecić każdemu fanowi powieści akcji.

…nie mogło zabraknąć słowa na temat jedynej (jak dotąd) ekranizacji Reachera – Jednym strzałem. No cóż… ekranizacja ma jeden podstawowy mankament – aktora grającego postać Jack Reachera. Otóż widzicie, oryginalny Jack Reacher to gość, który ma 195 cm wzrostu, ma 127 cm w klacie i waży ponad sto kilo. Aż tu nagle… na odtwórcę wzięli… Toma Cruise’a  czyli kurdupelka (nic mu nie ujmując). Poza tym “drobnym” (nomen-omen) faktem, fabuła jest w miarę dobrze oddana, choć oczywiście nie pozbawiona sporych skrótów. Kogo bym widział bardziej w tej roli? Chyba jestem skłonny zgodzić się z Drew McWeenym, że całkiem nieźle by tu pasował nie kto inny, jak Dwayne Johnson. Niemniej, szykuje się chyba kolejna odsłona Jacka Reachera z Tomem Cruisem w roli głównej. Pożyjemy – zobaczymy!

Android – dobór koloru tekstu pod kolor tła

Gdy dodajemy tekst na jakimś tle, którego kolor ustawiany jest dynamicznie, mamy problem: jaki kolor tekstu? Czarny czy biały?

Aby rozwiązać ten problem, należy sprawdzić, jak jasny jest kolor tła. Problem w tym, że wpływ poszczególnych komponentów RGB na ogólną jasność jest różna, stąd trzeba ową jasność policzyć uwzględniając tę zasadę. Ja użyłem dość popularnej w internecie formuły – i spisuje się naprawdę dobrze.

    /**
     * Find the right color of the text, depending on the color of the background.
     * @param aColor Color, to which we're adjusting by contrast.
     * @return Black or white color.
     */
    public int getBlackOrWhite(int aColor)
    {
        int red = (aColor >> 16) & 0xFF;
        int green = (aColor >> 8) & 0xFF;
        int blue = (aColor >> 0) & 0xFF;
        int result = 0;
        if (((double)red*0.299 + (double)green*0.587 + (double)blue*0.114) > 186)
            result = Color.BLACK;
        else
            result = Color.WHITE;
        return result;
    }

Parametrem wejściowym jest kolor tła, wartość zwracana to kolor czarny lub biały. Formuła doboru wygląda na dobrą, bo spośród tych kolorów, które przetestowałem, wybór: czarny-biały zawsze był trafny, stąd mogę ją z czystym sumieniem polecić – co też czynię.

Zmiana parametrów ekranu z C++ pod Windows 7

Czasem zachodzi potrzeba zmiany ustawień monitora z poziomu aplikacji. Czasem chodzi nam o rozdzielczość, czasem o odświeżanie. Mi akurat chodziło o odświeżanie – aplikacja wyświetla materiał video w różnych formatach i potrzebowałem dostosować monitor do materiału, aby osiągnąć jak najlepszą synchronizację.

Moja aplikacja jest w Qt (a jakże), więc zaczynam od sprawdzenia, na którym monitorze jest wyświetlona moja aplikacja:

int monitor = QApplication::desktop()->screenNumber(ui.centralWidget);

Aby napisać działającą poprawnie metodę zmieniającą parametry wyświetlania pod Windows 7, musimy podać dokładną nazwę urządzenia. Podawanie NULL, która wg dokumentacji MSDN powinna zadziałać na domyślnym urządzeniu, pod Windows 7 kończy się błędem niepoprawnego parametru. Dlatego najpierw listujemy wszystkie dostępne urządzenia – i jeśli jest to nasze urządzenie, pobieramy jego aktualne ustawienia i modyfikujemy je:

DEVMODE winMode;
DISPLAY_DEVICE displayDevice;
memset(&displayDevice, 0, sizeof(DISPLAY_DEVICE));
displayDevice.cb = sizeof(displayDevice);
DWORD iDevNum = 0;
if (EnumDisplayDevices(NULL, iDevNum, &displayDevice, EDD_GET_DEVICE_INTERFACE_NAME))
{
	if (EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &winMode) != 0)
	{
		winMode.dmPelsWidth = aWidth;
		winMode.dmPelsHeight = aHeight;
		winMode.dmDisplayFrequency = aFreq;
		ChangeDisplaySettingsEx(displayDevice.DeviceName, &winMode, NULL, CDS_NORESET | CDS_UPDATEREGISTRY, NULL);
	}
}

Wg dokumentacji, po użyciu ChangeDisplaySettingsEx powinniśmy jeszcze spowodować rozesłanie komunikatu do wszystkich aplikacji, wywołując ją jeszcze raz w ten sposób:

ChangeDisplaySettings(NULL, 0);

Składając wszystko do kupy, napisałem sobie metodę, która bierze parametry ustawień (rozdzielczość i odświeżanie) i sprawdza, czy podałem wartość większą od zera (gdybym chciał ustawić tylko niektóre z tych parametrów):

//! Change display (monitor) settings. If you don't want to change any of the values, pass 0 for them.
static bool setCurrentDisplayMode(int aWidth, int aHeight, int aFreq, int aDisplay = 0);
bool sysWindowsApi::setCurrentDisplayMode(int aWidth, int aHeight, int aFreq, int aDisplay)
{
	bool ret = false;
	DEVMODE winMode;
	DISPLAY_DEVICE displayDevice;
	memset(&displayDevice, 0, sizeof(DISPLAY_DEVICE));
	displayDevice.cb = sizeof(displayDevice);
	if (EnumDisplayDevices(NULL, aDisplay, &displayDevice, EDD_GET_DEVICE_INTERFACE_NAME))
	{
		if (EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &winMode) != 0)
		{
			if (aWidth > 0) winMode.dmPelsWidth = aWidth;
			if (aHeight > 0) winMode.dmPelsHeight = aHeight;
			if (aFreq > 0) winMode.dmDisplayFrequency = aFreq;
			if (ChangeDisplaySettingsEx(displayDevice.DeviceName, &winMode, NULL, CDS_NORESET | CDS_UPDATEREGISTRY, NULL) == DISP_CHANGE_SUCCESSFUL)
			{
				ChangeDisplaySettings(NULL, 0);
				ret = true;
			}
		}
	}
	return ret;
}

Z głównej aplikacji wywołuję ją np. tak:

sysWindowsApi::setCurrentDisplayMode(0, 0, 60, QApplication::desktop()->screenNumber(ui.centralWidget));

powoduje to zmianę tylko częstotliwości odświeżania, pozostawiając rozdzielczość bez zmian – i tylko na tym monitorze, na którym znajduje się nasza aplikacja.

Bend of Joy – fraktal 3D

Dawno nic nie pisałem… postaram się to nadrobić 🙂

Przez ostatnie dwa tygodnie wieczorami pracowałem nad nową animacją – fraktalem 3D. Poniżej możecie sobie obejrzeć efekt. Dla najlepszego odbioru, przejdźcie na stronę vimeo, żeby obejrzeć ten filmik w jakości HD – oczywiście, na pełnym ekranie.

Muzyka jest autorstwa Scotta Althama.

Zawartość niedostępna.
Wyraź zgodę na używanie plików cookie.

Android – backup danych aplikacji bez roota

Ostatnio musiałem się zmierzyć z przeniesieniem danych pomiędzy dwoma telefonami Androidowymi, które nie są zrootowane. Szczerze mówiąc, nigdy tego jeszcze nie robiłem, bo w swoich urządzeniach root jest pierwszą czynnością, którą wykonuję po rozpakowaniu 😉 dlatego też postanowiłem się podzielić z wami efektami prac.

Jedyne narzędzie, którego będziesz potrzebować (poza sterownikami USB do telefonu, które powinny się automatycznie zainstalować po podłączeniu telefonu) to Android Platform Tools, którego głównym składnikiem jest Android Debug Bridge (ADB). Android Platform Tools normalnie wchodzą w skład Android SDK i stamtąd właśnie należy je pobrać, ale ktoś, kto potrzebuje jedynie wykonać kilka prostych czynności, nie musi chcieć ciągnąć tego całego bagażu. Tutaj możecie pobrać paczuszkę przygotowaną przeze mnie. Są to Platform Tools w wersji 22, czyli najnowszej na dzień dzisiejszy, obsługującej Android 5.1.

Zanim jednak będziecie mogli użyć ADB na swoim telefonie, należy włączyć ukryte menu w ustawieniach telefonu. Idziemy do Ustawienia → Informacje o urządzeniu i klikamy raz za razem pozycję Numer wersji. Po około 10 tapnięciach pokaże się komunikat, że nowe menu zostało włączone. Wracamy do Ustawień i widzimy nowe menu: Opcje programisty. Wchodzimy do środka i zaznaczamy opcję Debugowanie USB. Od tej chwili możemy używać ADB.

debug_usb

Rozpakowujemy Platform Tools do jakiegoś katalogu. Najlepiej dodać sobie ścieżkę do niego do zmiennej $PATH, żeby móc z adb korzystać z dowolnego miejsca. Sprawdzamy, czy działa:

\> adb version
Android Debug Bridge version 1.0.32

Jeśli działa, podpinamy telefon, odczekujemy, aż system zainstaluje nowe sterowniki USB (z powodu aktywacji trybu debugowania) i sprawdzamy, czy urządzenie jest widoczne:

\> adb devices
List of devices attached
10feda99 device

Sukces! Można działać 🙂

Jeśli powyżej ujrzysz kilka urządzeń na liście, wszystkie dalsze komendy musisz poprzedzić opcją -s z identyfikatorem urządenia.

Sama czynność backupu jest w zasadzie banalna. Zacznijmy od opcji backupowania jednej lub kilku wybranych aplikacji:

\> adb backup -f CatchNotes.ab -apk com.threebanana.notes com.catchnotes.sketch.samsung
Now unlock your device and confirm the backup operation.

Co tu widzimy? Zleciłem backup dwóch aplikacji (com.threebanana.notes oraz com.catchnotes.sketch.samsung) tworzących pakiet Catch Notes i plugin do niego (już niedostępne w sklepie Play – a szkoda). Backup danych wraz z samą instalką aplikacji (APK). Kopia zapasowa zostanie zapisana do pliku CatchNotes.ab. Poniżej widać, że program każe wziąć do ręki telefon.

backup

Jeśli korzystamy z szyfrowania naszych danych w telefonie, wpisujemy hasło i następnie Utwórz kopię zapasową danych. I… to tyle 🙂  na dysku zostanie utworzony plik o nazwie CatchNotes.ab, zawierający dwie instalki APK wraz z danymi obu aplikacji.

Nie wszystkie aplikacje spełniają zalecenia Androida i stosują się do jego zasad (a jakże…). Np. taka gra Temple Run 2 przechowuje swoje dane inaczej niż pozostałe aplikacje, co spowoduje, że powyższy sposób nie zachowa owych danych. Co robić? Musimy skopiować je ręcznie. Wchodzimy Eksploratorem (lub Total Commanderem, jeśli jesteśmy świadomymi użytkownikami komputera 😉 ) do telefonu i wchodzimy do katalogu Phone\Android\data. Zobaczymy tam całą masę katalogów, a wśród nich com.imangi.templerun2. Kopiujemy na komputer cały katalog. W urządzeniu docelowym musimy koniecznie najpierw zainstalować aplikację, a później nadpisać ten sam katalog naszą kopią.

templerun2_data

Oprócz kopii zapasowej wybranych aplikacji, możemy chcieć wykonać pełny backup. Mamy do dyspozycji kilka dodatkowych opcji:

  • -shared spowoduje skopiowanie wszystkich danych współdzielonych i z karty SD.
  • -all spowoduje skopiowanie wszystkich aplikacji, bez ich podawania w komendzie.
  • -system / -nosystem jeśli podaliśmy opcję -all, ta opcja decyduje, czy backupujemy tylko aplikacje użytkownika, czy również aplikacje systemowe.

Np.:

\> adb backup -apk -shared -all

Taka opcja zajmie sporo czasu i wygeneruje potężny plik.

 

Jak taką kopię zapasową później przywrócić?

\> adb restore mojakopia.ab

i… tyle 🙂

 

I tak już na końcu, jako bonus… wśród naprawdę wielu fajnych rzeczy, które można zrobić przy pomocy ADB, jest m.in. również nagrywanie ekranu (tylko na nowszych Androidach):

\> adb shell screenrecord /storage/extSdCard/test123.mp4

Video jest mocno skompresowane, ale do prezentacji jakiejś opcji czy czynności nadaje się świetnie 🙂

Strona 2 z 6

Oparte na WordPress & Theme by Anders Norén

Aby kontynuować przeglądanie tej witryny, wyraź zgodę na przechowywanie plików cookie. więcej informacji

Ta witryna używa plików cookie dla największej wygody użytkowania. Kliknij "Zaakceptuj", aby wyrazić zgodę na przechowywanie plików cookie.

Zamknij