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.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringReader; import java.net.MalformedURLException; import java.net.URL; import java.util.List; import java.util.UUID; import java.util.Vector; import java.util.concurrent.TimeoutException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import android.app.Activity; import android.app.ActivityManager; import android.app.AlertDialog; import android.app.ProgressDialog; import android.app.ActivityManager.RunningTaskInfo; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.util.DisplayMetrics; import android.util.Log; import android.view.Window; import android.view.WindowManager; import android.widget.ProgressBar; public class Aptoide extends Activity { private static final int LOAD_TABS = 0; private static final int UPDATE_SELF = 99; private static final String TMP_SRV_FILE = Environment.getExternalStorageDirectory().getPath() + "/.aptoide/server"; private static final String TMP_UPDATE_FILE = Environment.getExternalStorageDirectory().getPath() + "/.aptoide/aptoideUpdate.apk"; private static final String LATEST_VERSION_CODE_URI = "http://aptoide.com/latest_version.xml"; private WakeLock keepScreenOn; private Intent DownloadQueueServiceIntent; private Vector<String> server_lst = null; private Vector<String[]> get_apks = null; // Used for Aptoide version update private DbHandler db = null; private SharedPreferences sPref; private SharedPreferences.Editor prefEdit; private PackageInfo pkginfo; private ProgressBar mProgress; private int mProgressStatus = 0; private Handler mHandler = new Handler(); private Handler startHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case LOAD_TABS: Intent i = new Intent(Aptoide.this, RemoteInTab.class); Intent get = getIntent(); if (get.getData() != null) { String uri = get.getDataString(); if (uri.startsWith("aptoiderepo")) { String repo = uri.substring(14); i.putExtra("newrepo", repo); } else if (uri.startsWith("aptoidexml")) { String repo = uri.substring(13); parseXmlString(repo); i.putExtra("uri", server_lst); if (get_apks.size() > 0) { //i.putExtra("uri", TMP_SRV_FILE); i.putExtra("apks", get_apks); } //i.putExtra("linkxml", repo); } else { downloadServ(uri); getRemoteServLst(TMP_SRV_FILE); i.putExtra("uri", server_lst); if (get_apks.size() > 0) { //i.putExtra("uri", TMP_SRV_FILE); i.putExtra("apks", get_apks); } } } startActivityForResult(i, 0); break; } super.handleMessage(msg); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); keepScreenOn = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, "Full Power"); DownloadQueueServiceIntent = new Intent(getApplicationContext(), DownloadQueueService.class); startService(DownloadQueueServiceIntent); //@dsilveira #534 +10lines Check if Aptoide is already running to avoid wasting time and showing the splash ActivityManager activityManager = (ActivityManager) getApplicationContext() .getSystemService(Context.ACTIVITY_SERVICE); List<RunningTaskInfo> running = activityManager.getRunningTasks(Integer.MAX_VALUE); for (RunningTaskInfo runningTask : running) { if (runningTask.baseActivity.getClassName().equals("cm.aptoide.pt.RemoteInTab")) { //RemoteInTab is the real Aptoide Activity Message msg = new Message(); msg.what = LOAD_TABS; startHandler.sendMessage(msg); return; } } Log.d("Aptoide", "******* \n Downloads will be made to: " + Environment.getExternalStorageDirectory().getPath() + "\n ********"); sPref = getSharedPreferences("aptoide_prefs", MODE_PRIVATE); prefEdit = sPref.edit(); db = new DbHandler(this); PackageManager mPm = getPackageManager(); try { pkginfo = mPm.getPackageInfo("cm.aptoide.pt", 0); } catch (NameNotFoundException e) { } requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); try { if (pkginfo.versionCode < Integer.parseInt(getXmlElement("versionCode"))) { Log.d("Aptoide-VersionCode", "Using version " + pkginfo.versionCode + ", suggest update!"); requestUpdateSelf(); } else { proceed(); } } catch (Exception e) { e.printStackTrace(); proceed(); } } private void proceed() { if (sPref.getInt("version", 0) < pkginfo.versionCode) { db.UpdateTables(); prefEdit.putBoolean("mode", true); prefEdit.putInt("version", pkginfo.versionCode); prefEdit.commit(); } if (sPref.getString("myId", null) == null) { String rand_id = UUID.randomUUID().toString(); prefEdit.putString("myId", rand_id); prefEdit.commit(); } if (sPref.getInt("scW", 0) == 0 || sPref.getInt("scH", 0) == 0) { DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); prefEdit.putInt("scW", dm.widthPixels); prefEdit.putInt("scH", dm.heightPixels); prefEdit.commit(); } if (sPref.getString("icdown", null) == null) { prefEdit.putString("icdown", "g3w"); prefEdit.commit(); } setContentView(R.layout.start); mProgress = (ProgressBar) findViewById(R.id.pbar); new Thread(new Runnable() { public void run() { Vector<ApkNode> apk_lst = db.getAll("abc"); mProgress.setMax(apk_lst.size()); PackageManager mPm; PackageInfo pkginfo; mPm = getPackageManager(); keepScreenOn.acquire(); for (ApkNode node : apk_lst) { if (node.status == 0) { try { pkginfo = mPm.getPackageInfo(node.apkid, 0); String vers = pkginfo.versionName; int verscode = pkginfo.versionCode; db.insertInstalled(node.apkid, vers, verscode); } catch (Exception e) { //Not installed anywhere... does nothing } } else { try { pkginfo = mPm.getPackageInfo(node.apkid, 0); String vers = pkginfo.versionName; int verscode = pkginfo.versionCode; db.UpdateInstalled(node.apkid, vers, verscode); } catch (Exception e) { db.removeInstalled(node.apkid); } } mProgressStatus++; // Update the progress bar mHandler.post(new Runnable() { public void run() { mProgress.setProgress(mProgressStatus); } }); } keepScreenOn.release(); Message msg = new Message(); msg.what = LOAD_TABS; startHandler.sendMessage(msg); } }).start(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case UPDATE_SELF: proceed(); break; default: super.onActivityResult(requestCode, resultCode, data); try { db.clodeDb(); } catch (Exception e) { Log.d("Aptoide", "Exit error: " + e.toString()); } finally { this.finish(); } break; } } private void downloadServ(String srv) { try { keepScreenOn.acquire(); BufferedInputStream getit = new BufferedInputStream(new URL(srv).openStream()); File file_teste = new File(TMP_SRV_FILE); if (file_teste.exists()) file_teste.delete(); FileOutputStream saveit = new FileOutputStream(TMP_SRV_FILE); BufferedOutputStream bout = new BufferedOutputStream(saveit, 1024); byte data[] = new byte[1024]; int readed = getit.read(data, 0, 1024); while (readed != -1) { bout.write(data, 0, readed); readed = getit.read(data, 0, 1024); } keepScreenOn.release(); bout.close(); getit.close(); saveit.close(); } catch (Exception e) { AlertDialog p = new AlertDialog.Builder(this).create(); p.setTitle(getText(R.string.top_error)); p.setMessage(getText(R.string.aptoide_error)); p.setButton(getText(R.string.btn_ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { return; } }); p.show(); } } private void getRemoteServLst(String file) { SAXParserFactory spf = SAXParserFactory.newInstance(); try { keepScreenOn.acquire(); SAXParser sp = spf.newSAXParser(); XMLReader xr = sp.getXMLReader(); NewServerRssHandler handler = new NewServerRssHandler(this); xr.setContentHandler(handler); InputStreamReader isr = new FileReader(new File(file)); InputSource is = new InputSource(isr); xr.parse(is); File xml_file = new File(file); xml_file.delete(); server_lst = handler.getNewSrvs(); get_apks = handler.getNewApks(); keepScreenOn.release(); } catch (IOException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } } private void parseXmlString(String file) { SAXParserFactory spf = SAXParserFactory.newInstance(); try { keepScreenOn.acquire(); SAXParser sp = spf.newSAXParser(); XMLReader xr = sp.getXMLReader(); NewServerRssHandler handler = new NewServerRssHandler(this); xr.setContentHandler(handler); InputSource is = new InputSource(); is.setCharacterStream(new StringReader(file)); xr.parse(is); server_lst = handler.getNewSrvs(); get_apks = handler.getNewApks(); keepScreenOn.release(); } catch (IOException e) { } catch (SAXException e) { } catch (ParserConfigurationException e) { } } private String getXmlElement(String name) throws ParserConfigurationException, MalformedURLException, SAXException, IOException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document dom = builder.parse(new InputSource(new URL(LATEST_VERSION_CODE_URI).openStream())); dom.getDocumentElement().normalize(); NodeList items = dom.getElementsByTagName(name); if (items.getLength() > 0) { Node item = items.item(0); Log.d("Aptoide-XmlElement Name", item.getNodeName()); Log.d("Aptoide-XmlElement Value", item.getFirstChild().getNodeValue().trim()); return item.getFirstChild().getNodeValue().trim(); } return "0"; } private void requestUpdateSelf() { AlertDialog.Builder alertBuilder = new AlertDialog.Builder(this); alertBuilder.setCancelable(false) .setPositiveButton(R.string.dialog_yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); new DownloadSelfUpdate().execute(); } }).setNegativeButton(R.string.dialog_no, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); proceed(); } }).setMessage(R.string.update_self_msg); AlertDialog alert = alertBuilder.create(); alert.setTitle(R.string.update_self_title); alert.setIcon(R.drawable.icon); alert.show(); } private class DownloadSelfUpdate extends AsyncTask<Void, Void, Void> { private final ProgressDialog dialog = new ProgressDialog(Aptoide.this); String latestVersionUri; String referenceMd5; void retrieveUpdateParameters() { try { latestVersionUri = getXmlElement("uri"); referenceMd5 = getXmlElement("md5"); } catch (Exception e) { e.printStackTrace(); Log.d("Aptoide-Auto-Update", "Update connection failed! Keeping current version."); } } @Override protected void onPreExecute() { this.dialog.setMessage("Retrieving update..."); this.dialog.show(); super.onPreExecute(); retrieveUpdateParameters(); } @Override protected Void doInBackground(Void... paramArrayOfParams) { try { if (latestVersionUri == null) { retrieveUpdateParameters(); } // Message msg_al = new Message(); // If file exists, removes it... File f_chk = new File(TMP_UPDATE_FILE); if (f_chk.exists()) { f_chk.delete(); } f_chk = null; FileOutputStream saveit = new FileOutputStream(TMP_UPDATE_FILE); DefaultHttpClient mHttpClient = new DefaultHttpClient(); HttpGet mHttpGet = new HttpGet(latestVersionUri); HttpResponse mHttpResponse = mHttpClient.execute(mHttpGet); if (mHttpResponse == null) { Log.d("Aptoide", "Problem in network... retry..."); mHttpResponse = mHttpClient.execute(mHttpGet); if (mHttpResponse == null) { Log.d("Aptoide", "Major network exception... Exiting!"); /*msg_al.arg1= 1; download_error_handler.sendMessage(msg_al);*/ throw new TimeoutException(); } } if (mHttpResponse.getStatusLine().getStatusCode() == 401) { throw new TimeoutException(); } else { InputStream getit = mHttpResponse.getEntity().getContent(); byte data[] = new byte[8096]; int bytesRead; bytesRead = getit.read(data, 0, 8096); while (bytesRead != -1) { // download_tick.sendEmptyMessage(readed); saveit.write(data, 0, bytesRead); bytesRead = getit.read(data, 0, 8096); } Log.d("Aptoide", "Download done!"); saveit.flush(); saveit.close(); getit.close(); } } catch (Exception e) { // download_error_handler.sendMessage(msg_al); e.printStackTrace(); Log.d("Aptoide-Auto-Update", "Update connection failed! Keeping current version."); } return null; } @Override protected void onPostExecute(Void result) { if (this.dialog.isShowing()) { this.dialog.dismiss(); } super.onPostExecute(result); if (!(referenceMd5 == null)) { try { File apk = new File(TMP_UPDATE_FILE); Md5Handler hash = new Md5Handler(); if (referenceMd5.equalsIgnoreCase(hash.md5Calc(apk))) { // msg_al.arg1 = 1; // download_handler.sendMessage(msg_al); doUpdateSelf(); } else { Log.d("Aptoide", referenceMd5 + " VS " + hash.md5Calc(apk)); // msg_al.arg1 = 0; // download_error_handler.sendMessage(msg_al); throw new Exception(referenceMd5 + " VS " + hash.md5Calc(apk)); } } catch (Exception e) { e.printStackTrace(); Log.d("Aptoide-Auto-Update", "Update package checksum failed! Keeping current version."); if (this.dialog.isShowing()) { this.dialog.dismiss(); } proceed(); super.onPostExecute(result); } } } } private void doUpdateSelf() { Intent intent = new Intent(); intent.setAction(android.content.Intent.ACTION_VIEW); intent.setDataAndType(Uri.parse("file://" + TMP_UPDATE_FILE), "application/vnd.android.package-archive"); startActivityForResult(intent, UPDATE_SELF); } @Override protected void onDestroy() { stopService(DownloadQueueServiceIntent); super.onDestroy(); } }