Java tutorial
/******************************************************************************* * Copyright (c) 2010 Eugene Vorobkalo. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v2.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * * Contributors: * Eugene Vorobkalo - initial API and implementation ******************************************************************************/ package org.droidpres.activity; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.SocketTimeoutException; import java.sql.Date; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Timer; import java.util.TimerTask; import org.apache.http.conn.HttpHostConnectException; import org.droidpres.BaseApplication; import org.droidpres.R; import org.droidpres.db.DB; import org.droidpres.db.QueryHelper; import org.droidpres.utils.Const; import org.xmlrpc.android.XMLRPCClient; import org.xmlrpc.android.XMLRPCException; import org.xmlrpc.android.XMLRPCFault; import android.app.Activity; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.ContentValues; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager.NameNotFoundException; import android.database.Cursor; import android.database.DatabaseUtils.InsertHelper; import android.database.sqlite.SQLiteDatabase; import android.net.NetworkInfo; import android.net.Uri; import android.net.wifi.WifiManager; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.Window; import android.view.View.OnClickListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.Spinner; import android.widget.TextView; public class TransferActivity extends Activity implements OnClickListener { private static final int SERVER_MOBILE = 0; private static final int SERVER_WIFI = 1; private SQLiteDatabase mDataBase; private Integer mAgentId; private boolean mWiFiFlag, mWiFiConnectFlag, mImportFlag, mStartTransferFlag; private boolean isNewVersion = false; private String mURL; private TextView mTvTrLog; private Button mBtExport, mBtImport; private Spinner mSpNetType; private XMLRPCClient mClientXMLRPC; private WiFiStateReceiver mWifiStateReceiver; private WifiManager mWiFiManager; private IntentFilter mFilter; private DecimalFormat cf; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); setContentView(R.layout.transfer); cf = SetupRootActivity.getCurrencyFormat(this); mBtExport = (Button) findViewById(R.id.btExport); mBtImport = (Button) findViewById(R.id.btImport); mTvTrLog = (TextView) findViewById(R.id.tvTransferLog); mSpNetType = (Spinner) findViewById(R.id.spNetType); mBtImport.setOnClickListener(this); mBtExport.setOnClickListener(this); mDataBase = DB.get().getWritableDatabase(); ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.itemNetType, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mSpNetType.setAdapter(adapter); mAgentId = Integer.parseInt(SetupRootActivity.getAgentID(this)); } public void onClick(View v) { mTvTrLog.setText(""); switch (mSpNetType.getSelectedItemPosition()) { case SERVER_MOBILE: mURL = SetupRootActivity.getMobileServer(this); if (mURL.trim().length() == 0) { log(getString(R.string.err_ServerPort), "No setup url transfer server."); return; } setGuiEnabled(false); if (mURL.toLowerCase().indexOf("http://") < 0) mURL = "http://" + mURL + Const.RPC_PATH; if (v.getId() == R.id.btImport) new ImportFromRCD().execute(mURL); else new ExportToRCD().execute(mURL); break; case SERVER_WIFI: mURL = SetupRootActivity.getWiFiServer(this); if (mURL.trim().length() == 0) { log(getString(R.string.err_ServerPort), "No setup url transfer server."); return; } setGuiEnabled(false); if (mURL.toLowerCase().indexOf("http://") < 0) mURL = "http://" + mURL + Const.RPC_PATH; mImportFlag = v.getId() == R.id.btImport; mWiFiFlag = true; swichWiFi(); } } @Override protected void onStart() { super.onStart(); setBtExportEnable(); } @Override protected void onDestroy() { mDataBase.close(); super.onDestroy(); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN && mStartTransferFlag) return true; else return super.onKeyDown(keyCode, event); } private void setBtExportEnable() { Cursor cur = mDataBase.rawQuery("select count(*) + (select count(*) from " + DB.TABLE_LOCATION + ") from " + DB.TABLE_DOCUMENT + " where docstate = " + Const.DOCSTATE_PREPARE_SEND, null); if (cur.moveToFirst()) { boolean flag = cur.getInt(0) > 0; mBtExport.setEnabled(flag); } else { mBtExport.setEnabled(false); } cur.close(); } private void setGuiEnabled(boolean flag) { if (!flag) mBtExport.setEnabled(false); else setBtExportEnable(); mBtImport.setEnabled(flag); mSpNetType.setEnabled(flag); } private void log(String msg, String error) { if (error == null) { mTvTrLog.append(msg + "\n"); } else { mTvTrLog.append("\nERROR: " + error + "\n\n"); new AlertDialog.Builder(this).setMessage(msg).setTitle(android.R.string.dialog_alert_title) .setPositiveButton(android.R.string.ok, null).setCancelable(true).show(); } } private class ExportToRCD extends AsyncTask<String, String, Void> { @Override protected Void doInBackground(String... params) { try { publishProgress(getString(R.string.msg_StartExport), null); int send_doc_coun = 0; Cursor cur_docdet = null; Cursor cur_doc = mDataBase.rawQuery("select d.*, c.name, t.paytype1or2 " + "from document d inner join typedoc t on (t._id = d.typedoc_id) " + "inner join client c on (c._id = d.client_id) " + "where docstate = " + Const.DOCSTATE_PREPARE_SEND, null); mClientXMLRPC = new XMLRPCClient(params[0], SetupRootActivity.getHttpLogin(TransferActivity.this), SetupRootActivity.getHttpPasswd(TransferActivity.this)); QueryHelper qh_docdet = new QueryHelper(DB.TABLE_DOCUMENT_DET, null); //DataSet dsDocDet = new DataSet(sDataBase, DBDroidPres.TABLE_DOCUMENT_DET); Integer central_id = 0; final Map<String, Object> dict = new HashMap<String, Object>(); final List<Object> items = new ArrayList<Object>(); if (cur_doc.moveToFirst()) { do { final long _id = QueryHelper.fieldByNameLong(cur_doc, QueryHelper.KEY_ID); dict.clear(); dict.put("_id", _id); dict.put("agent_id", mAgentId); dict.put("presventype", QueryHelper.fieldByNameInt(cur_doc, "presventype")); dict.put("client_id", QueryHelper.fieldByNameInt(cur_doc, "client_id")); dict.put("docdate", QueryHelper.fieldByNameString(cur_doc, "docdate")); dict.put("doctime", QueryHelper.fieldByNameString(cur_doc, "doctime")); final String desc = QueryHelper.fieldByNameString(cur_doc, "description"); if (desc.length() > 0) dict.put("description", desc); dict.put("paytype", QueryHelper.fieldByNameInt(cur_doc, "paytype")); dict.put("paytype1or2", QueryHelper.fieldByNameInt(cur_doc, "paytype1or2")); dict.put("paymentdate", QueryHelper.fieldByNameString(cur_doc, "paymentdate")); dict.put("typedoc_id", QueryHelper.fieldByNameInt(cur_doc, "typedoc_id")); dict.put("itemcount", QueryHelper.fieldByNameFloat(cur_doc, "itemcount")); dict.put("mainsumm", QueryHelper.fieldByNameFloat(cur_doc, "mainsumm")); items.clear(); qh_docdet.appendFilter("DOCUMENT_ID", QueryHelper.FILTER_AND, "document_id = %d", _id); if (cur_docdet != null) cur_docdet.close(); cur_docdet = qh_docdet.createCurcor(mDataBase); if (cur_docdet.moveToFirst()) { do { Map<String, Object> mapDocDet = new HashMap<String, Object>(); mapDocDet.put("product_id", QueryHelper.fieldByNameInt(cur_docdet, "product_id")); mapDocDet.put("qty", QueryHelper.fieldByNameFloat(cur_docdet, "qty")); mapDocDet.put("price", QueryHelper.fieldByNameFloat(cur_docdet, "price")); items.add(mapDocDet); } while (cur_docdet.moveToNext()); Object[] XMLRPCDocParams = { dict, items }; central_id = (Integer) mClientXMLRPC.callEx("SetDoc", XMLRPCDocParams); publishProgress(QueryHelper.fieldByNameString(cur_doc, "name") + " " + QueryHelper.fieldByNameString(cur_doc, "docdate") + " " + cf.format(QueryHelper.fieldByNameFloat(cur_doc, "mainsumm")), null); if (central_id != null && central_id > 0) { ContentValues values = new ContentValues(); values.put("docstate", 2); values.put("central_id", central_id); mDataBase.update(DB.TABLE_DOCUMENT, values, QueryHelper.KEY_ID + " = " + _id, null); send_doc_coun++; } } } while (cur_doc.moveToNext()); cur_docdet.close(); cur_doc.close(); dict.clear(); items.clear(); final Cursor cur = mDataBase.query(DB.TABLE_LOCATION, null, null, null, null, null, null); if (cur.moveToFirst()) do { Map<String, Object> row = new HashMap<String, Object>(); row.put("date_location", cur.getString(0)); row.put("provider", cur.getString(1)); row.put("lat", cur.getInt(2)); row.put("lon", cur.getInt(3)); row.put("accuracy", cur.getInt(4)); items.add(row); } while (cur.moveToNext()); cur.close(); Object result = mClientXMLRPC.call("SetLocation", mAgentId, items); items.clear(); if ((Boolean) result) { mDataBase.delete(DB.TABLE_LOCATION, null, null); } } publishProgress(getString(R.string.msg_StopExport), null); publishProgress(getString(R.string.msg_SendDocCount, send_doc_coun), null); deleteOldRecords(); } catch (final XMLRPCFault e) { Log.e("Transfer", "XMLRPCFault", e); publishProgress(getString(R.string.err_XMLRPCFault), e.getMessage()); } catch (final XMLRPCException e) { Throwable couse = e.getCause(); if (couse instanceof HttpHostConnectException) { Log.e("Transfer", "HttpHostConnectException", e); publishProgress(getString(R.string.err_HttpHostConnectException), e.getMessage()); } else if (couse instanceof SocketTimeoutException) { Log.e("Transfer", "SocketTimeoutException", e); publishProgress(getString(R.string.err_SocketTimeoutException), e.getMessage()); } else { Log.e("Transfer", "XMLRPCException", e); publishProgress(getString(R.string.err_XMLRPCException), e.getMessage()); } } catch (Exception e) { Log.e("Transfer", "UnknownException", e); publishProgress(getString(R.string.err_UnknownException), e.toString()); } return null; } @Override protected void onProgressUpdate(String... progress) { log(progress[0], progress[1]); } @Override protected void onPreExecute() { super.onPreExecute(); setProgressBarIndeterminateVisibility(true); mStartTransferFlag = true; } @Override protected void onPostExecute(Void result) { super.onPostExecute(result); setProgressBarIndeterminateVisibility(false); mStartTransferFlag = false; if (mSpNetType.getSelectedItemPosition() == SERVER_WIFI) { mWiFiFlag = false; swichWiFi(); } setGuiEnabled(true); } } private class ImportFromRCD extends AsyncTask<String, String, Void> { @Override protected Void doInBackground(String... params) { try { publishProgress(getString(R.string.msg_StartImport, params[0]), null); mClientXMLRPC = new XMLRPCClient(params[0], SetupRootActivity.getHttpLogin(TransferActivity.this), SetupRootActivity.getHttpPasswd(TransferActivity.this)); publishProgress(getString(R.string.msg_GetRefClientGroup), null); getReferenceFromRCD(mDataBase, DB.TABLE_CLIENT_GROUP, "GetRefClientGroup"); publishProgress(getString(R.string.msg_GetRefClient), null); getReferenceFromRCD(mDataBase, DB.TABLE_CLIENT, "GetRefClient"); publishProgress(getString(R.string.msg_GetRefProductGroup), null); getReferenceFromRCD(mDataBase, DB.TABLE_PRODUCT_GROUP, "GetRefProductGroup"); publishProgress(getString(R.string.msg_GetRefProduct), null); getReferenceFromRCD(mDataBase, DB.TABLE_PRODUCT, "GetRefProduct"); publishProgress(getString(R.string.msg_GetRefTypeDoc), null); getReferenceFromRCD(mDataBase, DB.TABLE_TYPEDOC, "GetRefTypeDoc"); publishProgress(getString(R.string.msg_StopImport), null); isNewVersion = getUppdateApp(); deleteOldRecords(); } catch (final XMLRPCFault e) { Log.e("ImportFromRCD", "XMLRPCFault", e); publishProgress(getString(R.string.err_XMLRPCFault), e.toString()); } catch (final IOException e) { Log.e("ImportFromRCD", "IOException", e); publishProgress(getString(R.string.err_IOException), e.toString()); } catch (final NameNotFoundException e) { Log.e("ImportFromRCD", "NameNotFoundException", e); publishProgress(getString(R.string.err_NameNotFoundException), e.toString()); } catch (final XMLRPCException e) { Throwable couse = e.getCause(); if (couse instanceof HttpHostConnectException) { Log.e("ImportFromRCD", "HttpHostConnectException", e); publishProgress(getString(R.string.err_HttpHostConnectException), e.toString()); } else if (couse instanceof SocketTimeoutException) { Log.e("ImportFromRCD", "SocketTimeoutException", e); publishProgress(getString(R.string.err_SocketTimeoutException), e.toString()); } else { Log.e("ImportFromRCD", "XMLRPCException", e); publishProgress(getString(R.string.err_XMLRPCException), e.toString()); } } catch (Exception e) { Log.e("ImportFromRCD", "UnknownException", e); publishProgress(getString(R.string.err_UnknownException), e.toString()); } return null; } @Override protected void onProgressUpdate(String... progress) { log(progress[0], progress[1]); } @Override protected void onPreExecute() { super.onPreExecute(); setProgressBarIndeterminateVisibility(true); mStartTransferFlag = true; } @Override protected void onPostExecute(Void result) { super.onPostExecute(result); setProgressBarIndeterminateVisibility(false); mStartTransferFlag = false; if (mSpNetType.getSelectedItemPosition() == SERVER_WIFI) { mWiFiFlag = false; swichWiFi(); } setGuiEnabled(true); if (isNewVersion) updateApp(); } @SuppressWarnings("unchecked") private void getReferenceFromRCD(SQLiteDatabase db, String table_name, String method_name) throws Exception { final Object[] params = { mAgentId }; final Object result = mClientXMLRPC.callEx(method_name, params); final Object[] arr = (Object[]) result; publishProgress(getString(R.string.msg_ReturNRecords, arr.length), null); Map<String, Object> map; String[] fields = QueryHelper.getFieldsOnTable(db, table_name); Arrays.sort(fields); db.execSQL("delete from " + table_name); InsertHelper ih = new InsertHelper(db, table_name); int processedCount = 0; for (int row = 0; row < arr.length; row++) { map = (Map<String, Object>) arr[row]; ih.prepareForInsert(); for (String key : map.keySet()) { final String _key = key.toLowerCase(); if (Arrays.binarySearch(fields, _key) >= 0) { ih.bind(ih.getColumnIndex(_key), map.get(key).toString()); } if (_key.equals("name") && (Arrays.binarySearch(fields, "name_case") >= 0)) { ih.bind(ih.getColumnIndex("name_case"), map.get(key).toString().toUpperCase()); } } ih.execute(); processedCount++; } ih.close(); publishProgress(getString(R.string.msg_UpdateNRecords, processedCount), null); } private boolean getUppdateApp() throws XMLRPCException, IOException { byte[] data = (byte[]) mClientXMLRPC.callEx("GetUpdateApp", new Object[] { BaseApplication.VERSION_CODE }); if (data.length > 1) { File apkFile = new File(SetupRootActivity.getApkFileName()); apkFile.createNewFile(); FileOutputStream fOut = new FileOutputStream(apkFile); fOut.write(data); fOut.flush(); fOut.close(); return true; } else return false; } } public void swichWiFi() { mWiFiConnectFlag = false; IntentFilter filter = mFilter; WiFiStateReceiver receiver = mWifiStateReceiver; if (receiver == null) { receiver = new WiFiStateReceiver(); mWifiStateReceiver = receiver; filter = new IntentFilter(); filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); mFilter = filter; } this.registerReceiver(receiver, filter); getWiFiManager().setWifiEnabled(mWiFiFlag); if (mWiFiFlag) { new Timer().schedule(new TimerTask() { @Override public void run() { if (!mWiFiConnectFlag) { mWiFiFlag = false; getWiFiManager().setWifiEnabled(mWiFiFlag); } } }, 90000); } } class WiFiStateReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent == null) return; if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())) { switch (intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN)) { case WifiManager.WIFI_STATE_DISABLING: log(getString(R.string.msg_WiFiState_DISABLING), null); break; case WifiManager.WIFI_STATE_DISABLED: log(getString(R.string.msg_WiFiState_DISABLED), null); break; case WifiManager.WIFI_STATE_ENABLING: log(getString(R.string.msg_WiFiState_ENABLING), null); break; case WifiManager.WIFI_STATE_ENABLED: log(getString(R.string.msg_WiFiState_ENABLED), null); break; default: log(getString(R.string.msg_WiFiState_UNKNOWN), null); break; } } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(intent.getAction())) { NetworkInfo info = (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); switch (info.getDetailedState()) { case CONNECTING: log(getString(R.string.msg_NetworkState_CONNECTING), null); break; case OBTAINING_IPADDR: log(getString(R.string.msg_NetworkState_OBTAINING_IPADDR), null); break; case DISCONNECTING: log(getString(R.string.msg_NetworkState_DISCONNECTING), null); break; case DISCONNECTED: log(getString(R.string.msg_NetworkState_DISCONNECTED), null); break; case FAILED: log(getString(R.string.msg_NetworkState_FAILED), null); break; case CONNECTED: mWiFiConnectFlag = true; log(getString(R.string.msg_NetworkState_CONNECTED, getWiFiManager().getConnectionInfo().getSSID()), null); if (mWiFiFlag && !mStartTransferFlag) { if (mImportFlag) new ImportFromRCD().execute(mURL); else new ExportToRCD().execute(mURL); } break; } } } } private WifiManager getWiFiManager() { if (mWiFiManager == null) { mWiFiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); } return mWiFiManager; } private void updateApp() { new AlertDialog.Builder(this).setMessage(R.string.msg_UpdateApk) .setTitle(android.R.string.dialog_alert_title) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { File apkFile = new File(SetupRootActivity.getApkFileName()); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive"); startActivity(intent); } }).setCancelable(false).show(); } private void deleteOldRecords() { Calendar cl = Calendar.getInstance(); cl.add(Calendar.DAY_OF_MONTH, -30); Date sqlDate = new Date(cl.getTime().getTime()); mDataBase.execSQL("delete from document where docstate = ? and docdate < ?", new Object[] { Const.DOCSTATE_SEND, sqlDate.toString() }); } }