Commit 56cd3fa1 authored by Adrien Béraud's avatar Adrien Béraud
Browse files

add log activity

Change-Id: I32221a0907a79b2492405ad015120ca2eace1a6e
parent 4c19cdc7
...@@ -100,12 +100,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. ...@@ -100,12 +100,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<meta-data <meta-data
android:name="google_analytics_adid_collection_enabled" android:name="google_analytics_adid_collection_enabled"
android:value="false" /> android:value="false" />
<activity
android:name=".client.LogsActivity"
android:label="@string/pref_logs_title"
android:theme="@style/AppTheme.Navigation"
/>
<activity <activity
android:name=".client.HomeActivity" android:name=".client.HomeActivity"
android:configChanges="screenSize|screenLayout|smallestScreenSize" android:configChanges="screenSize|screenLayout|smallestScreenSize"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:launchMode="singleTask" android:launchMode="singleTask"
android:theme="@style/AppTheme.Navigation" android:theme="@style/AppTheme.Navigation"
android:windowSoftInputMode="adjustResize"> android:windowSoftInputMode="adjustResize">
...@@ -139,14 +144,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. ...@@ -139,14 +144,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<meta-data <meta-data
android:name="android.app.searchable" android:name="android.app.searchable"
android:resource="@xml/searchable" /> android:resource="@xml/searchable" />
<meta-data
<meta-data android:name="android.app.shortcuts" android:name="android.app.shortcuts"
android:resource="@xml/shortcuts"/> android:resource="@xml/shortcuts" />
</activity> </activity>
<activity <activity
android:name=".client.ShareActivity" android:name=".client.ShareActivity"
android:label="@string/title_share_with"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/title_share_with"
android:parentActivityName=".client.HomeActivity" android:parentActivityName=".client.HomeActivity"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme">
<intent-filter> <intent-filter>
...@@ -164,10 +169,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. ...@@ -164,10 +169,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<activity <activity
android:name=".account.AccountWizardActivity" android:name=".account.AccountWizardActivity"
android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize" android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize"
android:theme="@style/AppThemeBase.Light"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:resizeableActivity="true" android:resizeableActivity="true"
android:windowSoftInputMode="adjustResize"/> android:theme="@style/AppThemeBase.Light"
android:windowSoftInputMode="adjustResize" />
<activity <activity
android:name=".client.RingtoneActivity" android:name=".client.RingtoneActivity"
android:configChanges="screenSize|screenLayout|smallestScreenSize" android:configChanges="screenSize|screenLayout|smallestScreenSize"
...@@ -186,7 +191,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. ...@@ -186,7 +191,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<intent-filter> <intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" /> <action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="android.intent.action.ACTION_MY_PACKAGE_REPLACED"/> <action android:name="android.intent.action.ACTION_MY_PACKAGE_REPLACED" />
</intent-filter> </intent-filter>
</receiver> </receiver>
...@@ -207,8 +212,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. ...@@ -207,8 +212,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
android:foregroundServiceType="dataSync" /> android:foregroundServiceType="dataSync" />
<service <service
android:name=".services.LocationSharingService" android:name=".services.LocationSharingService"
android:foregroundServiceType="location" android:exported="false"
android:exported="false" /> android:foregroundServiceType="location" />
<activity <activity
android:name=".client.CallActivity" android:name=".client.CallActivity"
...@@ -280,8 +285,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. ...@@ -280,8 +285,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
android:name=".client.ConversationActivity" android:name=".client.ConversationActivity"
android:allowEmbedded="true" android:allowEmbedded="true"
android:configChanges="screenSize|screenLayout|smallestScreenSize" android:configChanges="screenSize|screenLayout|smallestScreenSize"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:parentActivityName=".client.HomeActivity" android:parentActivityName=".client.HomeActivity"
android:resizeableActivity="true" android:resizeableActivity="true"
android:theme="@style/AppTheme.Fullscreen" android:theme="@style/AppTheme.Fullscreen"
...@@ -293,34 +298,37 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. ...@@ -293,34 +298,37 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<intent-filter> <intent-filter>
<action android:name=".service.DRingService" /> <action android:name=".service.DRingService" />
</intent-filter> </intent-filter>
</service> </service> <!-- AndroidTV section -->
<!-- AndroidTV section -->
<activity <activity
android:name=".tv.main.HomeActivity" android:name=".tv.main.HomeActivity"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.Jami.Leanback.Main"> android:theme="@style/Theme.Jami.Leanback.Main">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" /> <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<data <data
android:scheme="jamitv"
android:host="cx.ring" android:host="cx.ring"
android:path="/home" /> android:path="/home"
android:scheme="jamitv" />
</intent-filter> </intent-filter>
</activity> </activity>
<receiver <receiver
android:name=".tv.main.ChannelActionHandler" android:name=".tv.main.ChannelActionHandler"
android:enabled="true" android:enabled="true"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<action android:name="android.media.tv.ACTION_INITIALIZE_PROGRAMS" /> <action android:name="android.media.tv.ACTION_INITIALIZE_PROGRAMS" />
<action android:name="android.media.tv.ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED" /> <action android:name="android.media.tv.ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED" />
<action android:name="android.media.tv.ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT" /> <action android:name="android.media.tv.ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT" />
...@@ -330,30 +338,30 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. ...@@ -330,30 +338,30 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<activity <activity
android:name=".tv.account.TVAccountWizard" android:name=".tv.account.TVAccountWizard"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize" android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" /> android:theme="@style/AppTheme" />
<activity <activity
android:name=".tv.search.SearchActivity" android:name=".tv.search.SearchActivity"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.Leanback" /> android:theme="@style/Theme.Leanback" />
<activity <activity
android:name=".tv.about.AboutActivity" android:name=".tv.about.AboutActivity"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.Leanback" /> android:theme="@style/Theme.Leanback" />
<activity <activity
android:name=".tv.account.TVShareActivity" android:name=".tv.account.TVShareActivity"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.Ring.Leanback" /> android:theme="@style/Theme.Ring.Leanback" />
<activity <activity
android:name=".tv.call.TVCallActivity" android:name=".tv.call.TVCallActivity"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize" android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:resizeableActivity="true" android:resizeableActivity="true"
android:showOnLockScreen="true" android:showOnLockScreen="true"
android:supportsPictureInPicture="true" android:supportsPictureInPicture="true"
...@@ -366,9 +374,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. ...@@ -366,9 +374,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
</activity> </activity>
<activity <activity
android:name=".tv.camera.CustomCameraActivity" android:name=".tv.camera.CustomCameraActivity"
android:theme="@style/AppTheme" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"> android:theme="@style/AppTheme">
<intent-filter> <intent-filter>
<action android:name="cx.ring.action.CALL" /> <action android:name="cx.ring.action.CALL" />
...@@ -377,20 +385,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. ...@@ -377,20 +385,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
</activity> </activity>
<activity <activity
android:name=".tv.contact.TVContactActivity" android:name=".tv.contact.TVContactActivity"
android:theme="@style/Theme.Leanback.Details" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"> android:theme="@style/Theme.Leanback.Details">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<data <data
android:scheme="jamitv"
android:host="cx.ring" android:host="cx.ring"
android:pathPrefix="/conversation/" /> android:pathPrefix="/conversation/"
android:scheme="jamitv" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
android:name=".tv.account.TVSettingsActivity" android:name=".tv.account.TVSettingsActivity"
android:theme="@style/LeanbackPreferences" /> android:theme="@style/LeanbackPreferences" />
...@@ -408,8 +417,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. ...@@ -408,8 +417,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<activity <activity
android:name=".client.MediaViewerActivity" android:name=".client.MediaViewerActivity"
android:exported="false" android:exported="false"
android:label="@string/title_media_viewer"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/title_media_viewer"
android:theme="@style/AppThemeBase.Dark" /> android:theme="@style/AppThemeBase.Dark" />
<service <service
...@@ -419,16 +428,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. ...@@ -419,16 +428,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<activity <activity
android:name=".client.ContactDetailsActivity" android:name=".client.ContactDetailsActivity"
android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize" android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize"
android:label="@string/conversation_details"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/conversation_details"
android:resizeableActivity="true" android:resizeableActivity="true"
android:theme="@style/AppTheme.Fullscreen" android:theme="@style/AppTheme.Fullscreen"
android:windowSoftInputMode="adjustResize" /> android:windowSoftInputMode="adjustResize" />
<activity <activity
android:name=".client.ConversationSelectionActivity" android:name=".client.ConversationSelectionActivity"
android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize" android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize"
android:label="Choose a contact or conversation"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="Choose a contact or conversation"
android:theme="@style/Theme.MaterialComponents.DayNight.Dialog.Alert" android:theme="@style/Theme.MaterialComponents.DayNight.Dialog.Alert"
android:windowSoftInputMode="adjustResize" /> android:windowSoftInputMode="adjustResize" />
</application> </application>
......
/*
* Copyright (C) 2004-2021 Savoir-faire Linux Inc.
*
* Author: Adrien Beraud <adrien.beraud@savoirfairelinux.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 cx.ring.client;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import com.google.android.material.snackbar.Snackbar;
import net.jami.services.HardwareService;
import net.jami.utils.StringUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import javax.inject.Inject;
import javax.inject.Singleton;
import cx.ring.R;
import cx.ring.application.JamiApplication;
import cx.ring.databinding.ActivityLogsBinding;
import cx.ring.utils.AndroidFileUtils;
import cx.ring.utils.ContentUriHandler;
import io.reactivex.Maybe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
public class LogsActivity extends AppCompatActivity {
private static final String TAG = LogsActivity.class.getSimpleName();
private ActivityLogsBinding binding;
private final CompositeDisposable compositeDisposable = new CompositeDisposable();
private Disposable disposable;
private ActivityResultLauncher<String> fileSaver;
private File mCurrentFile = null;
@Inject
@Singleton
HardwareService mHardwareService;
public LogsActivity() {
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
JamiApplication.getInstance().startDaemon();
JamiApplication.getInstance().getInjectionComponent().inject(this);
binding = ActivityLogsBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
ActionBar ab = getSupportActionBar();
if (ab != null)
ab.setDisplayHomeAsUpEnabled(true);
fileSaver = registerForActivityResult(new ActivityResultContracts.CreateDocument(), result -> compositeDisposable.add(
AndroidFileUtils.copyFileToUri(getContentResolver(), mCurrentFile, result).
observeOn(AndroidSchedulers.mainThread()).
subscribe(() -> {
if (!mCurrentFile.delete())
Log.w(TAG, "Can't delete temp file");
mCurrentFile = null;
Snackbar.make(binding.getRoot(), R.string.file_saved_successfully, Snackbar.LENGTH_SHORT).show();
}, error -> Snackbar.make(binding.getRoot(), R.string.generic_error, Snackbar.LENGTH_SHORT).show())));
binding.fab.setOnClickListener(view -> {
if (disposable == null)
startLogging();
else
stopLogging();
});
if (mHardwareService.isLogging())
startLogging();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.logs_menu, menu);
return super.onCreateOptionsMenu(menu);
}
private Maybe<String> getLog() {
if (mHardwareService.isLogging())
return mHardwareService.startLogs()
.firstElement();
CharSequence log = binding.logView.getText();
if (StringUtils.isEmpty(log))
return Maybe.empty();
return Maybe.just(log.toString());
}
private Maybe<File> getLogFile() {
return getLog()
.observeOn(Schedulers.io())
.map(log -> {
File file = AndroidFileUtils.createLogFile(this);
OutputStream os = new FileOutputStream(file);
os.write(log.getBytes());
return file;
});
}
private Maybe<Uri> getLogUri() {
return getLogFile().map(file -> ContentUriHandler.getUriForFile(this, ContentUriHandler.AUTHORITY_FILES, file));
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
finish();
return true;
} else if (id == R.id.menu_log_share) {
compositeDisposable.add(getLogUri()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(uri -> {
Log.w(TAG, "saved logs to " + uri);
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
String type = getContentResolver().getType(uri);
sendIntent.setDataAndType(uri, type);
sendIntent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(sendIntent, null));
}, e -> Snackbar.make(binding.getRoot(), "Error sharing logs: " + e.getLocalizedMessage(), Snackbar.LENGTH_SHORT).show()));
return true;
} else if (id == R.id.menu_log_save) {
compositeDisposable.add(getLogFile()
.subscribe(file -> {
mCurrentFile = file;
fileSaver.launch(file.getName());
}));
return true;
}
return super.onOptionsItemSelected(item);
}
void startLogging() {
binding.logView.setText("");
disposable = mHardwareService.startLogs()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(message -> {
binding.logView.setText(message);
binding.scroll.post(() -> binding.scroll.fullScroll(View.FOCUS_DOWN));
}, e -> Log.w(TAG, "Error in logger", e));
compositeDisposable.add(disposable);
setButtonState(true);
}
void stopLogging() {
disposable.dispose();
disposable = null;
mHardwareService.stopLogs();
setButtonState(false);
}
void setButtonState(boolean logging) {
binding.fab.setText(logging ? R.string.pref_logs_stop : R.string.pref_logs_start);
binding.fab.setBackgroundColor(ContextCompat.getColor(this, logging ? R.color.red_400 : R.color.colorSecondary));
}
@Override
protected void onDestroy() {
if (disposable != null) {
disposable.dispose();
disposable = null;
}
compositeDisposable.clear();
super.onDestroy();
}
}
\ No newline at end of file
...@@ -41,6 +41,7 @@ import cx.ring.application.JamiApplication; ...@@ -41,6 +41,7 @@ import cx.ring.application.JamiApplication;
import cx.ring.client.ContactDetailsActivity; import cx.ring.client.ContactDetailsActivity;
import cx.ring.client.ConversationSelectionActivity; import cx.ring.client.ConversationSelectionActivity;
import cx.ring.client.HomeActivity; import cx.ring.client.HomeActivity;
import cx.ring.client.LogsActivity;
import cx.ring.client.RingtoneActivity; import cx.ring.client.RingtoneActivity;
import cx.ring.contactrequests.BlockListFragment; import cx.ring.contactrequests.BlockListFragment;
import cx.ring.contactrequests.ContactRequestsFragment; import cx.ring.contactrequests.ContactRequestsFragment;
...@@ -232,4 +233,7 @@ public interface JamiInjectionComponent { ...@@ -232,4 +233,7 @@ public interface JamiInjectionComponent {
void inject(LinkDeviceFragment linkDeviceFragment); void inject(LinkDeviceFragment linkDeviceFragment);
void inject(ContactPickerFragment contactPickerFragment); void inject(ContactPickerFragment contactPickerFragment);
void inject(LogsActivity logsActivity);
} }
...@@ -20,10 +20,9 @@ ...@@ -20,10 +20,9 @@
package cx.ring.settings; package cx.ring.settings;
import android.app.Activity; import android.app.Activity;
import android.content.DialogInterface; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.ArrayRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
...@@ -43,6 +42,7 @@ import android.widget.Toast; ...@@ -43,6 +42,7 @@ import android.widget.Toast;
import cx.ring.R; import cx.ring.R;
import cx.ring.application.JamiApplication; import cx.ring.application.JamiApplication;
import cx.ring.client.HomeActivity; import cx.ring.client.HomeActivity;
import cx.ring.client.LogsActivity;
import cx.ring.databinding.FragSettingsBinding; import cx.ring.databinding.FragSettingsBinding;
import net.jami.daemon.JamiService; import net.jami.daemon.JamiService;
...@@ -142,18 +142,15 @@ public class SettingsFragment extends BaseSupportFragment<SettingsPresenter> imp ...@@ -142,18 +142,15 @@ public class SettingsFragment extends BaseSupportFragment<SettingsPresenter> imp
binding.settingsNotification.setOnClickListener(v -> new MaterialAlertDialogBuilder(view.getContext()) binding.settingsNotification.setOnClickListener(v -> new MaterialAlertDialogBuilder(