Java tutorial
/* * Copyright (C) 2008 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.hhunj.hhudata; import android.content.ContentUris; import android.app.Activity; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Intent; import android.content.res.Configuration; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.webkit.CookieManager; import android.webkit.CookieSyncManager; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import android.widget.TextView; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpHead; import org.apache.http.client.methods.HttpUriRequest; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import com.hhunj.hhudata.alarm.AndroidHttpClient; import com.hhunj.hhudata.alarm.Intents; import com.hhunj.hhudata.alarm.Intents.SearchBookContents; import com.hhunj.hhudata.db.NotePad; import com.hhunj.hhudata.db.SearchBookContentsResult; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import java.util.Date; import android.telephony.SmsManager; import android.app.PendingIntent; import android.content.IntentFilter; import android.widget.Toast; import android.content.BroadcastReceiver; import android.content.Context; /** * Uses Google Book Search to find a word or phrase in the requested book. * * @author dswitkin@google.com (Daniel Switkin) */ public final class SearchBookContentsActivity extends Activity { private static final String TAG = SearchBookContentsActivity.class.getSimpleName(); private static final String USER_AGENT = "ZXing (Android)"; private static final Pattern TAG_PATTERN = Pattern.compile("\\<.*?\\>"); private static final Pattern LT_ENTITY_PATTERN = Pattern.compile("<"); private static final Pattern GT_ENTITY_PATTERN = Pattern.compile(">"); private static final Pattern QUOTE_ENTITY_PATTERN = Pattern.compile("'"); private static final Pattern QUOT_ENTITY_PATTERN = Pattern.compile("""); private NetworkThread networkThread; private String isbn; private EditText queryTextView; private Button queryButton; private ListView resultListView; private TextView headerView; private final Handler handler = new Handler() { @Override public void handleMessage(Message message) { switch (message.what) { case R.id.search_book_contents_succeeded: handleSearchResults((JSONObject) message.obj); resetForNewQuery(); break; case R.id.search_book_contents_failed: resetForNewQuery(); headerView.setText(R.string.msg_sbc_failed); break; } } }; private final Button.OnClickListener buttonListener = new Button.OnClickListener() { public void onClick(View view) { launchSearch(); } }; private final View.OnKeyListener keyListener = new View.OnKeyListener() { public boolean onKey(View view, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_ENTER) { launchSearch(); return true; } return false; } }; String getISBN() { return isbn; } @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); // Make sure that expired cookies are removed on launch. CookieSyncManager.createInstance(this); CookieManager.getInstance().removeExpiredCookie(); Intent intent = getIntent(); if (intent == null || (!intent.getAction().equals(Intents.SearchBookContents.ACTION))) { finish(); return; } //pageid,pagenumber //ISBN ---stationid, isbn = intent.getStringExtra(Intents.SearchBookContents.ISBN);//stationid if (isbn.startsWith("http://google.com/books?id=")) { setTitle(getString(R.string.sbc_name)); } else { setTitle(getString(R.string.sbc_name) + ": ISBN " + isbn); } setContentView(R.layout.search_book_contents); queryTextView = (EditText) findViewById(R.id.query_text_view); String initialQuery = intent.getStringExtra(Intents.SearchBookContents.QUERY); if (initialQuery != null && initialQuery.length() > 0) { // Populate the search box but don't trigger the search queryTextView.setText(initialQuery); } queryTextView.setOnKeyListener(keyListener); queryButton = (Button) findViewById(R.id.query_button); queryButton.setOnClickListener(buttonListener); resultListView = (ListView) findViewById(R.id.result_list_view); LayoutInflater factory = LayoutInflater.from(this); headerView = (TextView) factory.inflate(R.layout.search_book_contents_header, resultListView, false); resultListView.addHeaderView(headerView); } @Override protected void onResume() { super.onResume(); queryTextView.selectAll(); } @Override public void onConfigurationChanged(Configuration config) { // Do nothing, this is to prevent the activity from being restarted when the keyboard opens. super.onConfigurationChanged(config); } private void resetForNewQuery() { networkThread = null; queryTextView.setEnabled(true); queryTextView.selectAll(); queryButton.setEnabled(true); } private void launchSearch() { if (networkThread == null) { String query = queryTextView.getText().toString(); if (query != null && query.length() > 0) { networkThread = new NetworkThread(isbn, query, handler); networkThread.start(); headerView.setText(R.string.msg_sbc_searching_book); resultListView.setAdapter(null); queryTextView.setEnabled(false); queryButton.setEnabled(false); } } } //////////////////////////////////////// public void updatedb(List<SearchBookContentsResult> items) { int max_alarm_time_span = 60; ContentResolver resolver = getApplicationContext().getContentResolver(); ContentValues values = new ContentValues(); for (int i = 0; i < items.size(); i++) { SearchBookContentsResult res = items.get(i); long stationid = Long.parseLong(res.getPageNumber()); values.put(NotePad.Notes.TITLE, res.getName()); values.put(NotePad.Notes.NOTE, ""); values.put(NotePad.Notes.LONGITUTE, 108.0); values.put(NotePad.Notes.LATITUDE, 32.0); values.put(NotePad.Notes.SPEED, 55); values.put(NotePad.Notes.ALTITUDE, 55); values.put(NotePad.Notes.CREATEDDATE, res.getRectime().getTime()); values.put(NotePad.Notes._ID, stationid);//id Uri urlNote = NotePad.Notes.CONTENT_URI; Uri myUri = ContentUris.withAppendedId(NotePad.Notes.CONTENT_URI, stationid); Cursor cur = resolver.query(myUri, NotePad.Notes.PROJECTION, null, null, null); if (cur != null && cur.moveToFirst()) { try { long id = cur.getLong(NotePad.Notes._ID_COLUMN); Date oldtime = new Date(cur.getLong(cur.getColumnIndex(NotePad.Notes.CREATEDDATE))); boolean oldalarm = (cur.getInt(NotePad.Notes.ALARM_COLUMN) == 0) ? false : true; long dif = (res.getRectime().getTime() - oldtime.getTime()) / (60 * 1000); dif = ((new Date()).getTime() - oldtime.getTime()) / (60 * 1000); if (dif > max_alarm_time_span) { //... if (oldalarm == false) { Log.w(TAG, "over time err--------"); String phoneNumber = "13338620269"; String message = "over time err--------"; sendSMS(phoneNumber, message); values.put(NotePad.Notes.ALARM, true); } } else { values.put(NotePad.Notes.ALARM, false); } } catch (Exception e) { int aa = 0; } int count = resolver.update(myUri, values, null, null); // resolver.update( myUri, values, NotePad.Notes._ID + " = " +res.getPageNumber(), null); if (count == 0) { } } else { try { myUri = resolver.insert(urlNote, values); } catch (IllegalArgumentException e) { throw e; } } } } private void sendSMS(String phoneNumber, String message) { // ---sends an SMS message to another device--- SmsManager sms = SmsManager.getDefault(); String SENT_SMS_ACTION = "SENT_SMS_ACTION"; String DELIVERED_SMS_ACTION = "DELIVERED_SMS_ACTION"; // create the sentIntent parameter Intent sentIntent = new Intent(SENT_SMS_ACTION); PendingIntent sentPI = PendingIntent.getBroadcast(this, 0, sentIntent, 0); // create the deilverIntent parameter Intent deliverIntent = new Intent(DELIVERED_SMS_ACTION); PendingIntent deliverPI = PendingIntent.getBroadcast(this, 0, deliverIntent, 0); // register the Broadcast Receivers registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context _context, Intent _intent) { switch (getResultCode()) { case Activity.RESULT_OK: Toast.makeText(getBaseContext(), "SMS sent success actions", Toast.LENGTH_SHORT).show(); break; case SmsManager.RESULT_ERROR_GENERIC_FAILURE: Toast.makeText(getBaseContext(), "SMS generic failure actions", Toast.LENGTH_SHORT).show(); break; case SmsManager.RESULT_ERROR_RADIO_OFF: Toast.makeText(getBaseContext(), "SMS radio off failure actions", Toast.LENGTH_SHORT).show(); break; case SmsManager.RESULT_ERROR_NULL_PDU: Toast.makeText(getBaseContext(), "SMS null PDU failure actions", Toast.LENGTH_SHORT).show(); break; } } }, new IntentFilter(SENT_SMS_ACTION)); registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context _context, Intent _intent) { Toast.makeText(getBaseContext(), "SMS delivered actions", Toast.LENGTH_SHORT).show(); } }, new IntentFilter(DELIVERED_SMS_ACTION)); // if message's length more than 70 , // then call divideMessage to dive message into several part ,and call // sendTextMessage() // else direct call sendTextMessage() if (message.length() > 70) { ArrayList<String> msgs = sms.divideMessage(message); for (String msg : msgs) { sms.sendTextMessage(phoneNumber, null, msg, sentPI, deliverPI); } } else { sms.sendTextMessage(phoneNumber, null, message, sentPI, deliverPI); } } // Currently there is no way to distinguish between a query which had no results and a book // which is not searchable - both return zero results. private void handleSearchResults(JSONObject json) { try { String s = json.toString(); int count = json.getInt("number_of_results"); headerView.setText("Found " + (count == 1 ? "1 result" : count + " results")); if (count > 0) { JSONArray results = json.getJSONArray("search_results"); SearchBookContentsResult.setQuery(queryTextView.getText().toString()); List<SearchBookContentsResult> items = new ArrayList<SearchBookContentsResult>(count); for (int x = 0; x < count; x++) { items.add(parseResult(results.getJSONObject(x))); } //... //.... updatedb(items); // resultListView.setOnItemClickListener(new BrowseBookListener(this, items)); // resultListView.setAdapter(new SearchBookContentsAdapter(this, items)); } else // { //.... // String searchable = json.optString("searchable"); if ("false".equals(searchable)) { headerView.setText(R.string.msg_sbc_book_not_searchable); } resultListView.setAdapter(null); } } catch (JSONException e) { //.... //... Log.w(TAG, "Bad JSON from book search", e); resultListView.setAdapter(null); headerView.setText(R.string.msg_sbc_failed); } } public static Date JsonToDateTime(String jsonDate) { String value = jsonDate.substring(6, jsonDate.length() - 2); //DateTimeKind kind = DateTimeKind.Utc; int kind = 0; long h = 0; long m = 0; int index = value.indexOf('+', 1); if (index == -1) { index = value.indexOf('-', 1); } else { kind = 1; } if (index != -1) { if (kind == 0) { kind = -1; } String offset = value.substring(index + 1); String hour = offset.substring(0, 2); String minite = offset.substring(2); h = Long.parseLong(hour) * 3600 * 1000; m = Long.parseLong(minite) * 60 * 1000; } value = value.substring(0, index); long javaScriptTicks = kind * Long.parseLong(value) + h + m; //getTime() : 1228494414199 197011 Date utcDateTime = new Date((javaScriptTicks)); return utcDateTime; } // Available fields: page_id, page_number, page_url, snippet_text private SearchBookContentsResult parseResult(JSONObject json) { try { String pageId = json.getString("page_id"); String pageNumber = json.getString("page_number"); if (pageNumber.length() > 0) { // pageNumber = getString(R.string.msg_sbc_page) + ' ' + pageNumber; } else { // This can happen for text on the jacket, and possibly other reasons. //pageNumber = getString(R.string.msg_sbc_unknown_page); pageNumber = null; } // Remove all HTML tags and encoded characters. Ideally the server would do this. String snippet = json.optString("snippet_text"); boolean valid = true; if (snippet.length() > 0) { snippet = TAG_PATTERN.matcher(snippet).replaceAll(""); snippet = LT_ENTITY_PATTERN.matcher(snippet).replaceAll("<"); snippet = GT_ENTITY_PATTERN.matcher(snippet).replaceAll(">"); snippet = QUOTE_ENTITY_PATTERN.matcher(snippet).replaceAll("'"); snippet = QUOT_ENTITY_PATTERN.matcher(snippet).replaceAll("\""); } else { snippet = '(' + getString(R.string.msg_sbc_snippet_unavailable) + ')'; valid = false; } //new Date(+/\d+/.exec(value)[1]); Date date = JsonToDateTime(json.getString("rectime")); return new SearchBookContentsResult(pageId, pageNumber, snippet, valid, date); } catch (JSONException e) { Date date = new Date(); // Never seen in the wild, just being complete. return new SearchBookContentsResult(getString(R.string.msg_sbc_no_page_returned), "", "", false, date); } } /////////////////////////////////////////////////////////////////// private static final class NetworkThread extends Thread { private final String isbn; private final String query; private final Handler handler; NetworkThread(String isbn, String query, Handler handler) { this.isbn = isbn; this.query = query; this.handler = handler; } @Override public void run() { qureyAlarm(); } void qureyAlarm() { AndroidHttpClient client = null; try { // These return a JSON result which describes if and where the query was found. This API may // break or disappear at any time in the future. Since this is an API call rather than a // website, we don't use LocaleManager to change the TLD. URI uri; //androidsimulatorlocalhost,localhost127.0.0.1 uri = new URI("http", null, "192.168.2.103", 16666, "/hhudata/alarm.ashx", "", null); // //{"number_of_results":0,"search_query_escaped":"","searchable":true} HttpUriRequest get = new HttpGet(uri); get.setHeader("cookie", getCookie(uri.toString())); client = AndroidHttpClient.newInstance(USER_AGENT); HttpResponse response = client.execute(get); if (response.getStatusLine().getStatusCode() == 200) { //url HttpEntity entity = response.getEntity(); ByteArrayOutputStream jsonHolder = new ByteArrayOutputStream(); entity.writeTo(jsonHolder); jsonHolder.flush(); //JSONArray jarray=new JSONArray(jsonHolder.toString(getEncoding(entity))); JSONObject json = new JSONObject(jsonHolder.toString(getEncoding(entity))); jsonHolder.close(); Message message = Message.obtain(handler, R.id.search_book_contents_succeeded); message.obj = json; message.sendToTarget(); } else { Log.w(TAG, "HTTP returned " + response.getStatusLine().getStatusCode() + " for " + uri); Message message = Message.obtain(handler, R.id.search_book_contents_failed); message.sendToTarget(); } } catch (Exception e) { Log.w(TAG, "Error accessing book search", e); Message message = Message.obtain(handler, R.id.search_book_contents_failed); message.sendToTarget(); } finally { if (client != null) { client.close(); } } } // Book Search requires a cookie to work, which we store persistently. If the cookie does // not exist, this could be the first search or it has expired. Either way, do a quick HEAD // request to fetch it, save it via the CookieSyncManager to flash, then return it. private static String getCookie(String url) { String cookie = CookieManager.getInstance().getCookie(url); if (cookie == null || cookie.length() == 0) { Log.d(TAG, "Book Search cookie was missing or expired"); HttpUriRequest head = new HttpHead(url); AndroidHttpClient client = AndroidHttpClient.newInstance(USER_AGENT); try { HttpResponse response = client.execute(head); if (response.getStatusLine().getStatusCode() == 200) { Header[] cookies = response.getHeaders("set-cookie"); for (Header theCookie : cookies) { CookieManager.getInstance().setCookie(url, theCookie.getValue()); } CookieSyncManager.getInstance().sync(); cookie = CookieManager.getInstance().getCookie(url); } } catch (IOException e) { Log.w(TAG, "Error setting book search cookie", e); } client.close(); } return cookie; } private static String getEncoding(HttpEntity entity) { // FIXME: The server is returning ISO-8859-1 but the content is actually windows-1252. // Once Jeff fixes the HTTP response, remove this hardcoded value and go back to getting // the encoding dynamically. return "windows-1252"; // HeaderElement[] elements = entity.getContentType().getElements(); // if (elements != null && elements.length > 0) { // String encoding = elements[0].getParameterByName("charset").getValue(); // if (encoding != null && encoding.length() > 0) { // return encoding; // } // } // return "UTF-8"; } } }