piątek, sierpnia 13, 2010

Android - nawet platofrma potrafi przeciwko Tobie knuć ;-)

Wrzuciłem już Bloggeroida do Android Market i okazało się, że część użytkowników ma problem z obrazkami, dużymi obrazkami.

Problem mógł występować w 2 miejscach, w trakcie uploadowania dużych obrazków do Picasa'y i w momencie przeglądania obrazków w "menadżerze obrazków".

W obu przypadkach wylatywały błędy "OutOfMemoryError: bitmap size exceeds vm budget".

W przypadku uploadowania obrazków problem był w tym, że chcąc sobie ułatwić obrazek przerzucałem najpierw do strumienia w pamięci, niestety oznaczało to problemy z dużymi obrazkami. Na G1 problemy pojawiały się przy obrazkach mających 4-6 MB, wcześniej tego nie zauważyłem bo G1 ze swoim aparatem 3.2 megapiksela po prostu nie produkuje tak dużych zdjęć :-)
Tego strumienia pamięciowego (dokładniej ByteArrayOutputStream) używałem bo mogłem łatwo pobrać rozmiar obrazka co było mi potrzebne do ustawianie nagłówka Content-Lenght.
No to wyeliminowałem użycie ByteArrayOutputStream i szczęśliwy, że mi tak szybko poszło odpaliłem program na G1...... i znów się wywalił :-)
Okazuje się, że Android robi dokładnie taki sam numer jak ja i wykorzystuje ByteArrayOutputStream, przez co nadal do uploadowania każdy z obrazków był wrzucany do pamięci, tym razem jednak nie przez mój kod, a przez kod Androida i efektem był ten sam błąd :-)
Rozwiązaniem okazało się użycie trybu chunked w połączeniu HTTP.

Stąd lekcja, jeżeli na Androidzie masz zamiar wrzucać duże ilości danych przez HTTP to najlepiej rób to w trybie chunked, wystarczy na obiekcie typu HttpURLConnection wywołać metodę setChunkedStreamingMode(int) z wielkością "kawałka".

Drugi problem widoczny był w "menadżerze obrazków". Tutaj błąd leciał od razu z Androida, a dokładniej z BitmapFactory.decodeStream(InputStream), używanego do stworzenia bitmapy, z której powstać miała ikonka.
Poczytałem po sieci i okazało się, że tu dobrze jest użyć pewnej sztuczki, polegającej na wywołaniu metody BitmapFactory.decodeStream(InputStream,Rec,BitmapFactory.Options).
Kod wygląda teraz tak:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inTempStorage = new byte[16*1024];
options.inSampleSize=4;
Bitmap bitmap = BitmapFactory.decodeStream(is, null,options);


Najważniejsze wydaje się być to inSampleSize=4, które powoduje, że Android dekoduje obrazek do wymiarów 1/4 oryginału [czyli ma on 16 razy mniej pikseli niż oryginał].

No i proszę, człowiek się uczy całe życie :-)


Podobne postybeta
Wredne Google Docs
Chyba najtrudniejszy komponent UI - pasek postępu ;-)
Niewyspanie - złe skutki niechciejśpizmu ;-)
Lenistwo w działaniu, "piklujemy" Androida ;-)
Chrome2ChromeV2 na GitHub :-)

środa, sierpnia 11, 2010

Bloggeroid 1.0 :-)



No i stało się :-) Bloggeroid w wersji 1.0 trafił właśnie do Android Marketu :-)

Jeśli chcesz go zainstalować, do czego gorąco zachęcam :-) to tutaj link, który otworzy Ci go w Android Market :-)



Bloggeroid ma być prosty. Pierwszym ekranem który zobaczysz jako użytkownik będzie okno pozwalające na napisanie posta, w końcu po to zwykle będziesz otwierać aplikację do blogowania ;-)

Co możesz zrobić przy pomocy Bloggeroida?

Oto lista:
  • napisać post,
  • dodać obrazki do posta,
  • zdecydować gdzie w treści postu mają być te obrazki,
  • użyć prostego formatowania (**pogrubiony**, __pochylony__),
  • opublikować post na dowolnym ze swoich z blogów w Bloggerze,
  • używać wielu kont Bloggera,
  • publikować posty jako szkice,
  • edytować opublikowane już posty,
  • przeglądając galerię użyć Bloggeroida do "podzielenia" się obrazkami.


Wszystko zaś działa dość stabilnie i co ważne zajmuje mało miejsca na telefonie [użytkownicy G1 powinni być z tego powodu szczęśliwi :-)], bo aplikacja po zainstalowaniu zajmuje mniej niż 120KB.

Zapraszam więc do pobierania :-)

Podobne postybeta
Bloggeroid - wersja 1.0 tuż, tuż ;-)
Nie kłóć się z użytkownikiem! ;-)
Google+ & Blogger - mój pomysł ;-)
Piszemy sobie Bloggeroida dla Androida ;-)
Robimy nową galerię ;-)

niedziela, sierpnia 08, 2010

Bloggeroid - wersja 1.0 tuż, tuż ;-)


Przygotowuję się do wydania finalnej wersji 1.0 Bloggeroida i do opublikowania jej w Android Market'cie.
Pierwszy krok czyli zgłoszenie do Android Market i wpłatę wpisowego mam już za sobą ;-) Na chwilę obecną kosztowało mnie to 75.88 PLN, ale cena może ulec lekkiej zmianie bo transakcja nie jest jeszcze w pełni zaksięgowana ;-)

Czym jest Bloggeroid?
To prosty klient Bloggera, który pozwala na pisanie i publikowanie wpisów na blogach w Bloggerze, Bloggeroid wspiera wiele kont, dlatego jeżeli mamy np. 2 konta Google w każdym po 3 blogi to Bloggeroid daje nam możliwość blogowania na dowolnym z blogów podpiętych do kont :-)
Bloggeroid pozwala na wysyłanie obrazków, dodatkowo daje narzędzia do "zarządzania" obrazkami. Autor wpisu decyduje w którym miejscu wpisu obrazek ma się znajdować w treści postu. Same obrazki publikowane są w albumach Picasa'y.
Bloggeroid pozwala także na używanie prostej "wikiskładni", w której **tekst** spowoduje, że w finalnym poście tekst zostanie pogrubiony, a __tekst__ pochylony.
Do tego Bloggeroid pozwala na edycję istniejących wpisów na blogach, edycja może odbywać się w formacie "wikiskładnia" + HTML, lub w czystym HTMLu.
Bloggeroid jest także mały, wersja instalacyjna zajmuje mniej niż 50KB, a po zainstalowaniu zajmuje mniej niż 120KB pamięci telefonu :-)
Bloggeroid jest też stabilny. Znam co prawda jedno miejsce gdzie można go "wywrócić", ale mała szansa by się to często udawało :-)
Bloggeroid wymaga Androida 1.5 [choć jak przypuszczam mógłby być też używany na starszych wersjach systemu].
Do tego wszystkiego dostępny jest w wersji polskiej i angielskiej :-)

[do obrazka wkradł się jeden błąd, który został już poprawiony ;-)].

Jeśli ktoś chciałby pobrać to zapraszam do Android Market'u, gdzie trzeba szukać używając tekstu Bloggeroid, albo można po prostu użyć tego QR code'u :-)




Podobne postybeta
Bloggeroid 1.0 :-)
Google ma dziś zły dzień? ;-)
Javozagadka ;-)
Sztuczki tropiciela błędów, part 4
OO.org i Google Docs bez konwersji są tuż tuż ;-)

AppInventor - tego się da używać :-)

Po ostatnich poprawkach Google AppInventor for Android staje się już realnym narzędziem do robienia prostych programów.

Wróciłem do mojego projektu Planu Lekcji. Dzięki naprawieniu przez Gugielków [mała dygresja, jak pracowałem w Motoroli to zwano nas Motorolanami, w Google pracowników zwą Googlerami, jednak po polskiemu ładniej brzmi wg. mnie Gugielki :-)] komponentu TinyDB nie trzeba już inicjalizować kluczy w "bazie" przed ich użyciem. To pozwala na wyrzucenie brzydkiego guziczka init.
Okazuje się również, że w dość łatwy sposób można sobie zmieniać rozmiary komponentów.....

Dzięki temu Plan Lekcji w wersji AppInventorowej wypiękniał :-)



Dodatkowo pokusiłem się o dodanie mu funkcjonalności, która wcześniej wydawała mi się nieosiągalna, czyli domyślnego wyświetlania planu na aktualny dzień :-)
Tu pojawił się problem, bo zegar co prawda podaje numer dnia tygodnia, a nawet i nazwę, ale jeżeli używamy numeru dnia tygodnia to "po angielsku" tydzień zaczyna się od niedzieli, a gdy użyjemy nazwy dnia to niestety będziemy mieli ją w języku interfejsu...... Co można zmienić i już chyba wiem jak :-) ale to pozostawmy na następną wersję ;-)
Teraz problemem było przeliczenie z dni tygodnia liczonych "po angielsku" na takie nasze, tak by to poniedziałek był pierwszym dniem tygodnia.
Trochę to program skomplikowało :-) "kod" wygląda teraz tak:



Jeśli spojrzycie na drugi "moduł" programu to najstraszniej wygląda tam przeliczanie numeru dnia tygodnia "po angielsku" (1 to niedziela, 7 to sobota) na nasze (1 to poniedziałek, a 7 to niedziela).
Głowy nie dam, że dobrze to liczę, ale późno jest ;-) użyłem "wzoru":

Dnum_pol=((Dnum_eng+6) modulo 7)+1


i jest to chyba najtrudniejszy kawałek "programu".
Ten kod wykonywany jest w obsłudze zdarzenia Timera, chciałem go wykonywać w trakcie inicjalizacji ekranu, ale działało to dziwnie, więc zastosowałem sztuczkę polegającą na tym, że kod wykonuje Timer ustawiony na 10 ms, który zaraz po rozpoczęciu wykonywania kodu jest wyłączany.

Ostatni "moduł" to ustawianie zawartości pola tekstowego tym co odczytane zostanie z bazy i ustalanie nowego rozmiaru dla pola tekstowego tak by guziczki wyglądały ładniej na ekranie.
Ten ostatni "moduł" jest procedurą, która wywoływana jest tak ze zdarzenia wyboru elementu z listy jak i pod koniec obsługi Timera.

Nadal nie jest to wybitnie skomplikowany program, ale AppInventor pokazuje już tutaj swoje pazurki. Niezły efekt przy stosunkowo małym wysiłku.
Choć trzeba znać nadal programistyczne sztuczki, jak ta z dniem tygodnia [i nie chodzi nawet o przeliczenie, a o to, że nie każdy musi wiedzieć, że się w ogóle da to odczytać :-)].

A tutaj aplikacja do pobrania :-) [rozmiar to około 1 MB, niestety AppInventor nadal z tym przegina ;-)].
Tutaj źródła [te dla odmiany malutkie, mają mniej niż 4KB :-)]

Podobne postybeta
AppInventor - pierwsze wrażenia i pierwsze programy :-)
Czy się stoi czy się siedzi.... kamerka w laptopie jako detektor tego czy biurko jest w trybie stand czy sit ;-)
Androidowe boje... ale nie takie morskie ;-)
3 Home w jednym domu ;-)
Raport z prac nad ubogą krewną Playtypusa, czyli Kolczatką :-)

Androidowe boje... ale nie takie morskie ;-)

Dalej walczę z Bloggeroidem i mam problem.
Albo ja czegoś w platformie jaką jest Android nie rozumiem, albo jest w niej "pewne" niedopatrzenie.
Chciałbym pewną czynność, dokładniej pobranie postów z bloga, robić "z tyłu" aktywności. Gdy pierwszy raz wyświetla się nam aktywność powinien pojawić się "progress", a później lista postów z bloga. Ponieważ chcemy uniknąć pretensji Androida, że blokujemy na zbyt długo wątek UI to wszystko dzieje się w oddzielnym wątku, który robi swoje i w końcu zamyka progress i wyświetla pobraną listę postów....... ale, ale jak ktoś nam złośliwie zmieni orientację ekranu to aktywność ginie, ale wątek sobie leci nadal, i jak już skończy to próbuje zamknąć okienko, którego nie ma, a to powoduje pretensje Androida.... OK, tu możemy założyć zabezpieczenie, ale i tak dane się zgubią. To też by można było przeżyć, ale jeżeli ktoś bez opamiętania będzie latał telefonem i ciągle zmieniał orientację to zima, w końcu poleci OutOfMemmoryError bo po prostu te wątki ciągnące, plus pobrane dane i inne podobne rzeczy mogą przekroczyć ograniczenia na stertę/zrobić coś równie głupiego.
To czego potrzebuję to możliwość odpalenia z aktywności czegoś w oddzielnym wątku co zrobi swoje i odda sterowanie do aktywności nawet jeżeli ta aktywność zginie, ale wróci "na wierzch" jakaś inna tego typu.
Jedyne co przychodzi mi do głowy to coś takiego, że w aktywności będę miał statyczne pole w którym będę trzymał referencję do oddzielnej klasy, w której będzie szalał wątek i na końcu wywoła metodę z przekazanego mu obiektu, a aktywność przy tworzeniu będzie od razu wołała na tej trzymanej statycznie klasie metodę, w której zarejestruje się na wołania z tego obiektu.......
Ale to takie fuj.
Myślałem o serwisie i bindowaniu do niego, ale jakoś nie czuję bluesa.
A to się musi dać jakoś rozsądnie zrobić.

Z innych rzeczy :-) Google ostro pracuje nad Google AppInventor for Android. Naprawili TinyDB i obsługę sensorów :-)
Dzięki temu moja aplikacja do obsługi sensora już działa :-)
Wg. jej wskazań przyciąganie ziemskie u mnie w domu to 9.5 m/s2, wg. wzorów empirycznych powinno to być właśnie 9.81 m/s2.
Chętnie poznam wyniki innych osób :-) Tutaj link do aplikacji, w celu wykonania pomiaru należy telefon położyć na płaskiej powierzchni i sprawdzić wyniki dla ZAccel.
Tak wygląda źródło aplikacji "sensorowej" :-)



Plan Lekcji też jest już prostszy :-)


Podobne postybeta
I jak "po bożemu" zrobić updatowanie widoku na podstawie danych z sieci w Androidzie?
O tym w czym iOS jest lepszy od Androida
Modale nie takie dobre dla Androida ;-)
Raport z boju z Androidem ;-)
Sprawdzanie zdjęcia ;-)

piątek, sierpnia 06, 2010

AppInventor - pierwsze wrażenia i pierwsze programy :-)

Dostałem 2 dni temu czy jakoś tak zaproszenie do Google AppInventor for Android.
Zacząłem się bawić i zacząłem pracować nad projektem, który "obiecałem" w swojej aplikacji o konto [nie wiem czy akurat "za to" mi przyznali konto, bo kilka razy na ten adres próbowałem uzyskać zaproszenie [na inne też ;-)]], czyli postanowiłem spróbować napisać tą samą aplikację przy pomocy AppInventor'a i Java'y i porównać wrażenia.

Programem będzie Plan Lekcji.

Layout wersji dla AppInventora wygląda tak:



Idea jest taka, by po kliknięciu w guziczek u góry pokazywała się lista wyboru z nazwami dni tygodnia, a po wybraniu którejś z wartości pokazywać się będzie zapisana w bazie pod kluczem z nazwą tygodnia "notatka" będąca planem lekcji na dany dzień. Plan lekcji będzie pokazywał się w polu tekstowym pod guziczkiem do wyboru.
Danych dostarczy użytkownik klikając na odpowiedni dzień, wpisując dane w polu tekstowym i klikając na Save.

Kod AppInventorowy aplikacji wygląda tak:



Program "mówi":
po wybraniu opcji z listy wyboru (ListPicker1) ustaw tekst wyświetlany przez listę wyboru na wybraną opcję,
następnie ustaw zawartość pola tekstowego (TextBox1) przy pomocy wartości pobranej z bazy (TinyDB1) spod klucza równego wybranemu z listy (ListPicker1) tekstowi (tak naprawdę temu co wyświetla lista jako wybraną opcję, ale to to samo dzięki wcześniejszemu krokowi),
w końcu ustaw nazwę okna (Screen1) na wybrany tekst.

oraz:

W momencie przyciśnięcia guzika (Button1) zapisz do bazy (TinyDB1) pod kluczem równym wybranej z listy wyborów opcji (ListPicker1) treść z pola tekstowego (TextBox1).

Banał, prawda? :-)

Jest "małe" ale, w obecnej wersji AppInventor'a jest błąd, powodujący, że pobieranie z bazy wartości spod kluczy pod które nigdy nic nie zapisano wyrzuca błąd:



Mają to naprawić w tym lub przyszłym tygodniu :-)

Dlatego dla testu dodałem jeszcze jeden guziczek, który będzie inicjalizował naszą bazę.



Tu już jest trudniej niż w poprzednich blokach programu.
Najpierw mamy użycie pętli forEach, czyli "dla każdego", w tym przypadku dla każdego var z elementów naszej listy z dniami tygodnia (ListPicker1) zapisujemy do bazy (TinyDB1) pod kluczem będącym nazwą dnia tygodnia (w zmiennej var) nazwę tego dnia (z tej samej zmiennej).

Czas wykonania: Trudno powiedzieć dokładnie, ale nie więcej niż 30 minut :-) i to tylko przez to, że to "pierwszy raz".
Rozmiar: trochę ponad 1MB.
Poziom trudności: bardzo łatwy
Wymagana wiedza: niewielka

Działająca aplikacja nie jest zbyt piękna ;-)



Ale działa :-)
Dla mnie jako dla programisty wykonanie tej aplikacji było banalne, dla zwykłego człowieka powinno nie być zabójczo trudne :-)

Teraz wersja w Java'ie :-)

Zaczynamy od Layout'u:


Nasza aplikacja składa się z dokładnie 1 aktywności, w której jedyny istotny kod jest w metodzie onCreate():
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
List<String> list = Arrays.asList("Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday".split(","));
final Spinner spinner = (Spinner)findViewById(R.id.Spinner01);
final EditText editText = (EditText)findViewById(R.id.EditText01);
final SharedPreferences prefs = getSharedPreferences("plan", Context.MODE_PRIVATE);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, list);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> arg0, View arg1,int arg2, long arg3) {
String str = (String)spinner.getSelectedItem();
String content = prefs.getString(str, str);
editText.setText(content);
PlanLekcji.this.setTitle(str);
}
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
Button button = (Button)findViewById(R.id.Button01);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
String str = (String)spinner.getSelectedItem();
String content = editText.getText().toString();
prefs.edit().putString(str, content).commit();
}
});
}


I to by było na tyle ;-)

Wygląda tak:


Wg. mnie lepiej :-)

Rozmiar: niecałe 15KB.
Czas wykonania: około 15-30 minut, z "kradzieżą" kodu z moich innych projektów.
Poziom trudności: dużo wyższy niż w przypadku AppInventora.
Wymagana wiedza: Po pierwsze trzeba znać Java'ę, ale także API, trzeba też wiedzieć jak zainicjalizować listę wyboru dni, co takie oczywiste nie jest.

Program w Java'ie wykorzystuje łącznie 3 klasy, jedną główną PlanLekcji, oraz 2 anonimowe.

Na samym końcu wersja w HTML5, która powinna działać też np. na iPhone'ie czy iPad'zie ;-) (ale nie działa na moim G1 :-( bo w nim nie ma HTML5)

Która wygląda tak [tutaj, zrzut z ekranu emulatora udającego Nexus One]:



Ładna nie jest, choć faktem jest, że jej uładnienie byłoby najprostsze, bo w HTML'u mamy niemal pełną kontrolę nad layoutem strony.

Kod źródłowy wygląda tak:
<html>
<body>
<script>
function change(elem) {
var str = localStorage[elem.value];
if (str==null) {
str = elem.value;
}
document.getElementById("content").value=str;
}
function save() {
var str = document.getElementById("select").value
var content = document.getElementById("content").value;
localStorage[str]=content;
}
</script>
<select id="select" onchange="change(this)">
<option>Monday</option>
<option>Tuesday</option>
<option>Wednesday</option>
<option>Thursday</option>
<option>Friday</option>
<option>Saturday</option>
<option>Sunday</option>
</select><br />
<textarea id="content" rows="10" cols="10"></textarea><br />
<button onclick="save()">Save</button>
</body>
</html>


Rozmiar: 713 bajtów
Czas wykonania: 10 minut [mnie to tyle zajęło!]
Trudność: łatwe
Potrzebna wiedza: znajomość HTML/JavaScript.

A teraz sekcja downloadów :-)
Plan Lekcji w wersji z AppInventora [1MB]
Plan Lekcji w Java'ie [15KB]
Plan Lekcji w wersji HTML
"Źródła" wersji z AppInventor
Źródła wersji w Java'ie

Podsumowując, jak na razie AppInventor nie wprowadza rewolucji dla programistów, ale daje w ręce trochę bardziej zwykłych ludzi narzędzie do tworzenia prostych programików prostą metodą drag&drop. Robi to niestety kosztem ograniczenia funkcjonalności i wpływu na wygląd aplikacji wynikowej. Ma też jak na razie trochę błędów. Np. wspomniany już tu błąd działania TinyDB, oraz błąd polegający na złym odczytywaniu danych z akcelerometru :-)
Jeszcze kilka miesięcy i będzie to potężne narzędzie do zabawy, a może i do pracy :-)

[prawie 3 w nocy i mi się spać chce ;-)]


Podobne postybeta
Czy ustalanie pozycji w Androidzie może kosztować?
"Kodowanie" na Chrome OS ;-)
Python for Android vs. AppInventor - 2:0 ;-)
Jak "okradłem" Google Readera ;-)
Ile w tym i przyszłym miesiącu z odsetek za obligacje?

wtorek, sierpnia 03, 2010

Lenistwo w działaniu, "piklujemy" Androida ;-)

Znów mnie dopadło lenistwo i nie chce mi się kodować :-)
Przez to zamiast użerać z jakimś rozsądnym sposobem serializowania obiektów w Bloggeroidzie po to by przekazywać je w Intentach popełniłem to w najbardziej prymitywny i prosty sposób.

Żeby przesłać obiekt z jednej aktywności do innej, lub do/z serwisu używamy intent.putExtras(String,byte[]), a do odebrania intent.getExtras.getByteArray(String).

Nasz obiekt musi implementować Serializable, i jego członkowie też.

Tutaj dwie użyteczne metody ;-)

public static byte[] toByteArray(Object obj) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
return baos.toByteArray();
}

public static<E> E toObject(byte[] arr) throws StreamCorruptedException, IOException, ClassNotFoundException {
ByteArrayInputStream bais = new ByteArrayInputStream(arr);
ObjectInputStream ois = new ObjectInputStream(bais);
return (E)ois.readObject();
}


Do toByteArray(Object) przekazujemy nasz obiekt do serializacj, pobierając zaś obiekt z toObject(byte[]) dostajemy to do czego przypisujemy wynik działania tej metody [tu uwaga, jak przypiszemy do czegoś innego to wyleci ClassCastException i tyle będzie zabawy :-)].

Btw. Pythonowe piklowanie brzmi lepiej niż serializacja, której nawet słowniki ortograficzne nie znają.

Jak na razie próbowałem z kilku-kilkunastobajtowymi obiektami i działa, sterta procesu rośnie, ale niewiele ponad to co Android daje w standardzie. Choć udało mi się dotrzeć już do 11MB, a to jednak dużo :-)

Ktoś zna bardziej "koszerny" sposób?


Podobne postybeta
Refleksje i serializacja w Java'ie - podstawy i obalanie mitów ;-)
Serializacja w Java'ie - revisited ;-)
Zinwigiluj się sam ;-)
Wredne Google Docs
Toperz ;-) czyli OCR + Android odsłona 2 albo któraś tam

poniedziałek, sierpnia 02, 2010

Z placu boju z Bloggeroidem ;-)

Dwa największe problemy jakie mam z Bloggeroidem na chwilę obecną to, po pierwsze jak zmienić HTMLa w opublikowanych już postach w mój format udający wiki ;-), po drugie serializacja.
Serializacja np. listy postów pobranej przed chwilą z bloga.
Trochę głupio ściągać tą listę za każdym razem... trzeba by było jakoś zapisać te dane. Albo zserializować do Stringa, albo trzymać w jakimś objekcie globalnym... albo oszukać :-) Zapisać listę obiektów do ObjectOutpuStream otwartego nad ByteArratOutputStream'em i zapisać tablicę bajtów do outState w onSaveInstanceState (metoda w aktywności wołana przez Androida gdy system kładzie naszą aktywność, a powinna być ona później znów dostępna).

Wydaje się, że ta ostatnia metoda to nie jest to ;-) ale ma plusa bo szybka ;-)



Podobne postybeta
Serializacja w Java'ie - revisited ;-)
Co ładniejsze?
Nexus S - wrażenia z boju ;-)
Jak pogadać z Alexą na telefonie
Extremal recruting ;-)

Plusy dodatkie i plusy ujemne, czyli co może być złego, a co dobrego w AppInventorze :-)

Nie mam jeszcze konta w Google AppInventor for Android, czekam nadal, ale mam już chyba jakieś wnioski ;-)

Pierwszy taki, że jest pewne niebezpieczeństwo w tej aplikacji. Można sobie zrobić krzywdę przez wykorzystanie płatnych usług, albo zamienić telefon w maszynę utrudniającą komuś życie.
Ktoś wkurzony na swoją ex-połówkę będzie mógł chyba dość szybko wyklikać aplikację dzwoniącą pod wybrany numer w dziwnych porach, albo non-stop... z drugiej strony wtedy zapewne druga strona będzie mogła napisać aplikację zrzucającą wszelkie połączenia od tamtej osoby ;-) Dzieciak chcący wygrać "motór" czy innego iPoda w konkursie SMSowym może wpaść na pomysł wyklikania aplikacji do wysyłania SMSów o pełnej godzinie.

To mi przypomina to, że gdy pisałem sobie wtyczki do Gadu-Gadu to napisałem też Skryptusia, w którym zablokowałem np. możliwość wysyłania przez skrypty wiadomości do osób które się do nas nie odezwały. Chodziło mi o to by uniemożliwić powstawanie botów atakujących jakieś numerki ciągłym spamowaniem. Ale przez to ograniczyłem możliwości aplikacji tylko do reagowania na to co się do niej mówiło....
Google ma ten sam dylemat tylko jakiś milion razy większy ;-)

To wyżej to jedno niebezpieczeństwo, które widzę w Google AppInventor for Android. Plusów jest więcej ;-)

To nikt inny jak użytkownicy wie najlepiej czego potrzebują. To może być laboratorium, które posłuży do przetestowania wielu głupich pomysłów, z których niektóre mogą stać się użyteczne.
Ja bym nigdy nie widział potrzeby w pisaniu aplikacji, która będzie odpowiadała na wszystkie SMSy, które otrzyma [w zamyśle autora, gdy jeździ na rowerze to chciałby żeby osoby piszące do niego SMSy były informowane, że nie może odpisać bo jest zajęty], ale przypuszczam, że wielu ludzi nie będzie mogło żyć bez takiej aplikacji.

Zalety edukacyjne są oczywiste, ale i parę nieoczywistych jest ;-) Np. teraz nic nie będzie stało na przeszkodzie napisaniu aplikacji, która co np. 10 minut albo co godzinę będzie robiła zdjęcie. Albo codziennie o tej samej porze. Wystarczy wtedy taki telefon postawić przy oknie i mamy piękny film pokazujący ruch Słońca, czy coś podobnego.

Tak w ogóle. To mnie się marzy [od dobrych 8 lat] takie coś podobne do AppInventora, ale działające na telefonie/PDA :-)
Pojawia się pomysł albo potrzeba i w 5-10 minut wyklikuje się niezbyt skomplikowaną aplikację.
Problem jest "tylko" z interfejsem ;-) Bo nie umiem wymyślić dobrego ;-)

Aha, Google, dajcie to zaproszenie ;-) miejcie litość ;-)

Podobne postybeta
Raport z emigracji ;-)
Powiadomieniami w walce z uzależnienie od WhatsApp i Telegrama ;-)
Transport publiczny - moje top i bottom 5 (na dziś :-))
Planetarium czy Plebania?
Ku dyktaturze...

niedziela, sierpnia 01, 2010

zVATowani 2

OK, wszyscy płaczą, że zły rząd chce podwyższać podatki, a oni tacy biedni. Ci sami ludzie płaczą też, że przecież oni tacy biedni i im nikt nie chce pomagać.
Emeryci za mało dostają. Szkoły są biedne. Nauczyciele mało dostają.

Weźcie się zdecydujcie, OK?

Albo mamy model państwa opiekuńczego gdzie płacimy wysokie podatki [umówmy się, że składki na ubezpieczenia w stylu NFZ czy ZUS to też podatki] i z tych pieniędzy świadczone są nam usługi w stylu szkół, emerytur, opieki medycznej. To jest model z siatką zabezpieczającą, może ona krępować tych, którzy sobie świetnie radzą, ale daje ratunek tym którym się noga powinie.
Albo mamy model darwinizmu społecznego gdzie płacimy minimalne podatki, ale o wszystko musimy martwić się sami. To jest model w którym jak ci się noga powinie to odpadasz od ściany i spadasz w dół.

Nie da się połączyć tego tak by mieć przywileje i bezpieczeństwo z modelu 1, i koszty z modelu 2.

Jeżeli uważasz, że trzeba pomagać ludziom, że szkoły powinny być powszechne i nie powinno się dostawać rachunków za posyłanie tam dzieci, jeżeli uważasz, że opieka medyczna też powinna być powszechnie dostępna i nie powinno się dostawać rachunków po wyjściu od lekarza to nie ma przebacz, skądś pieniądze na to muszą pójść. Wszyscy się muszą zrzucić. Siłą rzeczy bogatsi zrzucą się bardziej niż biedni. Ale zrzucić się musi KAŻDY.

Nie ma darmowych obiadów [to tylko po części prawda, bo np. duża część Open Source to właśnie darmowy obiad], ktoś za to musi zapłacić. Albo płaci każdy za siebie i wtedy są tacy, których stać na dużo więcej niż potrzebują i są też tacy, których nie stać nawet na podstawowe sprawy, albo wszyscy wrzucają do wielkiego wora, i część dostaje z tego wora dużo więcej niż włożyli, a część nie wyciąga niczego, ale w zamian dostaje spokój społeczny, nie musi budować zamków ani nosić ostrego miecza przy sobie by bronić swojego dobytku przed tymi, którzy nie mają nic.

Jeżeli płaczesz, że emeryci dostają za mało to pomyśl, że rok w rok na emerytów wydajemy 130-150 mld złotych! Podwyższenie nawet o złotówkę miesięcznej emerytury dla każdego emeryta to dodatkowe 90 milionów złotych. O 10 złotych to 900 milionów, trzy razy więcej niż idzie na becikowe, albo IPN.

I teraz jest tylko pytanie czy trafia do Ciebie kawałek Kazika:
"całe życie tyrał w hucie, a do huty dokładali. Cała jego ciężka praca, wszystko było ch... warte, gdyby leżał całe życie mniejszą czyniłby on stratę"
Jeżeli przemawia, to godzisz się ponosić te koszty i rozumiesz, że ktoś za te emerytury musi zapłacić.

Jeśli kiedykolwiek pomyślałeś/pomyślałaś, że komuś powinno państwo/samorząd czy ogólnie społeczeństwo pomóc to w mniejszym lub większym stopniu popierasz ideę państwa opiekuńczego. Więc zaakceptuj, że za to musisz płacić niezależnie czy z tego korzystasz czy nie.
W domu nie rozliczasz dzieci z chleba który zjadły, nie przeliczasz tego na przyszłe zyski z inwestycji. Pomagasz znajomym bezinteresownie. Ponosisz koszty, jedynie dla satysfakcji i mglistej obietnicy rewanżu.
Państwo opiekuńcze to rozwinięcie tego modelu. Ci, którym powodzi się lepiej pomagają tym którym powodzi się gorzej.

Drugi model jest taki, że każdy może liczyć tylko na siebie, może rodzinę i znajomych. Panuje tam trybalizm, w którym pomaga się tylko ziomkom, a innych postrzega się jak potencjalnych wrogów, którzy mogą zagarnąć Twoje zasoby. Ten model prowadzi zawsze do koncentracji bogactwa. Wymusza przez to by bogaci bronili się przed biedną resztą.

Nie można mieć państwa opiekuńczego bez jego kosztów. Nie da się.

Wg. mnie się opłaca.
Dlatego skoro przez parę ostatnich lat wzbogaciliśmy się dość znacznie, i wygląda na to, że żyliśmy ponad stan, to trzeba za to teraz zapłacić.
Gdyby to ode mnie zależało większość kasy poszłaby z PIT, a nie z VAT, zlikwidowałbym becikowe, ulgę na dzieci, IPN, fundusz kościelny, Ministerstwo Sportu, zlikwidował dotację dla większość uczelni "wyższych" i zostawił tylko dla tych najlepszych [pomiar przez ilość cytowań w świecie i średnią zarobków absolwentów w porównaniu do absolwentów danego kierunku na innych uczelniach z uwzględnieniem rejonu], przetrzebił wojsko, zrezygnował z powiatów lub gmin, pomyślał o podniesieniu podatku Belki, by lokaty nie były bardziej opłacalne od ryzykowania i prowadzenia firm, podniósł składkę zdrowotną i emerytalną i wprowadził zasadę, że państwo ma prawo zaciągać długi tylko w celach inwestycyjnych.

Uwagi do ewentualnej dyskusji tutaj lub na Google Buzz, Flakerze czy gdziekolwiek indziej.
Tak, wiem, że Ty chcesz "wolności", że nie chcesz płacić za innych, tak i jesteś w 10% najbogatszych ludzi więc nigdy nie wyciągnąłeś nawet złotóweczki z wora, brawo! Tak trzymać!
Ale długi mamy i tak, dlatego powiedz skąd wziąć pieniądze na ich spłatę? Komu zabrać? Ja swoje opisałem, Ty opisz swoje.
Ja wolę państwo opiekuńcze, Ty nie, ale powiedz skąd wziąć pieniądze i jak uniknąć wtedy buntu społecznego, lub jeśli wybuchnie to jak go stłumić albo jak z nim żyć?
Powiedz jak przejść od złego "socjalizmu" do wspaniałej wolności.


Podobne postybeta
Dziura
2011 zaczęty ;-)
"Ja? Niech ktoś inny płaci" ;-)
Jak się profesjonalnie kłamie
Nie ma sprawiedliwych podatków ;-) przynajmniej obiektywnie sprawiedliwych ;-)