Počítače

Glass hackathon Brno 2014

0

Přestože jsem se spolupodílel na organizaci této akce, nebudu psát o slastech a strastech organizování, ale o tématu, které se přímo týká kódování a docela nepříjemně mě na této akci spálilo. Totiž o googlovském (dá se říci) házení klacků early adopterům a vývojářům pod nohy (hateposty dneska frčí, musím se trendu chytit!).

Spolčil jsem se s Radkem Bartoňem z Trinerdisu, protože jsem měl náladu stvořit nějaký backend, více než drátovat pro brýle. Radek přišel s nápadem čtečky ebooků ne nepodobnou Spritzu, na který mě shodou okolností nedávno odkázal jeden známý. Idea byla taková, že uživatel na telefonu vybere knížku a nechá si ji poslat do brýlí. Tudíž nějaký „push to device“. Pojďme se podívat na možnosti, které pro tuto funkcionalitu připadají v úvahu.

Glglglass

Nejjednodušší možností je využít Mirror API a intent filter. Pomocí Mirror API se pushne na timeline speciální karta, která obsahuje volání URI definované ve výše zmíněném intent filteru. Pěkný příklad použití je uveden v jedné odpovědi na Stack overflow.

Možností druhou je Google Cloud Messaging. Ten nabízí metody pushování notifikací dvě: pomocí HTTP a XMPP. HTTP volání je čistě synchronní, což vyplývá z podstaty protokolu – z mé aplikace (serveru) pošlu zprávu serverům GCM a čekám na odpověď o přijetí, což mě blokuje ve snaze odeslat zprávu další. Naproti tomu XMPP využívá GCM server jako broker, do kterého pere zprávy a odpovědi může až dodatečně (na základě id) vyhodnotit. Z toho je jasné, že pomocí HTTP je možné komunikovat pouze ve směru server->cloud->zařízení, kdežto v případě XMPP je díky držení otevřeného spojení možná obousměrná komunikace.

Protože byl na hákování vyhrazen celý den, zvolil jsem možnost b) Google Cloud Messaging a sice s využitím XMPP, abych neudělal během pěti minut servlet pro Mirror API a pak celý den jen neseděl a nekroutil palcama. Mimo jiné by potom bylo možné tento stejný přístup použít i pro mobilní aplikaci, která pushnutí iniciuje. Dokumentace je přehledná, dokonce je její součástí celý zdroják pro navázání komunikace s GCM. Existují i nějaké další poměrně detailní tutoriály. Kámen úrazu byl, že jsem (už po několikáté) přehlédnul nenápadný řádek „Note: To try out this feature, sign up using this form,“ takže jsem se nemálo divil odpovědi „Project 858xyz396 not whitelisted.“ Až po chvíli jsem daný formulář našel a zaregistroval do něj náš projekt pro hackathon. Bohužel, není to jenom robotem schvalovaná registrace, takže „lefuq“, zabil jsem spoustu času, tohle je jen pro vyvolené, až mi to někdy někdo schválí.

Po obědě jsem se pustil do GCM pomocí HTTP. Ovšem opět jsem to nedotáhl do konce, protože záhy mi Radek hlásí, že brýle nepodporují Google Play Services. To je teda fail, srsly, na co ty brejle jsou, opravdu jen na to pushování karet pomocí Mirror API? Nebo opět pouze pro vyvolené (to by mě zajímalo, kdo to je, když vývojáři zaplatili nemalé peníze za samotné pitomé brýle)?

Takže nakonec nouzovka v podobě jednoduchého REST rozhraní, kdy si brýle samy tahají seznam a odpovídající knížky. Škoda, teď by se hodil další den hackathonu, kdy bychom přidali to pushování pomocí Mirror API a k tomu appku pro telefon s tydlidrojdem (nebo tlačítko do prohlížeče – na pushnutí článku k pozdějšímu přečtení).

Poučení na závěr: důvěřuj, ale prověřuj se ve spojitosti s Googlem mění na: nedůvěřuj, ale prověř, neuvěř a radši to udělej jinak. Každopádně aspoň nějakým výstupem je zdroják k „serveru“ na GitHubu a běžící endpoint na OpenShiftu. Tak alespoň něco, mimo akce samotné a následných škopků.

Custom filesystem receiver for Alfresco

0

It’s really a long time since my last Alfresco post on this blog. And because of that I’d like to announce my comeback to Alfresco developing, because the year with mainly Android coding was long enough. Before that I’ve been working on content publisher for custom CMS based on Alfresco repository, which was able to publish through NATed networks.

My solution is based on Broker, which provides communication between publisher and endpoints, which both may be behind NAT. Each endpoint is subscribed to queue on broker and when request for publish comes, it locally compares published version and if published is newer, it sends request for content and content is transfered. Depublishing works the same way, data consistency is secured by ‚sync‘ mechanism – endpoint may send local file list to publisher, which checks its integrity and do appropriate actions.

Publisher/endpoint scheme

Publisher/endpoint scheme

First version was based on RabbitMQ and HSQLDB and had a lot of performance and security issues, but as I said – I’d like to resurrect it now, rewrite and open source it. I just need to be sure that there is no such a project, because I don’t want to do the same thing. If anyone knows similar stuff, please let me know!

Howto access recent query suggestions on Android and populate ListView with them

0

I’m working on search activity for Beermapa and because I did not find any topic covering reading access to SearchRecentSuggestions and I needed to load saved suggestions and fill a ListView with them, so I did some research and wrote this post.

What I want to achieve is an input for writing search query, which displays custom suggestions (based on searching query) and also ListView placed right under input box, which displays recent search queries.

SearchView with ListView

SearchView with ListView

My first try was with EditText and TextWatcher, which after each written character filtered my listAdapter backing ListView, something like this:

searchEditText.addTextChangedListener(new TextWatcher() {
    public void afterTextChanged(Editable s) {}

    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

    public void onTextChanged(CharSequence s, int start, int before, int count) {
        adapter.getFilter().filter(s);
    }
});

But since Android has pretty good Search Interface, I was wondering how to use it with my search (because of possible future use of voice search etc.). Adding recent query suggestion is described in tutorial, also custom suggestion is. But there is nothing about how to access saved queries another way then in SearchView whispering box. Saving is really easy:

SearchRecentSuggestions suggestions = new SearchRecentSuggestions(getApplicationContext(), MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE);

suggestions.saveRecentQuery(query, null);

First solution which came on my mind was to implement own saveRecentQuery routine, which saves last queries to local database, but that’s not the way – why to write already written code again?

Finally – there is possibility to access those saved queries through ContentResolver, which returns Cursor:

ContentResolver contentResolver = getApplicationContext().getContentResolver();

String contentUri = "content://" + MySuggestionProvider.AUTHORITY + '/' + SearchManager.SUGGEST_URI_PATH_QUERY;
Uri uri = Uri.parse(uriStr);

Cursor cursor = contentResolver.query(uri, null, null, new String[] { query }, null);

Where query is String representing searching query, or null for returning all records. Now with received cursor it’s simple to populate ListView:

cursor.moveToFirst();

String[] columns = new String[] { SearchManager.SUGGEST_COLUMN_TEXT_1 };
int[] views = new int[] { R.id.name };

ListAdapter listAdapter = new SimpleCursorAdapter(this, R.layout.component_pub_row, cursor, columns, views, 0);
listView.setAdapter(listAdapter);

Note that last parameter in SimpleCursorAdapter – it’s there because of deprecation of constructor with FLAG_AUTO_REQUERY, for more details see this Stack Overflow topic.

Vanitygen a import adresy do Bitcoin-QT na MacOS

8

Dlouho jsem nic nenapsal a protože jsem si právě vygeneroval novou krásnou (1SHM12iG4KPRs54CxjLsCwbvnMJp4bMh5) Bitcoinovou adresu (jo, mohlo to být lepší, ale není na to výkon) na Mackovi za pomocí Vanitygenu, poznamenám si tu postup.

Zdrojáky Vanitygenu je možné stáhnout z GitHubu, kde by měl být i Makefile pro Macka. Problém je v tom, že Macek má staré verze OpenSSL knihoven (na mém 10.7.5 je OpenSSL 0.9.8x 10 May 2012), takže je nutné použít ty z Homebrew. No a protože není dobrý nápad natvrdo zadávat cestu ke knihovnám a po změně kompilovat znovu, proč si pohodlně netapnout repozitář s Vanitigenem rovnou? Takže i s instalací OpenSSL a Vanitigenu následovně:

bash-3.2$ brew install openssl && brew tap WyseNynja/bitcoin && brew install vanitygen

Teď už je možné si nechat vygenerovat adresu a privátní klíč:

bash-3.2$vanitygen 1SHM1

Závěrečným krokem je import privátního klíče do peněženky – používám Bitcoin-QT 0.8.2. Takový nástřel je na bitcoin wiki, kterou doporučuju před akcí projít. Akce samotná sestává z následujících kroků:

  • spuštění Bitcoin-QT v režimu serveru (kdy naslouchá RPC na portu 8332),
  • odemknutí peněženky na dobu nezbytně nutnou k provedení importu,
  • provedení importu soukromého klíče,
  • …,
  • profit.

Aby bylo možné spustit Bitcoin-QT v režimu serveru, je nutné nastavit heslo pro uživatele rpcuser. Provede se to přidáním dvou řádků do konfiguračního souboru ~/Library/Application Support/Bitcoin/bitcoin.conf.

rpcuser=bitcoinrpc

rpcpassword=***************

Bitcoin-QT je nutné spustit v režimu serveru – provede se tak v konzoli pomocí příkazu

bash-3.2$ open Bitcoin-Qt.app --args -server

Jakmile naběhne, je možné posílat příkazy na port 8332 – např. pomocí curl. Protože se však takto budou zapisovat hesla a privátní klíče přímo do konzole, je vhodné zapisované příkazy potlačit v historii – před příkaz se do konzole přidá mezera. Sled příkazů je následující:

bash-3.2$ curl --user bitcoinrpc --data-binary '{"method": "walletpassphrase", "params": ["heslo_do_penezenky", 120] }' http://127.0.0.1:8332/
Enter host password for user 'bitcoinrpc':
{"result":null,"error":null,"id":null}
bash-3.2$  curl --user bitcoinrpc --data-binary '{"method": "importprivkey", "params": ["5_privatni_klic_pr_nove_vytvorenou_adresu_pomoci_vanitigenu", "popisek adresy"] }' http://127.0.0.1:8332/
Enter host password for user 'bitcoinrpc':
{"result":null,"error":null,"id":null}

První příkaz odemkne peněženku na 120s, což by mělo pro provedení druhého příkazu postačovat – stačí jen jeho iniciace, rescan blockchainu může probíhat až po opětovném (automatickém) locknutí.

V tento okamžik (až doběhne import) se nová adresa objeví v adresáři, ne mezi adresami pro příjem. Tomu napomůže ukončení Bitcoin-QT a opětovné spuštění, tentokrát už jako „obyčejné“ aplikace.

Jak si (zase) nabíjím hubu

0

Už jsem psal o tom, co jsem udělal špatně u minulého projektu a protože mám rozjetý další, tak vidím, že je spousta věcí, které opět tak nějak dělám špatně. No a protože chybama se člověk učí, tak se (aspoň s těma nejzásadnějšíma) pochlubím a budu doufat, že třeba pomůžou i někomu dalšímu, aby se jich vyvaroval. Ale známe to – každý si musí nejprve nabít hubu… 🙂 Jedná se o Androidí aplikaci Zasaď strom, ale myslím, že to jsou docela obecné věci, které se dají promítnout kamkoliv jinam. Nuže, pojďme na ně!

 

Drbání se s detaily

Aplikace je celá postavená na geolokaci, takže jsem si řekl, že když už, tak to udělám pořádně. Takže jsem několik dnů vytvářel a testoval sofistikovaný systém, který nežere moc baterku a snaží se co nejpřesnějším možným způsobem zjistit polohu uživatele. Pak jsem to pustil ven a zjistil, že je to celé úplně na ho*no – polovině uživatelů to blbne a ta druhá polovina nechápe, proč se to chová tak divně. Takže opět další čas zabitý měněním parametrů, dalším laděním… STOP! Všechno jsem vyházel a použil naprosto základní možnost zjištění polohy nabízený systémem – přece jenom to baterku zase tak nežere a já přece nebudu zabíjet veškerý čas laděním něčeho, o čem si ani nejsem jistý, jestli vůbec bude v takové složitosti potřeba – to ukáže až čas a způsob používání!

 

Neudržení se v rámci hranic nejmenší možné verze produktu (MVP)

Sice jsem si definoval, jak bude vypadat Minimum Viable Product, ale přesto jsem se neudržel a ještě než je hotový, pořád mi tam prosakují plánované gamifikační featury (ovšem z mnohem vyššího levelu – ne ty základní – a to jenom proto, že „teď by to bylo jednoduché implementovat“). Důsledkem je, že věci, které by měly být, stále nejsou, pořád v tom něco blbne a uživatelé (a často i já) jsou zmatení z nekompletních funkcí. STOP! Doladím základní plánovanou funkcionalitu a potom začnu postupně přidávat další věci – od těch nejjednodušších – časem se uvidí, jestli si uživatelé sami o něco neřeknou!

 

Snaha stále udržet zpětnou kompatibilitu

Spoustu času jsem věnoval hackování zpětné kompatibility. ActionBar je v Androidu od jisté verze a výš, Fragmenty taky existují od určité verze nahoru… Takže (dle obecných doporučení milovaného Gogolu) jsem ošetřoval, aby vše běželo i na prehistorických verzích systému. STOP! Na to se už příště můžu…!! Když jsem aplikaci zveřejnil, tak ty prastaré verze nemá jediný uživatel! A i kdyby – prostě vyvíjím aplikaci a mám nějaké minimální požadavky pro její běh – vždyť je to přece naprosto normální! Jednoduše to napíšu, jak je dneska v módě (jako prase) a až pokud zjistím, že je nemalé procento uživatelů nějaké starší verze systému a mají o aplikaci taky zájem, tak začnu přemýšlet o zpětné kompatibilitě.

Go to Top