czwartek, lipca 22, 2010

Toperz ;-) czyli OCR + Android odsłona 2 albo któraś tam

[mały edit, zdecydowałem, że toperz powinno się pisać przez rz, a nie ż, wziął się od nietoperza choć myślałem też o pisowni topesz ;-) i tak, to nie ma żadnego wpływu na resztę postu ;-)]

Dziś pochwalę się wynikami mojego eksperymentu z użyciem Androida i OCRa w Google Docs do tworzenia dokumentów w Google Docs na podstawie zdjęć ;-)

Jest to moim prywatnym zdaniem jedno z najmniej przydatnych narzędzi jakie sobie kiedykolwiek popełniłem ;-)

Znajdziecie je pod tym linkiem.

Obsługa jest prosta, po zainstalowaniu idziemy do galerii i wybieramy zdjęcie, które chcielibyśmy zOCeRować, wybieramy dzielenie się tym zdjęciem i z listy wybieramy OCRDroid, przy pierwszym uruchomieniu zostaniemy poproszeni o hasło do Google Docs, tutaj lepiej się nie pomylić bo program jest "jednorazowy" jeśli chodzi o wprowadzanie danych o koncie :-) [To dlatego, że oryginalnie miał namiary na konto zahardkodowane, ale "ukradłem" sobie okienko dodawania kont z Bloggeroida i teraz już nie muszę nic hardkodować], po wprowadzeniu nazwy konta i hasła klikamy Save i czekamy, przez jakiś czas będziemy widzieli czarny ekran z napisem OCRDroid, możemy też zobaczyć informację, że aktywność zbyt długo nie odpowiada, wtedy klikamy Czekaj. W końcu dostaniemy informację, że możemy sobie pójść do Google Docs żeby obejrzeć nasz dokument ;-)

W większości przypadków dokument ten nie będzie się do niczego nadawał ;-)

W trakcie działania programu lepiej nie robić żadnych zmian orientacji telefonu, to jest prosty program, a całe wysyłanie obrazka odbywa się bardzo nieprofesjonalnie w onCreate() aktywności, a Android ma tak, że jak zmienia się orientacja ekranu to zabija aktywność i tworzy ją od nowa. Dlatego w trakcie zabaw z Toperzem ;-) nie machać telefonem ;-)

Jak ktoś chciałby źródła to proszę się do mnie zgłosić :-)
Tutaj chyba najciekawszy kawałek odpowiedzialny za zalogowanie się i wrzucenie zdjęcia do Google Docs do przeprocesowania go przez OCR.

// Najwpierw logowanie
// W email jest adres e-mail usera, w password hasło
URL url = new URL("https://www.google.com/accounts/ClientLogin");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setAllowUserInteraction(true);
connection.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
connection.setDoOutput(true);
connection.connect();
OutputStream os = connection.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
// Logujemy się do Google Docs, czyli nazwa serwisu to writely
bw.write("\r\naccountType=HOSTED_OR_GOOGLE&Email="+email+"&Passwd="+password+"&service=writely&source=RMK-OCRDroid-0.01\r\n");
bw.flush();
is = connection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = "";
String auth = "";
// Teraz serwer nam odpowiada, linia zaczynająca się od Auth= zawiera token
// do autoryzacji
while ((line=br.readLine())!=null) {
if (line.startsWith("Auth=")) {
auth = line.replace("Auth=", "");
}
}

// Przesyłanie do Google Docs

// To ocr=true jest najważniejsze :-)
String uploadUrlStr = "https://docs.google.com/feeds/default/private/full?ocr=true";

URL uploadUrl = new URL(uploadUrlStr);

HttpURLConnection conn = (HttpURLConnection)uploadUrl.openConnection();

conn.setRequestMethod("POST");
conn.setRequestProperty("Authorization", "GoogleLogin auth="+auth);
conn.setRequestProperty("GData-Version", "3.0");
conn.setRequestProperty("Content-Type", "image/jpeg");
// wg. teorii Slug to nazwa pliku, ale coś nie działa tak jakbym chciał
conn.setRequestProperty("Slug", "OCRDoc "+new Date());
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();

long contentLength = baos.size();
conn.setRequestProperty("Content-Length", ""+contentLength);

conn.setDoOutput(true);
conn.connect();
// baos to zmienna zawierająca ByteArrayOutputStream z binarnymi danymi
// naszego obrazka
conn.getOutputStream().write(baos.toByteArray());

// W bardzo nieprofesjonalny sposób czytamy odpowiedź Google Docs,
// ale szczegół bo i tak ją zignorujemy ;-)
BufferedReader br2 = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line2 = "";
while ((line2=br2.readLine())!=null) {
System.out.println(line2);
}


Używam tutaj najbardziej podstawowej metody walki z połączeniami HTTP, na Androidzie wypada to robić ciut inaczej, ale szczerze nie miałem jeszcze czasu się temu przyjrzeć, a podejście takie jak moje ma tą zaletę, że można dość swobodnie kod testować poza Androidem na PC, a to pomaga ;-)
Przy okazji jak ktoś nie wierzy to przy pomocy HttpURLConnection można wysyłać też wieloczęściowe requesty co można zobaczyć np. w źródłach OOo2GD (Plik ZohoWrapper.java linia 357, metoda uploadDocumentForUrl).
Dlatego jak już piszesz jakąś wspaniałą aplikację na Androida to nie używaj przyciężkich bibliotek, to dla Ciebie pikuś, a zyskasz miłość userów ;-)


Podobne postybeta
Wredne Google Docs
Programowanie trudne ;-)
Wysyłamy pliki do Google Docs przy pomocy Go :-)
PROPFIND, czyli jak przechytrzyć HttpURLConnection
Chrome OS, Chrome2Chrome i w ogóle Chrome ;-)