czwartek, czerwca 17, 2010

Wredne Google Docs

Próbuję powołać do życia zabawkę, która pozwoli robić zdjęcia telefonem Androidowym jakiemuś tekstowi, wrzucać to do Google Docs, OCRować przez Google Docs i zwracać do telefonu jako tekst.

Wg. teorii przedstawionej w dokumentacji Google Docs List API to powinien być pikuś.
Trzeba się zalogować, później zaś użyć adresu:

https://docs.google.com/feeds/default/private/full?ocr=true

do zuploadowania pliku z obrazkiem i voila! wszystko powinno działać.

Ale nie działa. Dostaję od serwera błąd 403, z wyjaśnieniem, że nie mam prawa do korzystania z danego zasobu. Ale gdy korzystam z Google'owego przykładu, który działa jako aplikacja webowa to OCR działa dla każdego z moich kont.

Czyżby chodziło więc o to, że moja aplikacja używa autoryzacji ClientLogin?

Nie wiem. Z Google Docs List API jest taki problem, że to jest nadal beta (dokładniej jest w laboratorium] i nie zawsze wszystko działa tak jak powinno, dlatego nie mogę być pewny tego, że np. za chwilę wszystko jednak nie zacznie działać.
Np. okazuje się, że od momentu wprowadzenia nowego edytora do Google Docs nie działa eksport plików przez API. Ktoś w Google nad tym pracuje, ale jak na razie nie ma rozwiązania, a patrząc na wątki na forum i w bug trackerze to można momentami mieć wrażenie, że nie wiadomo do końca właściwie czemu to nie działa ;-)

Tak jakby kogoś interesowało to tutaj łopatologiczny i niezbyt ładny, ale działający sposób na logowanie do Google Docs [części związanej z dokumentami tekstowymi i prezentacjami, czyli do writely, z informacją, że logująca się aplikacja zowie się RMK-OCRDroid-0.01]:
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));
bw.write("\r\naccountType=HOSTED_OR_GOOGLE&Email="+email+"&Passwd="+password+"&service=writely&source=RMK-OCRDroid-0.01\r\n");
bw.flush();
InputStream is = connection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = "";
String auth = "";
while ((line=br.readLine())!=null) {
System.out.println(line);
if (line.startsWith("Auth=")) {
auth = line.replace("Auth=", "");
System.out.println("!"+auth);
}
}

To co wyżej zwykle lepiej zrobić przy pomocy bibliotek dostarczonych przez Google, ale ponieważ dla mnie okazało się prostszym i szybszym napisanie własnego kodu do kontaktów z Google Docs List API niż zrozumienie jak działa wersja bibliotek dla Androida, to przedstawiam jak zrobić to logowanie ręcznie :-)

Upload obrazka do OCRa robię w taki sposób [zakładam, że obrazek jest w lokalizacji E:\Projects\BLOG\OCRTest.jpg]:
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/jpg");
conn.setRequestProperty("Slug", "OCRd Doc");
String sourceFileName = "e:\\projects\\blog\\OCRtest.jpg";
FileInputStream fis = new FileInputStream(sourceFileName);
ByteArrayOutputStream baos = new ByteArrayOutputStream();

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

conn.setDoOutput(true);
conn.connect();

conn.getOutputStream().write(baos.toByteArray());
conn.getOutputStream().flush();
conn.getOutputStream().close();

BufferedReader br2 = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line2 = "";
while ((line2=br2.readLine())!=null) {
System.out.println(line2);
}

gdzie metoda int getStream(InputStream,OutputStream) jest podejrzanie podobna do tej :-)
I na koniec dostaję info o błędzie 403 :-(


Podobne postybeta
Toperz ;-) czyli OCR + Android odsłona 2 albo któraś tam
Programowanie trudne ;-)
PROPFIND, czyli jak przechytrzyć HttpURLConnection
Chrome OS, Chrome2Chrome i w ogóle Chrome ;-)
Wysyłamy pliki do Google Docs przy pomocy Go :-)