diff --git a/src/org/durka/hallmonitor/HMAppWidgetManager.java b/src/org/durka/hallmonitor/HMAppWidgetManager.java index 75b8403..bbf8539 100644 --- a/src/org/durka/hallmonitor/HMAppWidgetManager.java +++ b/src/org/durka/hallmonitor/HMAppWidgetManager.java @@ -115,6 +115,11 @@ public void configureWidget(String widgetType, Intent data) { AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager .getAppWidgetInfo(appWidgetId); + if (mStateManager.getCoverClosed()) { + Log.d(LOG_TAG + ".configureWidget", "needs to be worked out! doesn't work properly!"); + return; + } + // check if we need to configure if (appWidgetInfo.configure != null) { diff --git a/src/org/durka/hallmonitor/Logcat.java b/src/org/durka/hallmonitor/Logcat.java new file mode 100644 index 0000000..f41eafc --- /dev/null +++ b/src/org/durka/hallmonitor/Logcat.java @@ -0,0 +1,269 @@ +package org.durka.hallmonitor; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.media.MediaScannerConnection; +import android.os.Build; +import android.preference.Preference; +import android.util.Log; + +import java.io.BufferedReader; +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.security.DigestInputStream; +import java.security.KeyFactory; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.PublicKey; +import java.security.Security; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.RSAPublicKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; + +/** + * Created by habeIchVergessen on 02.10.2014. + */ +public class Logcat { + + public static File writeOutput(Context context) { + return writeOutput(context, null); + } + + public static File writeOutput(Context context, SharedPreferences prefs) { + String[] mPackageNames = context.getPackageName().split("(\\.|_)"); + + String mOutputName = "Logcat_"; + for (int i = 0; i < mPackageNames.length; i++) + mOutputName += mPackageNames[i].substring(0, 1).toUpperCase() + mPackageNames[i].substring(1); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss"); + mOutputName += "_" + sdf.format(new Date()) + ".log"; + + ArrayList log = getOutput(); + + String outDirName = "/storage/sdcard0/Download"; + File outFile = null; + try { + File outDir = new File(outDirName); + + if (!outDir.getParentFile().isDirectory()) { + Log.e("Logcat", "writeOutput: directory doesn't exists! '" + outDir.getAbsolutePath() + "'"); + return null; + } + + if (!outDir.isDirectory() && !outDir.mkdirs()) { + Log.e("Logcat", "writeOutput: can't create directory '" + outDir.getAbsolutePath() + "'"); + return null; + } + + outFile = new File(outDir, mOutputName); + outFile.createNewFile(); + + OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(outFile)); + + // build info's + out.write("hardware: " + Build.MANUFACTURER + " " + Build.MODEL + " (" + Build.DEVICE + ")\n"); + out.write("build: " + getBuildInfo() + "\n"); + out.write("os: " + Build.DISPLAY + " (" + System.getProperty("java.vm.name") + ")\n"); + out.write("kernel: " + System.getProperty("os.version") + "\n"); + out.write("\n"); + + // apk + String apkInfo = getApkInfo(context); + if ((apkInfo != null)) + out.write("apk:\n" + apkInfo + "\n"); + + // prefs + if (prefs != null) { + Map keys = prefs.getAll(); + + out.write("preferences:\n"); + for(Map.Entry entry : keys.entrySet()) { + out.write(" " + entry.getKey() + " = '" + entry.getValue().toString() + "'\n"); + } + out.write("\n"); + } + + for (int i=0; i < log.size(); i++) + if (!log.get(i).isEmpty()) + out.write(log.get(i)); + out.flush(); + out.close(); + + mOutputName = outFile.getAbsolutePath(); + } catch (Exception e) { + Log.e("Logcat", "writeOutput: exception occurred: '" + outDirName + File.pathSeparator + mOutputName + "', " + e.getMessage()); + return null; + } + + return outFile; + } + + public static ArrayList getOutput() { + ArrayList log = new ArrayList(); + + try { + ArrayList commandLine = new ArrayList(); + commandLine.add( "logcat"); + commandLine.add( "-d"); + commandLine.add( "-v"); + commandLine.add( "time"); + Process process = Runtime.getRuntime().exec( commandLine.toArray( new String[commandLine.size()])); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()), 1024); + + String line; + String matchAnyPid = ".*\\(\\ {0,9}\\d{1,}\\):.*"; + //String matchPid = ".*\\(\\ {0,9}" + android.os.Process.myPid() + "\\):.*"; + String matchPid = ".*\\(" + String.format("%5s", android.os.Process.myPid()) + "\\):.*"; + boolean pidMatched = false; + while ((line = bufferedReader.readLine()) != null) { + if (!pidMatched && line.matches(matchPid)) + pidMatched = true; + else if (pidMatched && line.matches(matchAnyPid) && !line.matches(matchPid)) + pidMatched = false; + + if (pidMatched) + log.add(line + "\n"); + } + } catch (IOException e) { + Log.e("Logcat", "getOutput: execption occurred: " + e.getMessage()); + } + + return log; + } + + private static String getBuildInfo() { + String buildInfo = null; + + try { + ArrayList commandLine = new ArrayList(); + commandLine.add("getprop"); + commandLine.add("ro.cm.display.version"); + Process process = Runtime.getRuntime().exec(commandLine.toArray(new String[commandLine.size()])); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()), 1024); + + buildInfo = bufferedReader.readLine(); + } catch (IOException e) { + } finally { + if (buildInfo == null) + buildInfo = Build.DEVICE + " " + new Date(Build.TIME); + } + + return buildInfo; + } + + private static String getApkInfo(Context context) { + String apkInfo = null, md5Hash, certInfo; + + ApplicationInfo applicationInfo = context.getApplicationInfo(); + File apkFile = new File(applicationInfo.sourceDir); + + String prefix = " "; + apkInfo = prefix + "file: " + apkFile.getName() + " (" + apkFile.getParentFile().getPath() + ")\n"; + apkInfo += prefix + "package: " + applicationInfo.packageName + "\n"; + + // md5 + if ((md5Hash = getMd5(apkFile)) != null) + apkInfo += prefix + "md5: " + md5Hash + "\n"; + + try { + ZipFile zf = new ZipFile(applicationInfo.sourceDir); + ZipEntry ze = zf.getEntry("AndroidManifest.xml"); + + // build date + if (ze != null) + apkInfo += prefix + "build: " + new Date(ze.getTime()) + "\n"; + + // signer + ze = zf.getEntry("META-INF/CERT.RSA"); + if (ze != null && (certInfo = getCertificateInfo(zf.getInputStream(ze))) != null) + apkInfo += prefix + "cert: " + certInfo + "\n"; + + // version + try { + PackageInfo packageInfo = context.getApplicationContext().getPackageManager().getPackageInfo(applicationInfo.packageName, 0); + apkInfo += prefix + "version: " + packageInfo.versionName + " (" + packageInfo.versionCode + ")\n"; + apkInfo += prefix + "install: " + new Date(packageInfo.firstInstallTime) + " (" + new Date(packageInfo.lastUpdateTime) + ")\n"; + } catch (PackageManager.NameNotFoundException e) { + } + } catch (IOException e) { + } + + return apkInfo; + } + + private static String getMd5(File inputFile) { + String returnVal = null; + + try + { + InputStream input = new FileInputStream(inputFile); + byte[] buffer = new byte[1024]; + MessageDigest md5Hash = MessageDigest.getInstance("MD5"); + int numRead = 0; + while (numRead != -1) + { + numRead = input.read(buffer); + if (numRead > 0) + { + md5Hash.update(buffer, 0, numRead); + } + } + input.close(); + + byte [] md5Bytes = md5Hash.digest(); + for (int i=0; i < md5Bytes.length; i++) { + if (i == 0) + returnVal = ""; + returnVal += Integer.toString( ( md5Bytes[i] & 0xff ) + 0x100, 16).substring( 1 ); + } + } catch(Throwable t) { + } + + return returnVal; + } + + private static String getCertificateInfo(InputStream inputStream) { + String certificateInfo = null; + + try { + try { + CertificateFactory certificateFactory = CertificateFactory.getInstance("X509"); + X509Certificate x509Certificate = (X509Certificate)certificateFactory.generateCertificate(inputStream); + + certificateInfo = x509Certificate.getSubjectDN().getName(); + certificateInfo += " (serial: " + x509Certificate.getSerialNumber() + ")"; + } catch (CertificateException ce) { + certificateInfo = "CertificateException: " + ce.getMessage(); + } + + inputStream.close(); + } catch (IOException e) { + certificateInfo = "IOException: " + e.getMessage(); + } + + return certificateInfo; + } +} diff --git a/src/org/durka/hallmonitor/PreferenceFragmentLoader.java b/src/org/durka/hallmonitor/PreferenceFragmentLoader.java index d013802..1d49773 100644 --- a/src/org/durka/hallmonitor/PreferenceFragmentLoader.java +++ b/src/org/durka/hallmonitor/PreferenceFragmentLoader.java @@ -26,6 +26,7 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.Color; +import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.preference.CheckBoxPreference; @@ -40,6 +41,9 @@ import android.view.View; import android.view.View.OnClickListener; import android.widget.Toast; + +import java.io.File; + import eu.chainfire.libsuperuser.Shell; public class PreferenceFragmentLoader extends PreferenceFragment implements @@ -104,6 +108,15 @@ public boolean onPreferenceClick(Preference preference) { mDebug = !prefs .getBoolean("pref_dev_opts_debug", false); // toggle // debug + if (!mDebug && prefs.getBoolean("pref_write_logcat_output", false)) { + File logcat = Logcat.writeOutput(getActivity().getBaseContext(), prefs); + + if (logcat != null && logcat.exists()) { + Toast.makeText(getActivity(), "wrote logcat output to '" + logcat.getAbsolutePath() + "'", Toast.LENGTH_LONG).show(); + // rescan media cache to show file via mtp + getActivity().sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(logcat))); + } + } prefs.edit().putBoolean("pref_dev_opts_debug", mDebug) .commit(); Toast.makeText( @@ -122,6 +135,8 @@ public boolean onPreferenceClick(Preference preference) { // mask text as disabled about.setTitle(getTextDisabledFormatted(about.getTitle())); about.setSummary(getTextDisabledFormatted(about.getSummary())); + + enableLogcat(getPreferenceManager().getSharedPreferences()); } } @@ -393,9 +408,9 @@ else if (key.equals("pref_do_notifications")) { else if (key.equals("pref_phone_controls_tts_delay")) { updatePhoneControlTtsDelay(prefs); - } - - ; + } else if (key.equals("pref_dev_opts_debug")) { + enableLogcat(prefs); + } // Special case of restart if (key.equals("pref_force_restart")) { @@ -456,7 +471,28 @@ private void enablePhoneScreen(SharedPreferences prefs) { } } - private void setSystemApp(SharedPreferences prefs) { + private void enableLogcat(SharedPreferences prefs) { + boolean enabled = prefs.getBoolean("pref_dev_opts_debug", false); + Preference cbr = findPreference("pref_write_logcat_output"); + + if (!enabled && cbr != null) { + prefs.edit().putBoolean(cbr.getKey(), false).commit(); + getPreferenceScreen().removePreference(cbr); + } + + if (enabled && cbr == null){ + Preference pAbout = findPreference("pref_about"); + cbr = new CheckBoxPreference(getActivity()); + cbr.setKey("pref_write_logcat_output"); + cbr.setDefaultValue(false); + cbr.setTitle("logcat to sdcard"); + cbr.setSummary("while disabling debug write logcat output to sdcard"); + cbr.setOrder(pAbout.getOrder() - 1); + getPreferenceScreen().addPreference(cbr); + } + } + + private void setSystemApp(SharedPreferences prefs) { if (mStateManager.getSystemApp()) { if (findPreference("pref_internal_power_management") != null) { findPreference("pref_internal_power_management").setEnabled(