1
0
mirror of https://github.com/oliexdev/openScale.git synced 2025-09-01 12:23:15 +02:00

App intro (#526)

added App intro slides
This commit is contained in:
OliE
2019-12-09 18:26:00 +01:00
committed by GitHub
parent f038a2792e
commit 78ff154edc
48 changed files with 1640 additions and 248 deletions

View File

@@ -60,7 +60,7 @@ android {
}
dependencies {
implementation 'com.google.android.material:material:1.1.0-beta01'
implementation 'com.google.android.material:material:1.2.0-alpha01'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.recyclerview:recyclerview:1.0.0'
@@ -72,10 +72,12 @@ dependencies {
implementation 'com.github.weliem:blessed-android:0.10'
// CustomActivityOnCrash
implementation 'cat.ereza:customactivityoncrash:2.2.0'
// AppIntro
implementation 'com.github.AppIntro:AppIntro:5.1.0'
// Room
implementation 'androidx.room:room-runtime:2.2.0'
annotationProcessor 'androidx.room:room-compiler:2.2.0'
androidTestImplementation 'androidx.room:room-testing:2.2.0'
implementation 'androidx.room:room-runtime:2.2.1'
annotationProcessor 'androidx.room:room-compiler:2.2.1'
androidTestImplementation 'androidx.room:room-testing:2.2.1'
// Timber
implementation 'com.jakewharton.timber:timber:4.7.1'
// Local unit tests

View File

@@ -38,6 +38,8 @@
<activity android:name=".gui.activities.SettingsActivity"/>
<activity android:name=".gui.activities.DataEntryActivity"/>
<activity android:name=".gui.activities.UserSettingsActivity"/>
<activity android:name=".gui.activities.BluetoothSettingsActivity"/>
<activity android:name=".gui.activities.AppIntroActivity"/>
<receiver android:name=".core.alarm.ReminderBootReceiver" android:enabled="false">
<intent-filter>

View File

@@ -55,15 +55,15 @@ import com.health.openscale.core.OpenScale;
import com.health.openscale.core.bluetooth.BluetoothCommunication;
import com.health.openscale.core.datatypes.ScaleMeasurement;
import com.health.openscale.core.datatypes.ScaleUser;
import com.health.openscale.gui.activities.AppIntroActivity;
import com.health.openscale.gui.activities.BaseAppCompatActivity;
import com.health.openscale.gui.activities.BluetoothSettingsActivity;
import com.health.openscale.gui.activities.DataEntryActivity;
import com.health.openscale.gui.activities.SettingsActivity;
import com.health.openscale.gui.activities.UserSettingsActivity;
import com.health.openscale.gui.fragments.GraphFragment;
import com.health.openscale.gui.fragments.OverviewFragment;
import com.health.openscale.gui.fragments.StatisticsFragment;
import com.health.openscale.gui.fragments.TableFragment;
import com.health.openscale.gui.preferences.BluetoothPreferences;
import java.io.File;
import java.util.List;
@@ -150,9 +150,8 @@ public class MainActivity extends BaseAppCompatActivity
}
if (prefs.getBoolean("firstStart", true)) {
Intent intent = new Intent(this, UserSettingsActivity.class);
intent.putExtra(UserSettingsActivity.EXTRA_MODE, UserSettingsActivity.ADD_USER_REQUEST);
startActivity(intent);
Intent appIntroIntent = new Intent(this, AppIntroActivity.class);
startActivity(appIntroIntent);
prefs.edit().putBoolean("firstStart", false).apply();
}
@@ -479,9 +478,9 @@ public class MainActivity extends BaseAppCompatActivity
}
String deviceName = prefs.getString(
BluetoothPreferences.PREFERENCE_KEY_BLUETOOTH_DEVICE_NAME, "");
BluetoothSettingsActivity.PREFERENCE_KEY_BLUETOOTH_DEVICE_NAME, "");
String hwAddress = prefs.getString(
BluetoothPreferences.PREFERENCE_KEY_BLUETOOTH_HW_ADDRESS, "");
BluetoothSettingsActivity.PREFERENCE_KEY_BLUETOOTH_HW_ADDRESS, "");
if (!BluetoothAdapter.checkBluetoothAddress(hwAddress)) {
setBluetoothStatusIcon(R.drawable.ic_bluetooth_connection_lost);

View File

@@ -0,0 +1,87 @@
/* Copyright (C) 2019 olie.xdev <olie.xdev@googlemail.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.health.openscale.gui.activities;
import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.github.paolorotolo.appintro.AppIntro;
import com.health.openscale.R;
import com.health.openscale.core.OpenScale;
import com.health.openscale.gui.slides.BluetoothIntroSlide;
import com.health.openscale.gui.slides.MetricsIntroSlide;
import com.health.openscale.gui.slides.OpenSourceIntroSlide;
import com.health.openscale.gui.slides.PrivacyIntroSlide;
import com.health.openscale.gui.slides.SupportIntroSlide;
import com.health.openscale.gui.slides.UserIntroSlide;
import com.health.openscale.gui.slides.WelcomeIntroSlide;
public class AppIntroActivity extends AppIntro {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setBarColor(getResources().getColor(R.color.blue_normal));
setWizardMode(true);
setBackButtonVisibilityWithDone(true);
showSkipButton(true);
addSlide(WelcomeIntroSlide.newInstance(R.layout.slide_welcome));
addSlide(PrivacyIntroSlide.newInstance(R.layout.slide_privacy));
addSlide(UserIntroSlide.newInstance(R.layout.slide_user));
addSlide(OpenSourceIntroSlide.newInstance(R.layout.slide_opensource));
addSlide(BluetoothIntroSlide.newInstance(R.layout.slide_bluetooth));
addSlide(MetricsIntroSlide.newInstance(R.layout.slide_metrics));
addSlide(SupportIntroSlide.newInstance(R.layout.slide_support));
}
@Override
public void onSkipPressed(Fragment currentFragment) {
super.onSkipPressed(currentFragment);
finish();
checkUserCreation();
}
@Override
public void onDonePressed(Fragment currentFragment) {
super.onDonePressed(currentFragment);
finish();
checkUserCreation();
}
@Override
public void onSlideChanged(@Nullable Fragment oldFragment, @Nullable Fragment newFragment) {
super.onSlideChanged(oldFragment, newFragment);
if (newFragment instanceof WelcomeIntroSlide) {
showSkipButton(true);
} else {
showSkipButton(false);
}
}
private void checkUserCreation() {
if (OpenScale.getInstance().getSelectedScaleUserId() == -1) {
Intent intent = new Intent(this, UserSettingsActivity.class);
intent.putExtra(UserSettingsActivity.EXTRA_MODE, UserSettingsActivity.ADD_USER_REQUEST);
startActivity(intent);
}
}
}

View File

@@ -0,0 +1,396 @@
/* Copyright (C) 2019 olie.xdev <olie.xdev@googlemail.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.health.openscale.gui.activities;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.preference.Preference;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.widget.Toolbar;
import androidx.core.graphics.drawable.DrawableCompat;
import com.health.openscale.R;
import com.health.openscale.core.OpenScale;
import com.health.openscale.core.bluetooth.BluetoothCommunication;
import com.health.openscale.core.bluetooth.BluetoothFactory;
import com.health.openscale.core.datatypes.ScaleUser;
import com.health.openscale.core.utils.Converters;
import com.health.openscale.gui.preferences.BluetoothPreferences;
import com.health.openscale.gui.utils.ColorUtil;
import com.health.openscale.gui.utils.PermissionHelper;
import com.welie.blessed.BluetoothCentral;
import com.welie.blessed.BluetoothCentralCallback;
import com.welie.blessed.BluetoothPeripheral;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import timber.log.Timber;
public class BluetoothSettingsActivity extends BaseAppCompatActivity {
private Context context;
public static final int GET_SCALE_REQUEST = 150;
public static final String PREFERENCE_KEY_BLUETOOTH_DEVICE_NAME = "btDeviceName";
public static final String PREFERENCE_KEY_BLUETOOTH_HW_ADDRESS = "btHwAddress";
private Map<String, BluetoothDevice> foundDevices = new HashMap<>();
private LinearLayout deviceListView;
private TextView txtSearching;
private ProgressBar progressBar;
private Handler progressHandler;
private BluetoothCentral central;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bluetoothsettings);
context = this;
deviceListView = findViewById(R.id.deviceListView);
txtSearching = findViewById(R.id.txtSearching);
progressBar = findViewById(R.id.progressBar);
Toolbar toolbar = findViewById(R.id.bluetoothSettingToolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle(R.string.label_bluetooth_title);
if (PermissionHelper.requestBluetoothPermission(this)) {
if (PermissionHelper.requestLocationServicePermission(this)) {
startBluetoothDiscovery();
}
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// Override the default behaviour in order to return to the correct fragment
// (e.g. the table view) and not always go to the overview.
case android.R.id.home:
stopBluetoothDiscovery();
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
private static final String formatDeviceName(String name, String address) {
if (name.isEmpty() || address.isEmpty()) {
return "-";
}
return String.format("%s [%s]", name, address);
}
private static final String formatDeviceName(BluetoothDevice device) {
return formatDeviceName(device.getName(), device.getAddress());
}
private final BluetoothCentralCallback bluetoothCentralCallback = new BluetoothCentralCallback() {
@Override
public void onDiscoveredPeripheral(BluetoothPeripheral peripheral, ScanResult scanResult) {
onDeviceFound(scanResult);
}
};
private void startBluetoothDiscovery() {
deviceListView.removeAllViews();
foundDevices.clear();
central = new BluetoothCentral(getApplicationContext(), bluetoothCentralCallback, new Handler(Looper.getMainLooper()));
central.scanForPeripherals();
txtSearching.setVisibility(View.VISIBLE);
txtSearching.setText(R.string.label_bluetooth_searching);
progressBar.setVisibility(View.VISIBLE);
progressHandler = new Handler();
// Don't let the BLE discovery run forever
progressHandler.postDelayed(new Runnable() {
@Override
public void run() {
stopBluetoothDiscovery();
txtSearching.setText(R.string.label_bluetooth_searching_finished);
progressBar.setVisibility(View.GONE);
BluetoothDeviceView notSupported = new BluetoothDeviceView(context);
notSupported.setDeviceName(getString(R.string.label_scale_not_supported));
notSupported.setSummaryText(getString(R.string.label_click_to_help_add_support));
notSupported.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent notSupportedIntent = new Intent(Intent.ACTION_VIEW);
notSupportedIntent.setData(
Uri.parse("https://github.com/oliexdev/openScale/wiki/Supported-scales-in-openScale"));
startActivity(notSupportedIntent);
}
});
deviceListView.addView(notSupported);
}
}, 20 * 1000);
}
private void stopBluetoothDiscovery() {
if (progressHandler != null) {
progressHandler.removeCallbacksAndMessages(null);
progressHandler = null;
}
if (central != null) {
central.stopScan();
}
}
private void onDeviceFound(final ScanResult bleScanResult) {
BluetoothDevice device = bleScanResult.getDevice();
if (device.getName() == null || foundDevices.containsKey(device.getAddress())) {
return;
}
BluetoothDeviceView deviceView = new BluetoothDeviceView(this);
deviceView.setDeviceName(formatDeviceName(bleScanResult.getDevice()));
BluetoothCommunication btDevice = BluetoothFactory.createDeviceDriver(this, device.getName());
if (btDevice != null) {
Timber.d("Found supported device %s (driver: %s)",
formatDeviceName(device), btDevice.driverName());
deviceView.setOnClickListener(new onClickListenerDeviceSelect());
deviceView.setDeviceAddress(device.getAddress());
deviceView.setIcon(R.drawable.ic_bluetooth_device_supported);
deviceView.setSummaryText(btDevice.driverName());
}
else {
Timber.d("Found unsupported device %s",
formatDeviceName(device));
deviceView.setIcon(R.drawable.ic_bluetooth_device_not_supported);
deviceView.setSummaryText(getString(R.string.label_bt_device_no_support));
deviceView.setEnabled(false);
if (OpenScale.DEBUG_MODE) {
deviceView.setEnabled(true);
deviceView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getDebugInfo(device);
}
});
}
}
foundDevices.put(device.getAddress(), btDevice != null ? device : null);
deviceListView.addView(deviceView);
}
private class onClickListenerDeviceSelect implements View.OnClickListener {
@Override
public void onClick(View view) {
BluetoothDeviceView deviceView = (BluetoothDeviceView)view;
BluetoothDevice device = foundDevices.get(deviceView.getDeviceAddress());
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.edit()
.putString(PREFERENCE_KEY_BLUETOOTH_HW_ADDRESS, device.getAddress())
.putString(PREFERENCE_KEY_BLUETOOTH_DEVICE_NAME, device.getName())
.apply();
finishActivity(GET_SCALE_REQUEST);
}
}
private void getDebugInfo(final BluetoothDevice device) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Fetching info")
.setMessage("Please wait while we fetch extended info from your scale...")
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
OpenScale.getInstance().disconnectFromBluetoothDevice();
dialog.dismiss();
}
});
final AlertDialog dialog = builder.create();
Handler btHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (BluetoothCommunication.BT_STATUS.values()[msg.what]) {
case CONNECTION_LOST:
OpenScale.getInstance().disconnectFromBluetoothDevice();
dialog.dismiss();
break;
}
}
};
dialog.show();
String macAddress = device.getAddress();
stopBluetoothDiscovery();
OpenScale.getInstance().connectToBluetoothDeviceDebugMode(macAddress, btHandler);
}
private class BluetoothDeviceView extends LinearLayout {
private TextView deviceName;
private ImageView deviceIcon;
private String deviceAddress;
public BluetoothDeviceView(Context context) {
super(context);
deviceName = new TextView(context);
deviceName.setLines(2);
deviceIcon = new ImageView(context);
addView(deviceIcon);
addView(deviceName);
}
public void setDeviceAddress(String address) {
deviceAddress = address;
}
public String getDeviceAddress() {
return deviceAddress;
}
public void setDeviceName(String name) {
deviceName.setText(name);
}
public void setSummaryText(String text) {
SpannableStringBuilder stringBuilder = new SpannableStringBuilder(new String());
stringBuilder.append(deviceName.getText());
stringBuilder.append("\n");
int deviceNameLength = deviceName.getText().length();
stringBuilder.append(text);
stringBuilder.setSpan(new ForegroundColorSpan(Color.GRAY), deviceNameLength, deviceNameLength + text.length()+1,
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
stringBuilder.setSpan(new RelativeSizeSpan(0.8f), deviceNameLength, deviceNameLength + text.length()+1,
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
deviceName.setText(stringBuilder);
}
public void setIcon(int resId) {
deviceIcon.setImageResource(resId);
int tintColor = ColorUtil.getTextColor(getApplicationContext());
deviceIcon.setColorFilter(tintColor, PorterDuff.Mode.SRC_IN);
}
@Override
public void setOnClickListener(OnClickListener listener) {
super.setOnClickListener(listener);
deviceName.setOnClickListener(listener);
deviceIcon.setOnClickListener(listener);
}
@Override
public void setEnabled(boolean status) {
super.setEnabled(status);
deviceName.setEnabled(status);
deviceIcon.setEnabled(status);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PermissionHelper.ENABLE_BLUETOOTH_REQUEST) {
if (resultCode == Activity.RESULT_OK) {
if (PermissionHelper.requestBluetoothPermission(this)) {
startBluetoothDiscovery();
}
}
else {
onBackPressed();
}
}
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PermissionHelper.PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (PermissionHelper.requestLocationServicePermission(this)) {
startBluetoothDiscovery();
}
} else {
Toast.makeText(this, R.string.permission_not_granted, Toast.LENGTH_SHORT).show();
onBackPressed();
}
break;
}
}
}
}

View File

@@ -105,10 +105,6 @@ public class SettingsActivity extends PreferenceActivity
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
// TODO HACK to call RequestPermissionResult(...) in PreferenceFragment otherwise API level > 23 is required
switch(requestCode) {
case PermissionHelper.PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION:
BluetoothPreferences bluetoothPreferences = (BluetoothPreferences)currentFragment;
bluetoothPreferences.onMyOwnRequestPermissionsResult(requestCode, permissions, grantResults);
break;
case PermissionHelper.PERMISSIONS_REQUEST_ACCESS_READ_STORAGE:
case PermissionHelper.PERMISSIONS_REQUEST_ACCESS_WRITE_STORAGE:
BackupPreferences backupPreferences = (BackupPreferences)currentFragment;

View File

@@ -40,6 +40,8 @@ import com.health.openscale.R;
import com.health.openscale.core.OpenScale;
import com.health.openscale.core.bluetooth.BluetoothCommunication;
import com.health.openscale.core.bluetooth.BluetoothFactory;
import com.health.openscale.gui.activities.BluetoothSettingsActivity;
import com.health.openscale.gui.activities.UserSettingsActivity;
import com.health.openscale.gui.utils.ColorUtil;
import com.health.openscale.gui.utils.PermissionHelper;
import com.welie.blessed.BluetoothCentral;
@@ -51,18 +53,13 @@ import java.util.Map;
import timber.log.Timber;
import static android.app.Activity.RESULT_OK;
public class BluetoothPreferences extends PreferenceFragment {
private static final String PREFERENCE_KEY_BLUETOOTH_SCANNER = "btScanner";
public static final String PREFERENCE_KEY_BLUETOOTH_DEVICE_NAME = "btDeviceName";
public static final String PREFERENCE_KEY_BLUETOOTH_HW_ADDRESS = "btHwAddress";
private PreferenceScreen btScanner;
private Map<String, BluetoothDevice> foundDevices = new HashMap<>();
private Handler progressHandler;
private BluetoothCentral central;
private static final String formatDeviceName(String name, String address) {
if (name.isEmpty() || address.isEmpty()) {
@@ -71,141 +68,11 @@ public class BluetoothPreferences extends PreferenceFragment {
return String.format("%s [%s]", name, address);
}
private static final String formatDeviceName(BluetoothDevice device) {
return formatDeviceName(device.getName(), device.getAddress());
}
private String getCurrentDeviceName() {
SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
return formatDeviceName(
prefs.getString(PREFERENCE_KEY_BLUETOOTH_DEVICE_NAME, ""),
prefs.getString(PREFERENCE_KEY_BLUETOOTH_HW_ADDRESS, ""));
}
private final BluetoothCentralCallback bluetoothCentralCallback = new BluetoothCentralCallback() {
@Override
public void onDiscoveredPeripheral(BluetoothPeripheral peripheral, ScanResult scanResult) {
onDeviceFound(scanResult);
}
};
private void startBluetoothDiscovery() {
foundDevices.clear();
btScanner.removeAll();
central = new BluetoothCentral(getActivity().getApplicationContext(), bluetoothCentralCallback, new Handler(Looper.getMainLooper()));
central.scanForPeripherals();
final Preference scanning = new Preference(getActivity());
scanning.setEnabled(false);
btScanner.addPreference(scanning);
btScanner.getPreference(0).setTitle(R.string.label_bluetooth_searching);
progressHandler = new Handler();
// Draw a simple progressbar during the discovery/scanning
final int progressUpdatePeriod = 150;
final String[] blocks = {"","","","","","","",""};
scanning.setSummary(blocks[0]);
progressHandler.postDelayed(new Runnable() {
int index = 1;
@Override
public void run() {
String summary = scanning.getSummary()
.subSequence(0, scanning.getSummary().length() - 1).toString();
if (index == blocks.length) {
summary += blocks[blocks.length - 1];
index = 0;
}
summary += blocks[index++];
scanning.setSummary(summary);
progressHandler.postDelayed(this, progressUpdatePeriod);
}
}, progressUpdatePeriod);
// Don't let the BLE discovery run forever
progressHandler.postDelayed(new Runnable() {
@Override
public void run() {
stopBluetoothDiscovery();
Preference scanning = btScanner.getPreference(0);
scanning.setTitle(R.string.label_bluetooth_searching_finished);
scanning.setSummary("");
Intent notSupportedIntent = new Intent(Intent.ACTION_VIEW);
notSupportedIntent.setData(
Uri.parse("https://github.com/oliexdev/openScale/wiki/Supported-scales-in-openScale"));
Preference notSupported = new Preference(getActivity());
notSupported.setTitle(R.string.label_scale_not_supported);
notSupported.setSummary(R.string.label_click_to_help_add_support);
notSupported.setIntent(notSupportedIntent);
btScanner.addPreference(notSupported);
}
}, 20 * 1000);
// Abort discovery and scan if back is pressed or a scale is selected
btScanner.getDialog().setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
stopBluetoothDiscovery();
}
});
}
private void stopBluetoothDiscovery() {
if (progressHandler != null) {
progressHandler.removeCallbacksAndMessages(null);
progressHandler = null;
}
central.stopScan();
}
private void onDeviceFound(final ScanResult bleScanResult) {
BluetoothDevice device = bleScanResult.getDevice();
if (device.getName() == null || foundDevices.containsKey(device.getAddress())) {
return;
}
Preference prefBtDevice = new Preference(getActivity());
prefBtDevice.setTitle(formatDeviceName(bleScanResult.getDevice()));
BluetoothCommunication btDevice = BluetoothFactory.createDeviceDriver(getActivity(), device.getName());
if (btDevice != null) {
Timber.d("Found supported device %s (driver: %s)",
formatDeviceName(device), btDevice.driverName());
prefBtDevice.setOnPreferenceClickListener(new onClickListenerDeviceSelect());
prefBtDevice.setKey(device.getAddress());
prefBtDevice.setIcon(R.drawable.ic_bluetooth_device_supported);
prefBtDevice.setSummary(btDevice.driverName());
int tintColor = ColorUtil.getTextColor(getActivity().getApplicationContext());
prefBtDevice.getIcon().setColorFilter(tintColor, PorterDuff.Mode.SRC_IN);
}
else {
Timber.d("Found unsupported device %s",
formatDeviceName(device));
prefBtDevice.setIcon(R.drawable.ic_bluetooth_device_not_supported);
prefBtDevice.setSummary(R.string.label_bt_device_no_support);
prefBtDevice.setEnabled(false);
if (OpenScale.DEBUG_MODE) {
prefBtDevice.setEnabled(true);
prefBtDevice.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
getDebugInfo(device);
return false;
}
});
}
}
foundDevices.put(device.getAddress(), btDevice != null ? device : null);
btScanner.addPreference(prefBtDevice);
prefs.getString(BluetoothSettingsActivity.PREFERENCE_KEY_BLUETOOTH_DEVICE_NAME, ""),
prefs.getString(BluetoothSettingsActivity.PREFERENCE_KEY_BLUETOOTH_HW_ADDRESS, ""));
}
private void updateBtScannerSummary() {
@@ -222,15 +89,11 @@ public class BluetoothPreferences extends PreferenceFragment {
btScanner = (PreferenceScreen) findPreference(PREFERENCE_KEY_BLUETOOTH_SCANNER);
final Fragment fragment = this;
btScanner.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
if (PermissionHelper.requestBluetoothPermission(getActivity(), fragment)) {
if (PermissionHelper.requestLocationServicePermission(getActivity())) {
startBluetoothDiscovery();
}
}
Intent intent = new Intent(preference.getContext(), BluetoothSettingsActivity.class);
startActivityForResult(intent, BluetoothSettingsActivity.GET_SCALE_REQUEST);
return true;
}
});
@@ -239,98 +102,15 @@ public class BluetoothPreferences extends PreferenceFragment {
// Dummy preference to make screen open
btScanner.addPreference(new Preference(getActivity()));
}
@Override
public void onStart() {
super.onStart();
// Restart discovery after e.g. orientation change
if (btScanner.getDialog() != null && btScanner.getDialog().isShowing()) {
startBluetoothDiscovery();
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PermissionHelper.ENABLE_BLUETOOTH_REQUEST) {
if (resultCode == Activity.RESULT_OK) {
if (PermissionHelper.requestBluetoothPermission(getActivity(), this)) {
startBluetoothDiscovery();
if (resultCode != RESULT_OK) {
return;
}
}
else {
btScanner.getDialog().dismiss();
}
}
}
private void getDebugInfo(final BluetoothDevice device) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Fetching info")
.setMessage("Please wait while we fetch extended info from your scale...")
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
OpenScale.getInstance().disconnectFromBluetoothDevice();
dialog.dismiss();
}
});
final AlertDialog dialog = builder.create();
Handler btHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (BluetoothCommunication.BT_STATUS.values()[msg.what]) {
case CONNECTION_LOST:
OpenScale.getInstance().disconnectFromBluetoothDevice();
dialog.dismiss();
break;
}
}
};
dialog.show();
String macAddress = device.getAddress();
stopBluetoothDiscovery();
OpenScale.getInstance().connectToBluetoothDeviceDebugMode(
macAddress, btHandler);
}
private class onClickListenerDeviceSelect implements Preference.OnPreferenceClickListener {
@Override
public boolean onPreferenceClick(final Preference preference) {
BluetoothDevice device = foundDevices.get(preference.getKey());
preference.getSharedPreferences().edit()
.putString(PREFERENCE_KEY_BLUETOOTH_HW_ADDRESS, device.getAddress())
.putString(PREFERENCE_KEY_BLUETOOTH_DEVICE_NAME, device.getName())
.apply();
if (requestCode == BluetoothSettingsActivity.GET_SCALE_REQUEST) {
updateBtScannerSummary();
btScanner.getDialog().dismiss();
return true;
}
}
public void onMyOwnRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PermissionHelper.PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (PermissionHelper.requestLocationServicePermission(getActivity())) {
startBluetoothDiscovery();
}
} else {
Toast.makeText(getActivity(), R.string.permission_not_granted, Toast.LENGTH_SHORT).show();
btScanner.getDialog().dismiss();
}
break;
}
}
}
}

View File

@@ -0,0 +1,106 @@
/* Copyright (C) 2019 olie.xdev <olie.xdev@googlemail.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.health.openscale.gui.slides;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.health.openscale.R;
import com.health.openscale.gui.activities.BluetoothSettingsActivity;
import static android.app.Activity.RESULT_OK;
public class BluetoothIntroSlide extends Fragment {
private static final String ARG_LAYOUT_RES_ID = "layoutResId";
private int layoutResId;
private Button btnSearchScale;
private TextView txtFoundDevice;
public static BluetoothIntroSlide newInstance(int layoutResId) {
BluetoothIntroSlide sampleSlide = new BluetoothIntroSlide();
Bundle args = new Bundle();
args.putInt(ARG_LAYOUT_RES_ID, layoutResId);
sampleSlide.setArguments(args);
return sampleSlide;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null && getArguments().containsKey(ARG_LAYOUT_RES_ID)) {
layoutResId = getArguments().getInt(ARG_LAYOUT_RES_ID);
}
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(layoutResId, container, false);
txtFoundDevice = view.findViewById(R.id.txtFoundDevice);
txtFoundDevice.setText(getCurrentDeviceName());
btnSearchScale = view.findViewById(R.id.btnSearchScale);
btnSearchScale.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(getContext(), BluetoothSettingsActivity.class);
startActivityForResult(intent, BluetoothSettingsActivity.GET_SCALE_REQUEST);
}
});
return view;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) {
return;
}
if (requestCode == BluetoothSettingsActivity.GET_SCALE_REQUEST) {
txtFoundDevice.setText(getCurrentDeviceName());
}
}
private final String formatDeviceName(String name, String address) {
if (name.isEmpty() || address.isEmpty()) {
return "[" + getContext().getString(R.string.label_empty) + "]";
}
return String.format("%s [%s]", name, address);
}
private String getCurrentDeviceName() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
return formatDeviceName(
prefs.getString(BluetoothSettingsActivity.PREFERENCE_KEY_BLUETOOTH_DEVICE_NAME, ""),
prefs.getString(BluetoothSettingsActivity.PREFERENCE_KEY_BLUETOOTH_HW_ADDRESS, ""));
}
}

View File

@@ -0,0 +1,68 @@
/* Copyright (C) 2019 olie.xdev <olie.xdev@googlemail.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.health.openscale.gui.slides;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.health.openscale.R;
public class MetricsIntroSlide extends Fragment {
private static final String ARG_LAYOUT_RES_ID = "layoutResId";
private int layoutResId;
private TextView slideMainText;
public static MetricsIntroSlide newInstance(int layoutResId) {
MetricsIntroSlide sampleSlide = new MetricsIntroSlide();
Bundle args = new Bundle();
args.putInt(ARG_LAYOUT_RES_ID, layoutResId);
sampleSlide.setArguments(args);
return sampleSlide;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null && getArguments().containsKey(ARG_LAYOUT_RES_ID)) {
layoutResId = getArguments().getInt(ARG_LAYOUT_RES_ID);
}
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(layoutResId, container, false);
slideMainText = view.findViewById(R.id.slideMainText);
slideMainText.setLinksClickable(true);
slideMainText.setMovementMethod(LinkMovementMethod.getInstance());
return view;
}
}

View File

@@ -0,0 +1,68 @@
/* Copyright (C) 2019 olie.xdev <olie.xdev@googlemail.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.health.openscale.gui.slides;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.health.openscale.R;
public class OpenSourceIntroSlide extends Fragment {
private static final String ARG_LAYOUT_RES_ID = "layoutResId";
private int layoutResId;
private TextView slideMainText;
public static OpenSourceIntroSlide newInstance(int layoutResId) {
OpenSourceIntroSlide sampleSlide = new OpenSourceIntroSlide();
Bundle args = new Bundle();
args.putInt(ARG_LAYOUT_RES_ID, layoutResId);
sampleSlide.setArguments(args);
return sampleSlide;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null && getArguments().containsKey(ARG_LAYOUT_RES_ID)) {
layoutResId = getArguments().getInt(ARG_LAYOUT_RES_ID);
}
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(layoutResId, container, false);
slideMainText = view.findViewById(R.id.slideMainText);
slideMainText.setLinksClickable(true);
slideMainText.setMovementMethod(LinkMovementMethod.getInstance());
return view;
}
}

View File

@@ -0,0 +1,68 @@
/* Copyright (C) 2019 olie.xdev <olie.xdev@googlemail.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.health.openscale.gui.slides;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.health.openscale.R;
public class PrivacyIntroSlide extends Fragment {
private static final String ARG_LAYOUT_RES_ID = "layoutResId";
private int layoutResId;
private TextView slideMainText;
public static PrivacyIntroSlide newInstance(int layoutResId) {
PrivacyIntroSlide sampleSlide = new PrivacyIntroSlide();
Bundle args = new Bundle();
args.putInt(ARG_LAYOUT_RES_ID, layoutResId);
sampleSlide.setArguments(args);
return sampleSlide;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null && getArguments().containsKey(ARG_LAYOUT_RES_ID)) {
layoutResId = getArguments().getInt(ARG_LAYOUT_RES_ID);
}
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(layoutResId, container, false);
slideMainText = view.findViewById(R.id.slideMainText);
slideMainText.setLinksClickable(true);
slideMainText.setMovementMethod(LinkMovementMethod.getInstance());
return view;
}
}

View File

@@ -0,0 +1,68 @@
/* Copyright (C) 2019 olie.xdev <olie.xdev@googlemail.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.health.openscale.gui.slides;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.health.openscale.R;
public class SupportIntroSlide extends Fragment {
private static final String ARG_LAYOUT_RES_ID = "layoutResId";
private int layoutResId;
private TextView slideMainText;
public static SupportIntroSlide newInstance(int layoutResId) {
SupportIntroSlide sampleSlide = new SupportIntroSlide();
Bundle args = new Bundle();
args.putInt(ARG_LAYOUT_RES_ID, layoutResId);
sampleSlide.setArguments(args);
return sampleSlide;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null && getArguments().containsKey(ARG_LAYOUT_RES_ID)) {
layoutResId = getArguments().getInt(ARG_LAYOUT_RES_ID);
}
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(layoutResId, container, false);
slideMainText = view.findViewById(R.id.slideMainText);
slideMainText.setLinksClickable(true);
slideMainText.setMovementMethod(LinkMovementMethod.getInstance());
return view;
}
}

View File

@@ -0,0 +1,165 @@
/* Copyright (C) 2019 olie.xdev <olie.xdev@googlemail.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.health.openscale.gui.slides;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.health.openscale.R;
import com.health.openscale.core.OpenScale;
import com.health.openscale.core.datatypes.ScaleUser;
import com.health.openscale.gui.activities.UserSettingsActivity;
import java.util.List;
public class UserIntroSlide extends Fragment{
private static final String ARG_LAYOUT_RES_ID = "layoutResId";
private int layoutResId;
private Button btnAddUser;
private TableLayout tblUsers;
public static UserIntroSlide newInstance(int layoutResId) {
UserIntroSlide sampleSlide = new UserIntroSlide();
Bundle args = new Bundle();
args.putInt(ARG_LAYOUT_RES_ID, layoutResId);
sampleSlide.setArguments(args);
return sampleSlide;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null && getArguments().containsKey(ARG_LAYOUT_RES_ID)) {
layoutResId = getArguments().getInt(ARG_LAYOUT_RES_ID);
}
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(layoutResId, container, false);
btnAddUser = view.findViewById(R.id.btnAddUser);
tblUsers = view.findViewById(R.id.tblUsers);
btnAddUser.setOnClickListener(new onBtnAddUserClickListener());
updateTableUsers();
return view;
}
private class onBtnAddUserClickListener implements View.OnClickListener {
@Override
public void onClick(View view) {
Intent intent = new Intent(getContext(), UserSettingsActivity.class);
intent.putExtra(UserSettingsActivity.EXTRA_MODE, UserSettingsActivity.ADD_USER_REQUEST);
startActivityForResult(intent, 100);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
updateTableUsers();
}
private void updateTableUsers() {
tblUsers.removeAllViews();
tblUsers.setStretchAllColumns(true);
List<ScaleUser> scaleUserList = OpenScale.getInstance().getScaleUserList();
TableRow header = new TableRow(getContext());
TextView headerUsername = new TextView(getContext());
headerUsername.setText(R.string.label_user_name);
headerUsername.setGravity(Gravity.CENTER_HORIZONTAL);
headerUsername.setTypeface(null, Typeface.BOLD);
header.addView(headerUsername);
TextView headAge = new TextView(getContext());
headAge.setText(R.string.label_age);
headAge.setGravity(Gravity.CENTER_HORIZONTAL);
headAge.setTypeface(null, Typeface.BOLD);
header.addView(headAge);
TextView headerGender = new TextView(getContext());
headerGender.setText(R.string.label_gender);
headerGender.setGravity(Gravity.CENTER_HORIZONTAL);
headerGender.setTypeface(null, Typeface.BOLD);
header.addView(headerGender);
tblUsers.addView(header);
if (!scaleUserList.isEmpty()) {
TableRow row = new TableRow(getContext());
for (ScaleUser scaleUser : scaleUserList) {
row = new TableRow(getContext());
TextView txtUsername = new TextView(getContext());
txtUsername.setText(scaleUser.getUserName());
txtUsername.setGravity(Gravity.CENTER_HORIZONTAL);
row.addView(txtUsername);
TextView txtAge = new TextView(getContext());
txtAge.setText(Integer.toString(scaleUser.getAge()));
txtAge.setGravity(Gravity.CENTER_HORIZONTAL);
row.addView(txtAge);
TextView txtGender = new TextView(getContext());
txtGender.setText((scaleUser.getGender().isMale()) ? getString(R.string.label_male) : getString(R.string.label_female));
txtGender.setGravity(Gravity.CENTER_HORIZONTAL);
row.addView(txtGender);
row.setGravity(Gravity.CENTER_HORIZONTAL);
tblUsers.addView(row);
}
} else {
TableRow row = new TableRow(getContext());
TextView txtEmpty = new TextView(getContext());
txtEmpty.setText("[" + getContext().getString(R.string.label_empty) + "]");
txtEmpty.setGravity(Gravity.CENTER_HORIZONTAL);
row.addView(txtEmpty);
row.setGravity(Gravity.CENTER_HORIZONTAL);
tblUsers.addView(row);
}
}
}

View File

@@ -0,0 +1,56 @@
/* Copyright (C) 2019 olie.xdev <olie.xdev@googlemail.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.health.openscale.gui.slides;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class WelcomeIntroSlide extends Fragment {
private static final String ARG_LAYOUT_RES_ID = "layoutResId";
private int layoutResId;
public static WelcomeIntroSlide newInstance(int layoutResId) {
WelcomeIntroSlide sampleSlide = new WelcomeIntroSlide();
Bundle args = new Bundle();
args.putInt(ARG_LAYOUT_RES_ID, layoutResId);
sampleSlide.setArguments(args);
return sampleSlide;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null && getArguments().containsKey(ARG_LAYOUT_RES_ID)) {
layoutResId = getArguments().getInt(ARG_LAYOUT_RES_ID);
}
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(layoutResId, container, false);
}
}

View File

@@ -43,7 +43,7 @@ public class PermissionHelper {
public final static int ENABLE_BLUETOOTH_REQUEST = 5;
public static boolean requestBluetoothPermission(final Activity activity, Fragment fragment) {
public static boolean requestBluetoothPermission(final Activity activity) {
final BluetoothManager bluetoothManager = (BluetoothManager) activity.getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter btAdapter = bluetoothManager.getAdapter();
@@ -52,7 +52,7 @@ public class PermissionHelper {
if (btAdapter != null) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
fragment.startActivityForResult(enableBtIntent, ENABLE_BLUETOOTH_REQUEST);
activity.startActivityForResult(enableBtIntent, ENABLE_BLUETOOTH_REQUEST);
}
return false;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 756 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 641 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/bluetoothSettingToolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<TextView
android:id="@+id/txtSearching"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:gravity="center"
android:paddingBottom="10px"
android:text="@string/label_bluetooth_searching"
android:textColor="@android:color/white"
android:visibility="gone"/>
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"/>
<LinearLayout
android:id="@+id/deviceListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10px"
android:orientation="vertical" />
</LinearLayout>

View File

@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:gravity="center_horizontal"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="40dp"
android:layout_marginBottom="40dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/imgLogo"
android:layout_width="40dp"
android:layout_height="40dp"
app:srcCompat="@drawable/ic_launcher_openscale" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="20dp"
android:text="openScale"
android:textSize="20sp" />
</LinearLayout>
<ScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="40dp"
android:gravity="center"
android:text="@string/label_slide_bluetooth_top_text"
android:textSize="18sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/imgSlide"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginBottom="40dp"
app:srcCompat="@drawable/ic_bluetooth_device_supported"
android:tint="@color/widgetTextColor"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="20dp"
android:gravity="center"
android:text="@string/label_slide_bluetooth_main_text"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:text="@string/label_your_bluetooth_scale"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/txtFoundDevice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:text="@string/label_empty"
android:textSize="16sp" />
<Button
android:id="@+id/btnSearchScale"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="100dp"
android:background="@drawable/flat_selector"
android:text="Add Bluetooth scale"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:textColor="@android:color/white" />
</LinearLayout>
</ScrollView>
</LinearLayout>

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:gravity="center_horizontal"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="40dp"
android:layout_marginBottom="40dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/imgLogo"
android:layout_width="40dp"
android:layout_height="40dp"
app:srcCompat="@drawable/ic_launcher_openscale" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="20dp"
android:text="openScale"
android:textSize="20sp" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="40dp"
android:gravity="center"
android:text="@string/label_slide_metrics_top_text"
android:textSize="18sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/imgSlide"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginBottom="40dp"
app:srcCompat="@drawable/ic_preferences_graph"
android:tint="@color/widgetTextColor" />
<TextView
android:id="@+id/slideMainText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="20dp"
android:gravity="center"
android:text="@string/label_slide_metrics_main_text"
android:textSize="16sp" />
</LinearLayout>

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:gravity="center_horizontal"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="40dp"
android:layout_marginBottom="40dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/imgLogo"
android:layout_width="40dp"
android:layout_height="40dp"
app:srcCompat="@drawable/ic_launcher_openscale" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="20dp"
android:text="openScale"
android:textSize="20sp" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="40dp"
android:gravity="center"
android:text="@string/label_slide_opensource_top_text"
android:textSize="18sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/imgSlide"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginBottom="40dp"
app:srcCompat="@drawable/ic_slide_opensource"
android:tint="@color/widgetTextColor" />
<TextView
android:id="@+id/slideMainText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="20dp"
android:gravity="center"
android:text="@string/label_slide_opensource_main_text"
android:textSize="16sp" />
</LinearLayout>

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:gravity="center_horizontal"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="40dp"
android:layout_marginBottom="40dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/imgLogo"
android:layout_width="40dp"
android:layout_height="40dp"
app:srcCompat="@drawable/ic_launcher_openscale" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="20dp"
android:text="openScale"
android:textSize="20sp" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="40dp"
android:gravity="center"
android:text="@string/label_slide_privacy_top_text"
android:textSize="18sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/imgSlide"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginBottom="40dp"
app:srcCompat="@drawable/ic_slide_privacy"
android:tint="@color/widgetTextColor" />
<TextView
android:id="@+id/slideMainText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="20dp"
android:gravity="center"
android:text="@string/label_slide_privacy_main_text"
android:textSize="16sp" />
</LinearLayout>

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:gravity="center_horizontal"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="40dp"
android:layout_marginBottom="40dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/imgLogo"
android:layout_width="40dp"
android:layout_height="40dp"
app:srcCompat="@drawable/ic_launcher_openscale" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="20dp"
android:text="openScale"
android:textSize="20sp" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="40dp"
android:gravity="center"
android:text="@string/label_slide_support_top_text"
android:textSize="18sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/imgSlide"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginBottom="40dp"
app:srcCompat="@drawable/ic_slide_support"
android:tint="@color/widgetTextColor" />
<TextView
android:id="@+id/slideMainText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="20dp"
android:gravity="center"
android:text="@string/label_slide_support_main_text"
android:textSize="16sp" />
</LinearLayout>

View File

@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:gravity="center_horizontal"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="40dp"
android:layout_marginBottom="40dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/imgLogo"
android:layout_width="40dp"
android:layout_height="40dp"
app:srcCompat="@drawable/ic_launcher_openscale" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="20dp"
android:text="openScale"
android:textSize="20sp" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="40dp"
android:gravity="center"
android:text="@string/label_slide_user_top_text"
android:textSize="18sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/imgSlide"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginBottom="40dp"
app:srcCompat="@drawable/ic_slide_group"
android:tint="@color/widgetTextColor" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="20dp"
android:gravity="center"
android:text="@string/label_slide_user_main_text"
android:textSize="16sp" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="100dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TableLayout
android:id="@+id/tblUsers"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp" />
</LinearLayout>
</ScrollView>
<Button
android:id="@+id/btnAddUser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/flat_selector"
android:text="@string/label_add_user"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:textColor="@android:color/white" />
</LinearLayout>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:id="@+id/imgSlide"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginTop="100dp"
android:layout_marginBottom="40dp"
app:srcCompat="@drawable/ic_launcher_openscale" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="40dp"
android:text="@string/label_slide_welcome_top_text"
android:gravity="center"
android:textSize="28sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="20dp"
android:gravity="center"
android:text="@string/label_slide_welcome_main_text"
android:textSize="16sp" />
</LinearLayout>

View File

@@ -19,6 +19,7 @@
<string name="label_yes">Yes</string>
<string name="label_no">No</string>
<string name="label_delete">Delete</string>
<string name="label_empty">empty</string>
<string name="label_add_user">Add user</string>
<string name="label_add_measurement">Add measurement</string>
<string name="label_share">Share</string>
@@ -37,6 +38,7 @@
<string name="label_whtr">Waist-to-height ratio</string>
<string name="label_whr">Waist-hip ratio</string>
<string name="label_bone">Bone mass</string>
<string name="label_age">Age</string>
<string name="label_smartUserAssign">Smart User assignment</string>
<plurals name="label_days">
<item quantity="one">day %d</item>
@@ -233,4 +235,24 @@
<string name="activity_level_heavy">Heavy</string>
<string name="activity_level_extreme">Extreme</string>
<string name="label_upgrade_to_openScale_pro">Please upgrade to openScale pro for Bluetooth support</string>
<string name="label_slide_welcome_top_text">Welcome to\nopenScale</string>
<string name="label_slide_welcome_main_text">Open-source weight and body metrics tracker, with support for Bluetooth scales.</string>
<string name="label_slide_privacy_top_text">Protect your personal health data.</string>
<string name="label_slide_privacy_main_text">openScale doesn\'t send any data to a cloud and not having permission to access the internet is a strong guarantee of that.\n\nIf you really want to synchronise your weight to GoogleFit or with MQTT, you can install <a href="https://play.google.com/store/apps/details?id=com.health.openscale.sync">openScale sync</a>.</string>
<string name="label_slide_user_top_text">Multiple users are supported.</string>
<string name="label_slide_user_main_text">openScale doesn\'t require you to create an online account.\n\nWe only need your user information to calculate some body metrics.</string>
<string name="label_slide_opensource_top_text">It\'s an open-source software with a high degree of transparency.</string>
<string name="label_slide_opensource_main_text">openScale is licensed under the <a href="https://github.com/oliexdev/openScale/blob/master/LICENSE">GPLv3</a>.\n\nAll body calculations are transparent and no hidden data transfer function or user identification are undertaken.\n\nYou can find the full source-code on <a href="https://github.com/oliexdev/openScale">GitHub</a>. Convince yourself of openScale by reviewing it.</string>
<string name="label_slide_bluetooth_top_text">Various Bluetooth scales from different manufacturers are supported.</string>
<string name="label_slide_bluetooth_main_text">openScale has a built-in support for a number of Bluetooth scales from different manufacturers.\n\nWe constantly improve and extend the set of supported scales. You can find the full list and the level of support for each scale on <a href="https://github.com/oliexdev/openScale/wiki/Supported-scales-in-openScale">GitHub</a>.</string>
<string name="label_slide_metrics_top_text">Track and analyse your body metrics.</string>
<string name="label_slide_metrics_main_text">openScale supports over 22 body metrics.\n\nIt can be individual configured to only show the metrics you care about.\n\nIf your scale doesn\'t support body fat, body water and lean body mass, you can even estimate those measurements based on <a href="https://github.com/oliexdev/openScale/wiki/Body-metric-estimations">scientific publications</a>.</string>
<string name="label_slide_support_top_text">Help us to improve openScale.</string>
<string name="label_slide_support_main_text">openScale needs you! If you found a bug, have an idea or a question or want to help to support your Bluetooth scale, please create a <a href="https://github.com/oliexdev/openScale/issues">new issue</a>.\n\nIf you would like to motivate the creator of this project in further development and continuous maintenance, feel free to give openScale a positive rating on <a href="http://play.google.com/store/apps/details?id=com.health.openscale.pro">GooglePlay</a> or a star on <a href="https://github.com/oliexdev/openScale">GitHub</a>.\n\nYour support and positive feedback is highly appreciated. Thank you!</string>
<string name="app_intro_skip_button">SKIP</string>
<string name="app_intro_next_button">NEXT</string>
<string name="app_intro_back_button">BACK</string>
<string name="app_intro_done_button">DONE</string>
</resources>