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 🙂

Facebooktwittergoogle_plusredditpinterestlinkedinmail
twitterlinkedin

Qt 5.3.2 vs GCC 4.8.1 TDM64

Kolejna wersja Qt, kolejna kompilacja… tym razem budujemy Qt 5.3.2 pod GCC pod Windows, w wydaniu TDM64.

Najpierw – konfiguracja. Ja stworzyłem sobie plik configure.cmd:

cd Qt-5.3.2-gcc-x86_64

set PATH_GCC=C:\gcc\gcc-4.8.1-tdm64
set PATH_PERL=C:\Perl
set PATH_PYTHON=C:\Python27
set PATH_ICU=D:\devel\Qt\Qt5_deps\icu
set PATH_OPENSSL=D:\devel\Qt\Qt5_deps\openssl-1.0.1e

set INCLUDE=%PATH_ICU%\dist\include;%PATH_OPENSSL%\dist\include
set LIB=%PATH_ICU%\dist\lib;%PATH_OPENSSL%\dist\lib
set QMAKESPEC=
set QTDIR=

set PATH=%CD%\qtbase\bin;%CD%\gnuwin32\bin;%PATH_GCC%\bin;%PATH_PERL%\bin;%PATH_PYTHON%;%PATH_ICU%\dist\lib;%PATH_OPENSSL%\dist\bin;%SystemRoot%\System32
set MAKE_COMMAND=

configure -release -opensource -confirm-license -platform win32-g++ -developer-build -c++11 -opengl desktop -plugin-sql-odbc -qt-style-windowsxp -qt-style-windowsvista -nomake tests -nomake examples -skip qtwebkit -skip qtwebkit-examples -skip qtquick1

i uruchamiam.
Jeśli wszystko przebiegło pomyślnie, pozostało nam wykonać jeszcze jeden szybki fix. Będzie to fix nieelegancki i tylko na potrzeby naszej kompilacji, bez zagłębiania się w prawidłowe rozwiązanie, które zadziała z każdym kompilatorem.

Odnajdujemy plik qtwinextras\src\winextras\winshobjidl_p.h i na samym końcu usuwamy sekcję:

#if (defined _MSC_VER && _MSC_VER < 1600) || defined(Q_CC_MINGW)

#   if !defined(__MINGW64_VERSION_MAJOR) || !defined(__MINGW64_VERSION_MINOR) || __MINGW64_VERSION_MAJOR * 100 + __MINGW64_VERSION_MINOR < 301

typedef struct SHARDAPPIDINFOLINK
{
    IShellLink *psl;        // An IShellLink instance that when launched opens a recently used item in the specified
                            // application. This link is not added to the recent docs folder, but will be added to the
                            // specified application's destination list.
    PCWSTR pszAppID;        // The id of the application that should be associated with this recent doc.
} SHARDAPPIDINFOLINK;

#   endif // !defined(__MINGW64_VERSION_MAJOR) || !defined(__MINGW64_VERSION_MINOR) || __MINGW64_VERSION_MAJOR * 100 + __MINGW64_VERSION_MINOR < 301

#endif

Usuwamy tę sekcję całkowicie. Plik zapisujemy, wracamy do głównego katalogu i zaczynamy budowanie:

mingw32-make

Zbudowane binarki będą, jak zwykle, w katalogu qtbase\bin.

Facebooktwittergoogle_plusredditpinterestlinkedinmail
twitterlinkedin

Seria Millenium Stiega Larssona

Znajoma podrzuciła mi (dzięki, Aga!) do przeczytania coś, co mnie jakoś ominęło wcześniej – serię Millenium Stiega Larssona (zmarłego w 2004 roku). To trylogia kryminalna, mieszcząca się na prawie dwu tysiącach stron.

Autor, sam będący dziennikarzem, opowiada historię splatającą losy dociekliwego dziennikarza finansowego i dziewczyny, której osobowość stanowi jeden z głównych kluczy do sukcesu tej powieści. To skomplikowana dziewczyna, doświadczona przez los, a przy tym świetna hakerka, obdarzona pamięcią fotograficzną.

W pierwszej części bohaterowie się spotykają (nie tak znów szybko) i wspólnie rozwiązują pewną starą zagadkę. W tomie drugim i trzecim, zajmują się sprawami bezpośrednio dotyczącymi Lisbeth i tropią niebywałą aferę na najwyższym szczeblu władzy w Szwecji.

Na podstawie tomu pierwszego nakręcono film, w którym Mikaela Blomkvista zagrał Daniel Craig, a w rolę Lisbeth Salander wcieliła się Rooney Mara. Ten film to Dziewczyna z tatuażem, który zapewne już widzieliście.

Te dwa tysiące stron przemknęło bardzo szybko w kilka dni. Muszę przyznać, że pióro Stieg Larsson miał naprawdę świetne i ani przez chwilę się powieść nie nuży. Polecam! 🙂

Facebooktwittergoogle_plusredditpinterestlinkedinmail
twitterlinkedin

S.T.A.L.K.E.R.: Lost Alpha 1.3002 już jest!

Dziś na świat przyszedł długo oczekiwany wielki patch do gry S.T.A.L.K.E.R.: Lost Alpha produkcji grupy dez0wave, której mam zaszczyt być członkiem (jako programista, oczywiście 😉 ).
Patch nosi numer 1.3002 i jest patchem kumulatywnym, co oznacza, że można go instalować bezpośrednio na gołą grę, bez konieczności wcześniejszej instalacji poprzedniego patcha 1.30013.

Co przynosi nowa wersja?
Przede wszystkim całą masę poprawek błędów (których, nie ukrywajmy, było sporo – z przyczyn większości zainteresowanym wiadomych), a także dość długą listę usprawnień i dodatków. Po szczegółową listę zmian zapraszam tutaj lub tutaj. Sam patch pobrać można tutaj.

Pozostaje mi życzyć wam fascynującej przygody w nowej Zonie – a ja tymczasem udaję się na zasłużony urlop w góry 😉 Do zobaczenia!

Facebooktwittergoogle_plusredditpinterestlinkedinmail
twitterlinkedin

MEncoder – odwracanie video

W moim telefonie mam funkcję nagrywania filmów w podwyższonych fps (czyli krótko mówiąc: slow-motion). Oglądając dzisiaj jeden z takich filmików zapragnąłem zobaczyć go od tyłu. I… pojawił się problem – jak to, do diabła, zrobić szybko i wygodnie? No i – oczywiście – używając tylko darmowych narzędzi? Jak zwykle, skorzystałem z mencodera, ale tym razem w połączeniu z mplayerem i tworząc cały skrypt, gdyż cały proces jest kilkustopniowy. Zatem – do dzieła!

Pierwszą czynnością, jaką musimy wykonać, jest rozbiórka naszego video do pojedynczych klatek. Użyjemy do tego mplayera:

mplayer -vo png:outdir=klatki video.avi

W efekcie otrzymamy katalog klatki, a w nim pliki png z poszczególnymi klatkami z całego video. Zanim przekujemy je w video, musimy przygotować listę plików – w kolejności odwróconej. Z pomocą przyjdzie nam zwykła komenda dir:

dir klatki /b /s /o-n >> klatki.txt

W pliku zapisane zostaną pliki wraz z pełnymi ścieżkami, w porządku alfabetycznym malejącym. Taki plik może już posłużyć nam do zakodowania naszego nowego video:

mencoder mf://@klatki.txt -mf fps=30:type=png -ovc x264 .... itd.

Ja, w celu wygodnego używania, napisałem sobie mały skrypt, który przyjmuje jeden lub dwa parametry. Pierwszy, to oczywiście nazwa pliku video do obrobienia, a drugi, to docelowy fps. Jeśli drugiego parametru nie podamy, zostanie użyta wartość 30 klatek na sekundę. Na końcu, skrypt sprząta po sobie 🙂 Życzę miłego używania!

set MPLAYER="C:\Program Files (x86)\mplayer\mplayer.exe"
set MENCODER="C:\Program Files (x86)\mplayer\mencoder.exe"

mkdir %1.images
%MPLAYER% -vo png:outdir=%1.images %1
dir %1.images /b /s /o-n >> %1.frames.txt

set H264_FAST=-ovc x264 -x264encopts subq=4:bframes=2:b_pyramid=normal:weight_b
set H264_HIGH=-ovc x264 -x264encopts subq=5:8x8dct:frameref=2:bframes=3:b_pyramid=normal:weight_b
set H264_VHIGH=-ovc x264 -x264encopts subq=6:partitions=all:8x8dct:me=umh:frameref=5:bframes=3:b_pyramid=normal:weight_b
set FPS=%2
if [%2] == [] set FPS=30

%MENCODER% mf://@%1.frames.txt -mf fps=%FPS%:type=png %H264_HIGH% -nosound -o %1.reversed.avi
rd /s /q %1.images
del %1.frames.txt
Facebooktwittergoogle_plusredditpinterestlinkedinmail
twitterlinkedin

Wojny wsadowe – jesteś pewien?

Tym razem zajmiemy się wyświetlaniem okna komunikatu z poziomu skryptu powłoki Windows. Oknu możemy nadać te klawisze, które chcemy, np. Ok, Yes i No, czy jakikolwiek inny zestaw, a także na wyjściu sprawdzić, co user ewentualnie wybrał (jeśli jakiś wybór mu daliśmy 😉 ).

Jeśli chcemy użyć pełnego wachlarza możliwości, stwierdziłem, że najmniejszą linią oporu będzie posłużenie się skryptem VisualBasic i jego funkcją MsgBox, np.:

MsgBox("Are you sure you want to do this??",4,"Haha!")

Pierwszy parametr to treść komunikatu, trzeci to tytuł okna. Drugi parametr, to zestaw przycisków, które mają być udostępnione użytkownikowi do wyboru. Możliwości są następujące:

0 Tylko przycisk OK
1 OK i Cancel
2 Abort, Retry i Ignore
3 Yes, No i Cancel
4 Yes i No
5 Retry i Cancel
16 Użyj ikonki Critical Message
32 Użyj ikonki Warning Query
48 Użyj ikonki Warning Message
64 Użyj ikonki Information Message
0 Pierwszy przycisk jest domyślny
256 Drugi przycisk jest domyślny
512 Trzeci przycisk jest domyślny
768 Czwarty przycisk jest domyślny

Jak widać, mamy tu dostępne trzy grupy. Wybieramy pożądane opcje i sumujemy je, np. chcąc wyświetlić klawisze „Yes” i „No”, dodać ikonkę „Warning Query” i uczynić przycisk „No” domyślnie zaznaczonym, użyjemy wartości 4+32+256:

MsgBox("Are you sure you want to do this??",4+32+256,"Haha!")

Oczywiście, nic nie stoi na przeszkodzie, aby wpisać tam po prostu 292, ale dla późniejszej analizy i edycji, łatwiej pozostawić to w takiej czytelnej postaci.

Skrypt VBS skryptem VBS, ale my chcemy wywołać nasze okienko z regularnego skryptu wsadowego… uciekniemy się do małego tricku i… stworzymy tymczasowy plik vbs i go wywołamy 😉

echo MsgBox("Are you sure you want to do this??",4+32+256,"Haha!") >tempmsg.vbs
call tempmsg.vbs

Tu pojawia się kolejny problem: jak sprawdzić, co wybrał użytkownik? Najpierw, zmusimy nasz skrypt VBS do zwracania na swoim wyjściu wynik funkcji MsgBox – czyli właśnie wybór użytkownika. Robimy to tak:

wscript.quit MsgBox("Are you sure you want to do this??",4+32+256,"Haha!")

Dzięki temu, cały skrypt na swoim wyjściu zwróci wartość wg klucza:

1 OK
2 Cancel
3 Abort
4 Retry
5 Ignore
6 Yes
7 No

W naszym pierwotnym skrypcie, po wywołaniu skryptu VBS, musimy sprawdzić wartość zmiennej %errorlevel%, która wskazuje właśnie na wynik ostatnio wykonanej komendy.

echo wscript.quit MsgBox("Are you sure you want to do this??",4+32+256,"Haha!") >tempmsg.vbs
call tempmsg.vbs
if %errorlevel% NEQ 6 goto finish

echo Jest! Zgodził się! Hurrra!!
echo Tutaj rozkręcamy imprezkę...

:finish
del tempmsg.vbs

Prawda, że proste? 🙂

Facebooktwittergoogle_plusredditpinterestlinkedinmail
twitterlinkedin

Fullscreen widget w Qt4

Stworzenie widgeta pełnoekranowego w Qt4 niby jest proste, ale… okazuje się, że po drodze czyha na nas kilka pułapek. Postaram się was przez nie przeprowadzić…

W moim przypadku, mam aplikację, która wyświetla strumień video (akurat ze specjalnej karty, ale to kompletnie nieważne – może Ty chcesz oglądać np. film z pliku). Idąc za niepisanym standardem, postanowiłem opcję przejścia do fullscreen położyć na klawiszu <F11>.

QAction *theFullscreenAction = new QAction(this);
theFullscreenAction->setShortcut(QKeySequence(Qt::Key_F11));
theFullscreenAction->setCheckable(true);
connect(theFullscreenAction, SIGNAL(toggled(bool)), this, SLOT(toggleFullscreen(bool)));
addAction(theFullscreenAction);

Aby przełączyć widget, trzeba zapamiętać kilka jego właściwości, aby było do czego wracać a następnie go przełączyć. Przy powrocie, oczywiście należy odtworzyć wszystkie właściwości.

QWidget *videoFrameParent;
QLayout *videoFrameParentLayout;
Qt::WindowFlags videoFrameFlags;
QSize videoFrameSize;
void myApp::toggleFullscreen(bool bFullscreen)
	{
	if (bFullscreen)
		{
		videoFrameParent = ui.videoFrame->parentWidget();
		videoFrameParentLayout = ui.videoFrame->parentWidget()-&gt;layout();
		videoFrameFlags = ui.videoFrame->windowFlags();
		videoFrameSize = ui.videoFrame->size();

		// untie it...
		ui.videoFrame->setParent(NULL);
		ui.videoFrame->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
		ui.videoFrame->showMaximized();
		}
	else
		{
		// bring it back!
		ui.videoFrame->resize(videoFrameSize);
		ui.videoFrame->overrideWindowFlags(videoFrameFlags);
		ui.videoFrame->setParent(videoFrameParent);
		videoFrameParentLayout>addWidget(ui.videoFrame);
		ui.videoFrame->show();
		}
	}

Odpalamy aplikację i testujemy… pierwsze, co się rzuca, to nie działa klawisz powrotu. Chwila zabawy i – działa, ale trzeba Alt-Tabem przejść do osieroconego okna aplikacji głównej. Rozwiązanie jest dość proste: wystarczy naszą akcję dodać również do naszego widgetu. Dlaczego? Dlatego, że po jego wydziedziczeniu (setParent(NULL);) aplikacja główna przestaje otrzymywać zdarzenia klawiatury, gdy nasz widget ma fokus.

ui.videoFrame->addAction(theFullscreenAction);

Kolejny problem objawia się w momencie, gdy mamy konfigurację wielomonitorową i wywołamy akcję w momencie, gdy aplikacja będzie na monitorze innym, niż główny. Okaże się, że nasz fullscreen włączy się na ekranie głównym, pozostawiając osieroconą i ogołoconą aplikację główną tam, gdzie była.

Tu niestety musimy kilka linijek kodu spędzić na rozwiązanie tego problemu… sprawdzimy najpierw, gdzie nasza aplikacja się znajduje, a następnie (po wydziedziczeniu!) przesuniemy okno tam ręcznie, po czym dopiero uruchomimy showMaximized().

// untie it...
ui.videoFrame->setParent(NULL);
ui.videoFrame->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);

// hack for showing it on a screen, where the app is (in a multimonitor setup)
QDesktopWidget *dw = QApplication::desktop();
QRect drect = dw->screenGeometry(dw->screenNumber(QCursor::pos()));
int desk_x = drect.width();
int desk_y = drect.height();
int x = ui.videoFrame->width();
int y = ui.videoFrame->height();
ui.videoFrame->move(desk_x / 2 - x / 2 + drect.left(), desk_y / 2 - y / 2 + drect.top());

// yeah!
ui.videoFrame->showMaximized();

Kolejny test i… działa! 🙂 Poniżej kod w komplecie:

QWidget *videoFrameParent;
QLayout *videoFrameParentLayout;
Qt::WindowFlags videoFrameFlags;
QSize videoFrameSize;
QAction *theFullscreenAction = new QAction(this);
theFullscreenAction->setShortcut(QKeySequence(Qt::Key_F11));
theFullscreenAction->setCheckable(true);
connect(theFullscreenAction, SIGNAL(toggled(bool)), this, SLOT(toggleFullscreen(bool)));
addAction(theFullscreenAction);
ui.videoFrame->addAction(theFullscreenAction);
void myApp::toggleFullscreen(bool bFullscreen)
	{
	if (bFullscreen)
		{
		videoFrameParent = ui.videoFrame->parentWidget();
		videoFrameParentLayout = ui.videoFrame->parentWidget()->layout();
		videoFrameFlags = ui.videoFrame->windowFlags();
		videoFrameSize = ui.videoFrame->size();

		// untie it...
		ui.videoFrame->setParent(NULL);
		ui.videoFrame->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);

		// hack for showing it on a screen, where the app is (in a multimonitor setup)
		QDesktopWidget *dw = QApplication::desktop();
		QRect drect = dw->screenGeometry(dw->screenNumber(QCursor::pos()));
		int desk_x = drect.width();
		int desk_y = drect.height();
		int x = ui.videoFrame->width();
		int y = ui.videoFrame->height();
		ui.videoFrame->move(desk_x / 2 - x / 2 + drect.left(), desk_y / 2 - y / 2 + drect.top());

		// yeah!
		ui.videoFrame->showMaximized();
		}
	else
		{
		// bring it back!
		ui.videoFrame->resize(videoFrameSize);
		ui.videoFrame->overrideWindowFlags(videoFrameFlags);
		ui.videoFrame->setParent(videoFrameParent);
		videoFrameParentLayout->addWidget(ui.videoFrame);
		ui.videoFrame->show();
		}
	}

Miłego oglądania! 😉

Facebooktwittergoogle_plusredditpinterestlinkedinmail
twitterlinkedin

Android: pełna obsługa multitouch w grze

Dodać do programu (gry) obsługę dotyku pod Androidem jest niezmiernie prosto. Wystarczy kilka linijek kodu:

 

@Override
public boolean onTouchEvent(MotionEvent event)
{
	float x = event.getX();
	float y = event.getY();

	switch (event.getAction())
	{
	case MotionEvent.ACTION_DOWN:
		processTouchDown(x, y);
		break;
	case MotionEvent.ACTION_UP:
		processTouchUp(x, y);
		break;
	}		
	return false;
}

 

Schody zaczynają się w momencie, gdy chcemy zrobić np. pełne sterowanie postacią – a jego ramach np. ruch oraz strzelanie. Już przy pierwszym teście dochodzimy do wniosku, że chcemy obsługiwać wiele palców naraz, niezależnych od siebie.

 

Z pomocą przychodzi nam mechanizm dodany w API Level 8, czyli od Androida 2.2.x Froyo. Każdy event dotyku zawiera w sobie pełną informację o wszystkich ewentualnych punktach nacisku, ich pozycji itd. Dlatego, naszą obsługę zdarzeń rozwiniemy tak:

 

private int actionMovementId = -1;
private int actionFiringId = -1;

 

@Override
public boolean onTouchEvent(MotionEvent event)
{
	int actionId = event.getActionIndex();
	float x = event.getX(actionId);
	float y = event.getY(actionId);

	switch (event.getActionMasked())
	{
	case MotionEvent.ACTION_DOWN:
	case MotionEvent.ACTION_POINTER_DOWN:
		processTouchDown(x, y, actionId);
		break;
	case MotionEvent.ACTION_UP:
	case MotionEvent.ACTION_POINTER_UP:
		processTouchUp(x, y, actionId);
		break;
	}

	return false;
}

 

private void processTouchDown(float x, float y, int actionId)
{
	Point displaySize = new Point(CgEngine.display.getWidth(), CgEngine.display.getHeight());
	int touchableArea = displaySize.y * 3 / 4;
	int halfX = displaySize.x / 2;

	if (y &gt; touchableArea)
	{
		// fire!
		if (x &lt; halfX)
		{
			CgEngine.playerFireAction = CgEngine.PLAYER_FIRE_SHOOT;
			actionFiringId = actionId;
		}
		// steering
		else
		{
			if (x &lt; halfX * 1.5)
				CgEngine.playerRunAction = CgEngine.PLAYER_TURN_LEFT_1;
			else
				CgEngine.playerRunAction = CgEngine.PLAYER_TURN_RIGHT_1;

			actionMovementId = actionId;
		}
	}
}

 

private void processTouchUp(float x, float y, int actionId)
{
	if (actionFiringId == actionId)
	{
		CgEngine.playerFireAction = CgEngine.PLAYER_FIRE_HOLD;
		actionFiringId = -1;
	}
	if (actionMovementId == actionId)
	{
		CgEngine.playerRunAction = CgEngine.PLAYER_RELEASE;
		actionMovementId = -1;
	}
}

 

Jak widać, przy rozpoczynaniu każdej akcji, musimy zapamiętać identyfikator palca, który ją uruchomił – później, gdy przyjdzie event puszczenia palca, będzie można łatwo zidentyfikować, która akcja powinna się zakończyć.

 

Powodzenia!

 

Facebooktwittergoogle_plusredditpinterestlinkedinmail
twitterlinkedin

MEncoder – tips&tricks

Od lat używam mencodera – a jednak wciąż potrafi zaskakiwać i zmuszać do ruszania głową… 😉 dlatego postanowiłem zgromadzić w jednym miejscu garść porad (również dla samego siebie).

 

Kodowanie H.264 szybkie:

-ovc x264 -x264encopts subq=4:bframes=2:b_pyramid=normal:weight_b

 

Kodowanie H.264 wysoka jakość:

-ovc x264 -x264encopts subq=5:8x8dct:frameref=2:bframes=3:b_pyramid=normal:weight_b

 

Kodowanie H.264 bardzo wysoka jakość:

-ovc x264 -x264encopts subq=6:partitions=all:8x8dct:me=umh:frameref=5:bframes=3:b_pyramid=normal:weight_

 

Zmiana prędkości poprzez zmianę framerate’u:

-speed 8

Trzeba zauważyć, że ten efekt jest raczej słaby i niewiele jest prawdziwych zastosowań dla niego…

 

Zmiana prędkości poprzez odrzucenie ramek (tu 8x):

-fps 240 -ofps 30

A tu mała sztuczka, pozwalająca na prawdziwe przyśpieszenie filmu 🙂 MEncoder przy takiej konstrukcji zacznie odrzucać zbędne ramki.

 

Odwrócenie filmu do góry nogami (np. w nagraniu z telefonu):

-vf flip,mirror

 

Odwrócenie filmu w prawo:

-vf rotate=1

Odwrócenie filmu w lewo:

-vf rotate=2

 

Bez dźwięku:

-nosound

Podłożenie zewnętrznej ścieżki audio:

-audiofile sciezka.mp3 -oac mp3lame -lameopts mode=2:cbr:br=128:vol=0

Kodowanie MP3:

-oac mp3lame -lameopts mode=2:cbr:br=128:vol=0

Zrzut pliku MP3 z filmu:

mencoder film.avi -oac copy -of rawaudio -ovc copy -o sameaudio.mp3

 

Przycięcie filmu:

-ss 0:00:35 -endpos 0:07:47

Połączenie kilku plików:

mencoder plik1.mp4 plik2.mp4 plik3.mp4 -ovc copy -oac pcm -o joined.mp4

 

 

I na koniec mały przykład, który właśnie przed chwilą uskuteczniałem: odwrócenie filmu do góry nogami, 8-krotne przyśpieszenie, podłożenie ścieżki audio z MP3 i kodowanie całości do H.264:

mencoder filmik.mp4 -vf flip,mirror -ovc x264 -x264encopts subq=5:8x8dct:frameref=2:bframes=3:b_pyramid=normal:weight_b -fps 240 -ofps 30 -audiofile muza.mp3 -oac mp3lame -lameopts mode=2:cbr:br=128:vol=0 -o final_video.mp4

 

Miłego kodowania! 🙂

Facebooktwittergoogle_plusredditpinterestlinkedinmail
twitterlinkedin