瀏覽代碼

Initial file logging

Signed-off-by: Mario Danic <mario@lovelyhq.com>
Mario Danic 6 年之前
父節點
當前提交
ef2d1b8c92

+ 3 - 3
app/build.gradle

@@ -162,9 +162,9 @@ dependencies {
     implementation 'com.bluelinelabs:conductor:2.1.5'
     implementation 'com.bluelinelabs:conductor-support:2.1.5'
 
-    implementation 'com.squareup.okhttp3:okhttp:3.13.1'
-    implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.13.1'
-    implementation 'com.squareup.okhttp3:logging-interceptor:3.13.1'
+    implementation 'com.squareup.okhttp3:okhttp:3.14.2'
+    implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.14.2'
+    implementation 'com.squareup.okhttp3:logging-interceptor:3.14.2'
 
     implementation 'com.bluelinelabs:logansquare:1.3.7'
     implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.9.8'

+ 13 - 0
app/src/main/AndroidManifest.xml

@@ -99,5 +99,18 @@
         <service
             android:exported="false"
             android:name="com.novoda.merlin.MerlinService" />
+
+        <provider
+            android:name="androidx.core.content.FileProvider"
+            android:grantUriPermissions="true"
+            android:exported="false"
+            android:authorities="${applicationId}">
+
+            <meta-data
+                android:name="android.support.FILE_PROVIDER_PATHS"
+                android:resource="@xml/file_provider_paths"/>
+
+        </provider>
+
     </application>
 </manifest>

+ 1 - 1
app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.java

@@ -183,7 +183,7 @@ public class NextcloudTalkApplication extends MultiDexApplication implements Lif
                 .busModule(new BusModule())
                 .contextModule(new ContextModule(getApplicationContext()))
                 .databaseModule(new DatabaseModule())
-                .restModule(new RestModule())
+                .restModule(new RestModule(getApplicationContext()))
                 .userModule(new UserModule())
                 .arbitraryStorageModule(new ArbitraryStorageModule())
                 .build();

+ 9 - 4
app/src/main/java/com/nextcloud/talk/controllers/SettingsController.java

@@ -44,6 +44,7 @@ import androidx.work.OneTimeWorkRequest;
 import androidx.work.WorkManager;
 import autodagger.AutoInjector;
 import butterknife.BindView;
+import butterknife.OnClick;
 import com.bluelinelabs.conductor.RouterTransaction;
 import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
 import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler;
@@ -59,10 +60,7 @@ import com.nextcloud.talk.controllers.base.BaseController;
 import com.nextcloud.talk.jobs.AccountRemovalWorker;
 import com.nextcloud.talk.models.RingtoneSettings;
 import com.nextcloud.talk.models.database.UserEntity;
-import com.nextcloud.talk.utils.ApiUtils;
-import com.nextcloud.talk.utils.DisplayUtils;
-import com.nextcloud.talk.utils.DoNotDisturbUtils;
-import com.nextcloud.talk.utils.SecurityUtils;
+import com.nextcloud.talk.utils.*;
 import com.nextcloud.talk.utils.bundle.BundleKeys;
 import com.nextcloud.talk.utils.database.user.UserUtils;
 import com.nextcloud.talk.utils.preferences.AppPreferences;
@@ -321,6 +319,13 @@ public class SettingsController extends BaseController {
         }
     }
 
+    @OnClick(R.id.settings_version)
+    void sendLogs() {
+        if (getResources().getBoolean(R.bool.nc_is_debug)) {
+            LoggingUtils.sendMailWithAttachment(context);
+        }
+    }
+
     @Override
     protected void onSaveViewState(@NonNull View view, @NonNull Bundle outState) {
         saveStateHandler.saveInstanceState(outState);

+ 25 - 6
app/src/main/java/com/nextcloud/talk/dagger/modules/RestModule.java

@@ -20,15 +20,18 @@
  */
 package com.nextcloud.talk.dagger.modules;
 
+import android.content.Context;
 import android.text.TextUtils;
 import android.util.Log;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import com.github.aurae.retrofit2.LoganSquareConverterFactory;
 import com.nextcloud.talk.BuildConfig;
+import com.nextcloud.talk.R;
 import com.nextcloud.talk.api.NcApi;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.utils.ApiUtils;
+import com.nextcloud.talk.utils.LoggingUtils;
 import com.nextcloud.talk.utils.database.user.UserUtils;
 import com.nextcloud.talk.utils.preferences.AppPreferences;
 import com.nextcloud.talk.utils.singletons.AvatarStatusCodeHolder;
@@ -62,6 +65,11 @@ import java.util.concurrent.TimeUnit;
 public class RestModule {
 
     private static final String TAG = "RestModule";
+    private final Context context;
+
+    public RestModule(Context context) {
+        this.context = context;
+    }
 
     @Singleton
     @Provides
@@ -179,12 +187,6 @@ public class RestModule {
         httpClient.cookieJar(new JavaNetCookieJar(cookieManager));
         httpClient.cache(cache);
 
-        if (BuildConfig.DEBUG) {
-            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
-            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
-            httpClient.addInterceptor(loggingInterceptor);
-        }
-
         // Trust own CA and all self-signed certs
         httpClient.sslSocketFactory(sslSocketFactoryCompat, magicTrustManager);
         httpClient.retryOnConnectionFailure(true);
@@ -205,6 +207,23 @@ public class RestModule {
 
         httpClient.addInterceptor(new HeadersInterceptor());
 
+        if (BuildConfig.DEBUG && !context.getResources().getBoolean(R.bool.nc_is_debug)) {
+            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
+            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
+            loggingInterceptor.redactHeader("Authorization");
+            loggingInterceptor.redactHeader("Proxy-Authorization");
+            httpClient.addInterceptor(loggingInterceptor);
+        } else if (context.getResources().getBoolean(R.bool.nc_is_debug)) {
+
+            HttpLoggingInterceptor.Logger fileLogger =
+                    s -> LoggingUtils.writeLogEntryToFile(context, s);
+            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(fileLogger);
+            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
+            loggingInterceptor.redactHeader("Authorization");
+            loggingInterceptor.redactHeader("Proxy-Authorization");
+            httpClient.addInterceptor(loggingInterceptor);
+        }
+
         return httpClient.build();
     }
 

+ 77 - 0
app/src/main/java/com/nextcloud/talk/utils/LoggingUtils.java

@@ -0,0 +1,77 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.talk.utils;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import androidx.core.content.FileProvider;
+import com.nextcloud.talk.BuildConfig;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class LoggingUtils {
+    public static void writeLogEntryToFile(Context context, String logEntry) {
+        DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+        Date date = new Date();
+        String logEntryWithDateTime = dateFormat.format(date) + ": " + logEntry + "\n";
+
+        try {
+            FileOutputStream outputStream = context.openFileOutput("nc_log.txt",
+                    Context.MODE_PRIVATE | Context.MODE_APPEND);
+            outputStream.write(logEntryWithDateTime.getBytes());
+            outputStream.flush();
+            outputStream.close();
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static void sendMailWithAttachment(Context context) {
+        File logFile = context.getFileStreamPath("nc_log.txt");
+        Intent emailIntent = new Intent(Intent.ACTION_SEND);
+        String mailto = "mario@nextcloud.com";
+        emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{mailto});
+        emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Talk logs");
+        emailIntent.setType("text/plain");
+        emailIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        Uri uri;
+
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
+            uri = Uri.fromFile(logFile);
+        } else {
+            uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID, logFile);
+        }
+
+        emailIntent.putExtra(Intent.EXTRA_STREAM, uri);
+        emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        context.startActivity(emailIntent);
+    }
+}

+ 1 - 0
app/src/main/res/values/setup.xml

@@ -23,6 +23,7 @@
     <!-- Set before a release -->
     <string name="nc_talk_database_encryption_key" translatable="false">HvAfHtAy/QdFYqAWFFXa1VV_Iv6ZQ1.tf5swMc^45wS_vz=Wm[oyRP5D-</string>
     <string name="nc_talk_login_scheme" translatable="false">nc</string>
+    <bool name="nc_is_debug">true</bool>
 
     <string name="nc_app_name">Nextcloud Talk</string>
     <string name="nc_server_product_name">Nextcloud</string>

+ 23 - 0
app/src/main/res/xml/file_provider_paths.xml

@@ -0,0 +1,23 @@
+<!--
+  ~ Nextcloud Talk application
+  ~
+  ~ @author Mario Danic
+  ~ Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
+  ~
+  ~ 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 3 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, see <http://www.gnu.org/licenses/>.
+  -->
+
+<paths>
+    <files-path name="files" path="/" />
+</paths>