Java tutorial
/* * Copyright (C) 2009 Roberto Jacinto * roberto.jacinto@caixamagica.pt * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package cm.aptoide.pt; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.net.UnknownHostException; import java.util.Vector; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.apache.http.HttpResponse; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.util.EntityUtils; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import android.app.AlertDialog; import android.app.ProgressDialog; import android.app.TabActivity; import android.app.AlertDialog.Builder; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.DialogInterface.OnClickListener; import android.content.res.Configuration; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.TabHost; import android.widget.Toast; public class RemoteInTab extends TabActivity { private String LOCAL_PATH = "/sdcard/.aptoide"; private String ICON_PATH = LOCAL_PATH + "/icons"; private String XML_PATH = LOCAL_PATH + "/remapklst.xml"; private String EXTRAS_XML_PATH = LOCAL_PATH + "/extras.xml"; private String REMOTE_FILE = "/info.xml"; private String REMOTE_EXTRAS_FILE = "/extras.xml"; private static final int UPDATE_REPO = Menu.FIRST; private static final int MANAGE_REPO = 2; private static final int SEARCH_MENU = 3; private static final int SETTINGS = 4; private static final int ABOUT = 5; private static final int SETTINGS_FLAG = 31; private static final int NEWREPO_FLAG = 33; private DbHandler db = null; private ProgressDialog pd; private Context mctx = this; private String order_lst = "abc"; private TabHost myTabHost; private SharedPreferences sPref; private SharedPreferences.Editor prefEdit; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); File local_path = new File(LOCAL_PATH); if (!local_path.exists()) local_path.mkdir(); File icon_path = new File(ICON_PATH); if (!icon_path.exists()) icon_path.mkdir(); db = new DbHandler(this); sPref = getSharedPreferences("aptoide_prefs", MODE_PRIVATE); prefEdit = sPref.edit(); prefEdit.putBoolean("update", true); prefEdit.commit(); myTabHost = getTabHost(); myTabHost.addTab(myTabHost.newTabSpec("avail") .setIndicator("Available", getResources().getDrawable(android.R.drawable.ic_menu_add)) .setContent(new Intent(this, TabAvailable.class))); myTabHost.addTab(myTabHost.newTabSpec("inst") .setIndicator("Installed", getResources().getDrawable(android.R.drawable.ic_menu_agenda)) .setContent(new Intent(this, TabInstalled.class))); myTabHost.addTab(myTabHost.newTabSpec("updt") .setIndicator("Updates", getResources().getDrawable(android.R.drawable.ic_menu_info_details)) .setContent(new Intent(this, TabUpdates.class))); myTabHost.setPersistentDrawingCache(ViewGroup.PERSISTENT_SCROLLING_CACHE); Vector<ServerNode> srv_lst = db.getServers(); if (srv_lst.isEmpty()) { Intent call = new Intent(this, ManageRepo.class); call.putExtra("empty", true); call.putExtra("uri", "http://apps.aptoide.org"); startActivityForResult(call, NEWREPO_FLAG); } Intent i = getIntent(); if (i.hasExtra("uri")) { Intent call = new Intent(this, ManageRepo.class); call.putExtra("uri", i.getStringExtra("uri")); startActivityForResult(call, NEWREPO_FLAG); } else if (i.hasExtra("newrepo")) { Intent call = new Intent(this, ManageRepo.class); call.putExtra("newrepo", i.getStringExtra("newrepo")); startActivityForResult(call, NEWREPO_FLAG); } } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); menu.add(Menu.NONE, UPDATE_REPO, 1, R.string.menu_update_repo).setIcon(android.R.drawable.ic_menu_rotate); menu.add(Menu.NONE, MANAGE_REPO, 2, R.string.menu_manage).setIcon(android.R.drawable.ic_menu_agenda); menu.add(Menu.NONE, SEARCH_MENU, 3, R.string.menu_search).setIcon(android.R.drawable.ic_menu_search); menu.add(Menu.NONE, SETTINGS, 4, R.string.menu_settings).setIcon(android.R.drawable.ic_menu_preferences); menu.add(Menu.NONE, ABOUT, 5, R.string.menu_about).setIcon(android.R.drawable.ic_menu_help); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case UPDATE_REPO: final AlertDialog upd_alrt = new AlertDialog.Builder(this).create(); if (!db.areServers()) { upd_alrt.setIcon(android.R.drawable.ic_dialog_alert); upd_alrt.setTitle("Empty"); upd_alrt.setMessage( "There are no enabled repositories in your list.\nPlease add repository or enable the ones you have!"); upd_alrt.setButton("Ok", new OnClickListener() { public void onClick(DialogInterface dialog, int which) { } }); } else { upd_alrt.setIcon(android.R.drawable.ic_dialog_alert); upd_alrt.setTitle("Update repositories"); upd_alrt.setMessage( "Do you wish to update repositories?\nThis can take a while (WiFi is advised)..."); upd_alrt.setButton("Yes", new OnClickListener() { public void onClick(DialogInterface dialog, int which) { updateRepos(); } }); upd_alrt.setButton2("No", new OnClickListener() { public void onClick(DialogInterface dialog, int which) { upd_alrt.dismiss(); } }); } upd_alrt.show(); return true; case MANAGE_REPO: Intent i = new Intent(this, ManageRepo.class); startActivityForResult(i, NEWREPO_FLAG); return true; case SEARCH_MENU: onSearchRequested(); return true; case ABOUT: LayoutInflater li = LayoutInflater.from(this); View view = li.inflate(R.layout.about, null); Builder p = new AlertDialog.Builder(this).setView(view); final AlertDialog alrt = p.create(); alrt.setIcon(R.drawable.icon); alrt.setTitle("APTOIDE"); alrt.setButton("ChangeLog", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { Uri uri = Uri.parse("http://aptoide.com/changelog.html"); startActivity(new Intent(Intent.ACTION_VIEW, uri)); } }); alrt.show(); return true; case SETTINGS: Intent s = new Intent(RemoteInTab.this, Settings.class); s.putExtra("order", order_lst); startActivityForResult(s, SETTINGS_FLAG); } return super.onOptionsItemSelected(item); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == NEWREPO_FLAG) { if (data != null && data.hasExtra("update")) { final AlertDialog alrt = new AlertDialog.Builder(this).create(); alrt.setTitle("Update repositories"); alrt.setMessage("The list of repositories in use has been changed.\nDo you wish to update them?"); alrt.setButton("Yes", new OnClickListener() { public void onClick(DialogInterface dialog, int which) { updateRepos(); } }); alrt.setButton2("No", new OnClickListener() { public void onClick(DialogInterface dialog, int which) { alrt.dismiss(); } }); alrt.show(); } } else if (requestCode == SETTINGS_FLAG) { if (data != null && data.hasExtra("align")) { order_lst = data.getExtras().getString("align"); prefEdit.putString("order_lst", order_lst); prefEdit.commit(); } } } public boolean updateRepos() { pd = ProgressDialog.show(this, "Please Wait", "Updating applications list...", true); pd.setIcon(android.R.drawable.ic_dialog_info); //Check for connection first! ConnectivityManager netstate = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); if (netstate.getNetworkInfo(1).getState() == NetworkInfo.State.CONNECTED || netstate.getNetworkInfo(0).getState() == NetworkInfo.State.CONNECTED) { db.removeAll(); myTabHost.setCurrentTabByTag("inst"); new Thread() { public void run() { try { Vector<ServerNode> serv = db.getServers(); for (ServerNode node : serv) { if (node.inuse) { downloadList(node.uri); xmlPass(node.uri, true); } } } catch (Exception e) { } update_handler.sendEmptyMessage(0); } }.start(); return true; } else { pd.dismiss(); Toast.makeText(RemoteInTab.this, "Could not connect to the network.", Toast.LENGTH_LONG).show(); return false; } } /* * Pass XML info to BD * @type: true - info.xml * false - extras.xml */ private void xmlPass(String srv, boolean type) { SAXParserFactory spf = SAXParserFactory.newInstance(); try { File xml_file = null; SAXParser sp = spf.newSAXParser(); XMLReader xr = sp.getXMLReader(); if (type) { RssHandler handler = new RssHandler(this, srv); xr.setContentHandler(handler); xml_file = new File(XML_PATH); } else { ExtrasRssHandler handler = new ExtrasRssHandler(this, srv); xr.setContentHandler(handler); xml_file = new File(EXTRAS_XML_PATH); } InputStreamReader isr = new FileReader(xml_file); InputSource is = new InputSource(isr); xr.parse(is); xml_file.delete(); } catch (IOException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } } /* * Get extras.xml file from server and save it in the SD card */ private void downloadExtras(String srv) { String url = srv + REMOTE_EXTRAS_FILE; try { FileOutputStream saveit = new FileOutputStream(LOCAL_PATH + REMOTE_EXTRAS_FILE); HttpParams httpParameters = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParameters, 5000); HttpConnectionParams.setSoTimeout(httpParameters, 5000); DefaultHttpClient mHttpClient = new DefaultHttpClient(httpParameters); HttpGet mHttpGet = new HttpGet(url); String[] logins = null; logins = db.getLogin(srv); if (logins != null) { URL mUrl = new URL(url); mHttpClient.getCredentialsProvider().setCredentials(new AuthScope(mUrl.getHost(), mUrl.getPort()), new UsernamePasswordCredentials(logins[0], logins[1])); } HttpResponse mHttpResponse = mHttpClient.execute(mHttpGet); if (mHttpResponse.getStatusLine().getStatusCode() == 401) { /*Message msg = new Message(); msg.obj = new String(srv); secure_error_handler.sendMessage(msg);*/ } else { byte[] buffer = EntityUtils.toByteArray(mHttpResponse.getEntity()); saveit.write(buffer); } } catch (UnknownHostException e) { } catch (ClientProtocolException e) { } catch (IOException e) { } } /* * Get info.xml file from server and save it in the SD card */ private void downloadList(String srv) { String url = srv + REMOTE_FILE; try { FileOutputStream saveit = new FileOutputStream(XML_PATH); HttpParams httpParameters = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParameters, 5000); HttpConnectionParams.setSoTimeout(httpParameters, 5000); DefaultHttpClient mHttpClient = new DefaultHttpClient(httpParameters); HttpGet mHttpGet = new HttpGet(url); String[] logins = null; logins = db.getLogin(srv); if (logins != null) { URL mUrl = new URL(url); mHttpClient.getCredentialsProvider().setCredentials(new AuthScope(mUrl.getHost(), mUrl.getPort()), new UsernamePasswordCredentials(logins[0], logins[1])); } HttpResponse mHttpResponse = mHttpClient.execute(mHttpGet); if (mHttpResponse.getStatusLine().getStatusCode() == 401) { Message msg = new Message(); msg.obj = new String(srv); secure_error_handler.sendMessage(msg); } else { byte[] buffer = EntityUtils.toByteArray(mHttpResponse.getEntity()); saveit.write(buffer); } } catch (UnknownHostException e) { Message msg = new Message(); msg.obj = new String(srv); error_handler.sendMessage(msg); } catch (ClientProtocolException e) { } catch (IOException e) { } } /* * Handlers for thread functions that need to access GUI */ private Handler update_handler = new Handler() { @Override public void handleMessage(Message msg) { prefEdit.putBoolean("update", true); prefEdit.commit(); myTabHost.setCurrentTabByTag("avail"); if (pd.isShowing()) pd.dismiss(); new Thread() { public void run() { try { Vector<ServerNode> serv = db.getServers(); for (ServerNode node : serv) { if (node.inuse) { downloadExtras(node.uri); xmlPass(node.uri, false); } } } catch (Exception e) { } } }.start(); } }; private Handler secure_error_handler = new Handler() { @Override public void handleMessage(Message msg) { if (pd.isShowing()) pd.dismiss(); AlertDialog p = new AlertDialog.Builder(mctx).create(); p.setTitle("Login required"); p.setIcon(android.R.drawable.ic_dialog_alert); p.setMessage("Server: \"" + msg.obj.toString() + "\" requests login.\nCheck your username/password."); p.setButton("Ok", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { return; } }); p.show(); } }; private Handler error_handler = new Handler() { @Override public void handleMessage(Message msg) { if (pd.isShowing()) pd.dismiss(); final AlertDialog p = new AlertDialog.Builder(mctx).create(); p.setTitle("Time out"); p.setIcon(android.R.drawable.ic_dialog_alert); p.setMessage("Could not connect to server: " + msg.obj.toString()); p.setButton("Ok", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { p.dismiss(); } }); p.show(); } }; @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); } }