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ę.

Facebooktwittergoogle_plusredditpinterestlinkedinmail
twitterlinkedin

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

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 > touchableArea)
	{
		// fire!
		if (x < halfX)
		{
			CgEngine.playerFireAction = CgEngine.PLAYER_FIRE_SHOOT;
			actionFiringId = actionId;
		}
		// steering
		else
		{
			if (x < 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