/** DR Radio 2 is developed by Jacob Nordfalk, Hanafi Mughrabi and Frederik Aagaard. Some parts of the code are loosely based on Sveriges Radio Play for Android. DR Radio 2 for Android is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. DR Radio 2 for Android 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 DR Radio 2 for Android. If not, see <http://www.gnu.org/licenses/>. */ package dk.dr.radio.diverse; import android.app.Activity; import android.app.AlertDialog.Builder; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.media.AudioManager; import android.os.Build; import com.crashlytics.android.Crashlytics; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import dk.dr.radio.data.DRData; /** * Loggerklasse * - hvor man slipper for at angive tag * - man kan logge objekter (få kaldt toString) * - cirkulær buffer tillader at man kan gemme loggen til fejlrapportering * @author j */ public class Log { public static final String TAG = "DRRadio"; private static final StringBuilder log = new StringBuilder(18000); /** * Føjer data til loggen. * Er loggen blevet for lang trimmes den. * Er synkroniseret da der enkelte gange er blevet set crashes fordi der blev skrevet * loggen samtidig med at den var ved at blive trimmet. * Af performancehensyn bør logning nok begrænses til kun at omfatte det vi som udviklere * tror vil afhjælpe en evt senere fejlfinding */ private static synchronized void logappend(String s) { if (log.length() > 57500) { log.delete(0, 10000); } // Roterende log int n = s.length(); if (n > 10000) n = 10000; log.append(s, 0, n); log.append('\n'); } public static synchronized String getLog() { return log.toString(); } /** * Logfunktion uden TAG som tager et objekt. Sparer bytekode og tid */ public static void d(Object o) { String s = String.valueOf(o); logappend(s); if (App.instans == null || App.IKKE_Android_VM) { System.out.println(o); return; // Hop ud hvis vi ikke kører i en Android VM } android.util.Log.d(TAG, s); } public static void e(Throwable e) { e("fejl", e); } public static void e(String tekst, Throwable e) { if (e == null) e = new Exception(tekst); if (App.instans == null || App.IKKE_Android_VM) { System.err.println(tekst); e.printStackTrace(); return; // Hop ud hvis vi ikke kører i en Android VM } android.util.Log.e(TAG, tekst, e); //e.printStackTrace(); logappend(tekst); logappend(android.util.Log.getStackTraceString(e)); } static int fejlRapporteret = 0; public static void rapporterFejl(final Throwable e) { Log.e(e); if (fejlRapporteret++ > 2) return; // rapportér ikke mere end 2 fejl per kørsel if (!App.EMULATOR) { Crashlytics.logException(e); //Mint.logException(e); if (!App.PRODUKTION && App.instans!=null) App.langToast("fejl: " + e); } } public static void rapporterFejl(final Throwable e, final Object f) { Log.e("" + f, e); if (fejlRapporteret++ > 2) return; // rapportér ikke mere end 2 fejl per kørsel if (!App.EMULATOR) { Crashlytics.log("fejl " + f); Crashlytics.logException(e); //Mint.logExceptionMessage("fejl", "" + f, e); } if (!App.PRODUKTION && App.instans!=null) App.langToast("Fejl: " + f); } public static void rapporterOgvisFejl(final Activity akt, final Exception e) { if (!App.EMULATOR) { Crashlytics.logException(e); //Mint.logException(e); } Log.e(e); Builder ab = new Builder(akt); ab.setTitle("Beklager, der skete en fejl"); ab.setMessage(e.toString()); ab.setNegativeButton("Fortsæt", null); ab.setPositiveButton("Indsend fejl", new Dialog.OnClickListener() { public void onClick(DialogInterface arg0, int arg1) { String brødtekst = "Skriv, hvad der skete:\n\n\n---\n"; brødtekst += "\nFejlspor;\n" + android.util.Log.getStackTraceString(e); brødtekst += "\n\n" + lavKontaktinfo(); App.kontakt(akt, "Fejl DR Radio", brødtekst, Log.log.toString()); } }); ab.create().show(); } public static void fejlantagelse(String fejl) { IllegalStateException e = new IllegalStateException(fejl); if (!App.PRODUKTION) throw e; else Log.rapporterFejl(e); } //private static LinkedHashMap<String, String> afprøvedeTing = new LinkedHashMap<String, String>(); public static final void registrérTestet(String hvad, String res) { return; //afprøvedeTing.put(hvad, res); } public static String lavKontaktinfo() { String ret = ""; try { /* for (String afprøvet : afprøvedeTing.keySet()) { ret += "\n" + afprøvet + ": " + afprøvedeTing.get(afprøvet); } ret += "\nOvenstående er korrekt: JA/NEJ\n\n"; PackageManager pm = instans.getPackageManager(); String version; try { PackageInfo pi = pm.getPackageInfo(instans.getPackageName(), 0); version = pi.versionName; } catch (Exception e) { version = e.toString(); e.printStackTrace(); } ret += instans.getPackageName() + " (v " + version + ")" + "\nTelefonmodel: " + Build.MODEL + " " + Build.PRODUCT + "\nAndroid v" + Build.VERSION.RELEASE + " (sdk: " + Build.VERSION.SDK + ")"; */ AudioManager am = (AudioManager) App.instans.getSystemService(Context.AUDIO_SERVICE); LinkedHashSet<String> udgange = new LinkedHashSet<>(); if (am.isBluetoothA2dpOn()) udgange.add("BluetoothA2dp"); if (am.isBluetoothScoOn()) udgange.add("BluetoothSco"); if (am.isSpeakerphoneOn()) udgange.add("Speakerphone"); if (am.isWiredHeadsetOn()) udgange.add("(Kablede høretelefoner forbundne)"); ret += "\nVersion: "+App.versionsnavn + "\nTelefonmodel: " + Build.MODEL + " " + Build.PRODUCT + "\nAndroid v" + Build.VERSION.RELEASE + " (sdk: " + Build.VERSION.SDK_INT + ")"; ret += "\nFunktioner brugt: "+ Sidevisning.getViste(); // ret += "\nFunktioner ej brugt: "+ Sidevisning.getIkkeViste(); ret += "\nIndstillinger: "+ App.prefs.getAll(); ret += "\nAfspiller: "+ DRData.instans.afspiller.toString(); ret += "\nUdgange: "+ udgange; } catch (Exception e) { Log.rapporterFejl(e); } return ret; } /** * Læser logcat, for Jelly Bean og senere kun fra *egen* proces, og behøver ikke nogen tilladelser. * For tidligere udgaver af Android skulle tilladelsen READ_LOGS med i manifestet, * og man fik log fra alle processer (hvilket var en sikkerhedsrisiko) * @param log */ public static void læsLogcat(StringBuilder log) { try { Process process = Runtime.getRuntime().exec("logcat -d"); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line = ""; while ((line = bufferedReader.readLine()) != null) { log.append(line).append("\n"); } } catch (Exception e) { Log.e(e); } } }