ui+search+conn

This commit is contained in:
leo 2022-12-18 19:03:39 +01:00
parent b982711339
commit a4e6d4ba17
Signed by: leo
GPG Key ID: 0DD993BFB2B307DB
26 changed files with 597 additions and 82 deletions

1
.idea/gradle.xml generated
View File

@ -13,7 +13,6 @@
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>

2
.idea/misc.xml generated
View File

@ -4,7 +4,7 @@
<option name="filePathToZoomLevelMap">
<map>
<entry key="../../../../layout/custom_preview.xml" value="0.203125" />
<entry key="app/src/main/res/layout/activity_main.xml" value="0.2" />
<entry key="app/src/main/res/layout/activity_main.xml" value="0.33" />
</map>
</option>
</component>

View File

@ -3,12 +3,12 @@ plugins {
}
android {
compileSdk 31
compileSdk 33
defaultConfig {
applicationId "com.example.co2sense_app"
minSdk 26
targetSdk 31
targetSdk 33
versionCode 1
versionName "1.0"
@ -25,14 +25,18 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
namespace 'com.example.co2sense_app'
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.6.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.7.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.activity:activity:1.7.0-alpha02'
implementation 'androidx.fragment:fragment:1.6.0-alpha04'
implementation 'androidx.core:core:1.9.0'
//testImplementation 'junit:junit:4.13.2'
//androidTestImplementation 'androidx.test.ext:junit:1.1.3'
//androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

View File

@ -1,10 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.co2sense_app">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-feature android:name="android.software.companion_device_setup" />
<uses-feature android:name="android.software.companion_device_setup"/>
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:usesPermissionFlags="neverForLocation"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
@ -12,6 +18,15 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.CO2Sense_app">
<!--android:theme="@style/Theme.AppCompat.NoActionBar"-->
<!--android:theme="@style/Theme.CO2Sense_app"-->
<activity
android:name=".search_ble_devices_activity"
android:exported="false">
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".MainActivity"
android:exported="true">
@ -22,4 +37,5 @@
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -10,12 +10,11 @@ import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.companion.AssociationRequest;
import android.companion.BluetoothDeviceFilter;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.companion.CompanionDeviceManager;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.os.Build;
import android.util.Log;
@ -31,36 +30,45 @@ import java.nio.ByteBuffer;
import java.util.NoSuchElementException;
public abstract class BLEDevice {
private enum ConnectionState {NONE, STARTING_BT, CONNECTING, CONNECTED};
private ConnectionState state = ConnectionState.NONE;
private static final int REQUEST_BT_PERMISSION = 16535;
private static final int REQUEST_ENABLE_BT = 16536;
private static final int SELECT_DEVICE_REQUEST_CODE = 16537;
private static final int REQUEST_BT_CONNECT_PERMISSION = 16538;
private static final int REQUEST_BT_SCAN_PERMISSION = 16539;
private static final int REQUEST_FINE_LOC_PERMISSION = 16540;
private final Activity activity;
private boolean startPairingOnBTStart;
private boolean startConnectOnBTStart;
protected BluetoothGatt bluetoothGatt;
private BluetoothDevice device;
private final ActivityResultLauncher<String> requestPermissionLauncher;
private BluetoothAdapter bluetoothAdapter;
private ScanCallback scanCallback;
@RequiresApi(api = Build.VERSION_CODES.S)
BLEDevice(Activity activity) {
this.activity = activity;
requestPermissionLauncher = ((ActivityResultCaller) activity).registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> connect());
}
ActivityResultLauncher<String> requestPermissionLauncher = ((ActivityResultCaller) activity).registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> connect());
public void startBT() {
Log.d("bt", "startBT");
Context context = activity.getApplicationContext();
BluetoothManager bluetoothManager = ContextCompat.getSystemService(context, BluetoothManager.class);
if (bluetoothManager == null)
throw new NoSuchElementException("No Bluetooth manager found");
BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
bluetoothAdapter = bluetoothManager.getAdapter();
}
@RequiresApi(api = Build.VERSION_CODES.S)
public void startBT() {
Log.d("bt", "startBT");
if (bluetoothAdapter == null)
throw new NoSuchElementException("No Bluetooth adapter found");
if (bluetoothAdapter.isEnabled()) {
if (startPairingOnBTStart) pair();
if (startConnectOnBTStart) connect();
} else {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED) {
@ -71,36 +79,6 @@ public abstract class BLEDevice {
}
}
protected void pair() {
Log.d("bt", "pair");
BluetoothDeviceFilter deviceFilter = new BluetoothDeviceFilter.Builder()
//.setNamePattern(Pattern.compile("My device"))
//.addServiceUuid(new ParcelUuid(new UUID(0x123abcL, -1L)), null)
.build();
AssociationRequest pairingRequest = new AssociationRequest.Builder()
.addDeviceFilter(deviceFilter)
//.setSingleDevice(true)
.build();
CompanionDeviceManager deviceManager = (CompanionDeviceManager) activity.getSystemService(Context.COMPANION_DEVICE_SERVICE);
deviceManager.associate(pairingRequest, new CompanionDeviceManager.Callback() {
@Override
public void onDeviceFound(IntentSender chooserLauncher) {
try {
activity.startIntentSenderForResult(chooserLauncher, SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0
);
} catch (IntentSender.SendIntentException e) {
Log.e("MainActivity", "Failed to send intent");
}
}
@Override
public void onFailure(CharSequence error) {
Log.e("pair", (String) error);
}
}, null);
}
@SuppressLint("MissingPermission")
@RequiresApi(api = Build.VERSION_CODES.S)
protected void connect() {
@ -119,6 +97,7 @@ public abstract class BLEDevice {
bluetoothGatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.d("bt", "disconnected");
connect();
}
}
@ -150,7 +129,7 @@ public abstract class BLEDevice {
switch (requestCode) {
case REQUEST_ENABLE_BT:
if(resultCode != Activity.RESULT_OK) startBT();
else if(startPairingOnBTStart) pair();
else if(startConnectOnBTStart) connect();
break;
case SELECT_DEVICE_REQUEST_CODE:
Log.d("bt", "device selected");
@ -166,11 +145,55 @@ public abstract class BLEDevice {
}
}
public void startPairingOnBTStart(boolean status) {
startPairingOnBTStart = status;
@RequiresApi(api = Build.VERSION_CODES.S)
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults){
switch (requestCode){
case REQUEST_BT_SCAN_PERMISSION:
//startScan(scanCallback);
break;
case REQUEST_FINE_LOC_PERMISSION:
startScan(scanCallback);
break;
}
}
public void startConnectOnBTStart(boolean status) {
startConnectOnBTStart = status;
}
protected void onServicesDiscovered(){
}
@RequiresApi(api = Build.VERSION_CODES.S)
public void startScan(ScanCallback callback){
scanCallback = callback;
Log.d("BLE_device", "startScan: startBT");
startBT();
Log.d("BLE_device", "startScan: getPerm");
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_FINE_LOC_PERMISSION);
Log.d("BLE_device", "startScan: asking perms");
return;
}
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_FINE_LOC_PERMISSION);
Log.d("BLE_device", "startScan: asking perms");
return;
}
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(new String[]{Manifest.permission.BLUETOOTH_SCAN}, REQUEST_BT_SCAN_PERMISSION);
Log.d("BLE device", "startScan: asking perms");
//return;
}
Log.d("BLE_device", "startScan: ");
BluetoothLeScanner bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
bluetoothLeScanner.startScan(callback);
}
@RequiresApi(api = Build.VERSION_CODES.S)
public void setDeviceFromMAC(String targetDeviceMAC) {
device = bluetoothAdapter.getRemoteDevice(targetDeviceMAC);
}
}

View File

@ -1,13 +1,21 @@
package com.example.co2sense_app;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.constraintlayout.widget.ConstraintLayout;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.text.Layout;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
public class MainActivity extends AppCompatActivity {
@ -19,14 +27,31 @@ public class MainActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar myToolbar = (Toolbar) findViewById(R.id.toolbar);
myToolbar.showContextMenu();
myToolbar.showOverflowMenu();
setSupportActionBar(myToolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
SharedPreferences sharedPref = getSharedPreferences(
getString(R.string.main_shared_pref),Context.MODE_PRIVATE);
String targetDeviceMAC = sharedPref.getString("target_device_mac", null);
Log.d("MAIN", "onCreate: "+targetDeviceMAC);
Log.d("MAIN", "onCreate: "+sharedPref.hashCode());
sensor = new CO2Sensor(this);
sensor.startPairingOnBTStart(true);
if(targetDeviceMAC != null) {
sensor.setDeviceFromMAC(targetDeviceMAC);
sensor.startConnectOnBTStart(true);
sensor.startBT();
}
ConstraintLayout mainLayout = findViewById(R.id.mainLayout);
OMeter CO2Meter = findViewById(R.id.CO2OMeter);
mainLayout.setOnClickListener(v -> {
// sensor.startBT();
// sensor.pair();
ConstraintLayout CO2_widget = findViewById(R.id.CO2_ES);
OMeter CO2Meter = CO2_widget.findViewById(R.id.OMeter);
CO2_widget.setOnClickListener(v -> {
Log.d("MAIN", "onCreate: click");
CO2Meter.setValue(CO2Meter.getValue() + 100);
});
}
@ -43,4 +68,33 @@ public class MainActivity extends AppCompatActivity {
super.onActivityResult(requestCode, resultCode, data);
sensor.onActivityResult(requestCode, resultCode, data);
}
@RequiresApi(api = Build.VERSION_CODES.S)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
sensor.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.select_target:
Intent myIntent = new Intent(this, search_ble_devices_activity.class);
startActivity(myIntent);
return true;
default:
// If we got here, the user's action was not recognized.
// Invoke the superclass to handle it.
return super.onOptionsItemSelected(item);
}
}
}

View File

@ -17,13 +17,14 @@ import android.view.View;
import androidx.annotation.Nullable;
public class OMeter extends View {
private float min, max, value;
private float min, max, value = 100;
private float angle;
private int minColor, maxColor;
private int bandRad;
private int strokeWidth;
private RectF rectf;
private String dispValue = "NaN";
private int textColor;
private final Paint bandPaint;
private final Paint textPaint;
@ -48,7 +49,7 @@ public class OMeter extends View {
bandPaint.setStrokeCap(Paint.Cap.ROUND);
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(0xFFFFFFFF); //TODO : get from theme
textPaint.setColor(textColor);
textPaint.setTextAlign(Paint.Align.CENTER);
}

View File

@ -0,0 +1,74 @@
package com.example.co2sense_app;
import android.bluetooth.le.ScanResult;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class ble_devices_adapter extends RecyclerView.Adapter<ble_devices_adapter.ViewHolder> {
ArrayList<ScanResult> data;
View.OnClickListener itemSelectListener;
public static class ViewHolder extends RecyclerView.ViewHolder {
private final TextView textView;
private final Button selectButton;
public ViewHolder(View view) {
super(view);
textView = view.findViewById(R.id.name);
selectButton = view.findViewById(R.id.select_ble_device);
}
public void setName(String name) {
textView.setText(name);
}
public void setSelectOnClickListener(View.OnClickListener l){
selectButton.setOnClickListener(l);
}
}
public ble_devices_adapter(){
data = new ArrayList<>();
}
public void addDevice(ScanResult result){
if(data.stream().anyMatch(r -> r.getDevice().getAddress().equals(result.getDevice().getAddress()))) return;
data.add(result);
}
public void setSelectOnClickListener(View.OnClickListener l){
itemSelectListener = l;
}
public ScanResult getDataByIndex(int viewIndex) {
return data.get(viewIndex);
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.ble_device_scan_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.setName(data.get(position).getScanRecord().getDeviceName());
holder.setSelectOnClickListener(itemSelectListener);
}
@Override
public int getItemCount() {
return data.size();
}
}

View File

@ -0,0 +1,86 @@
package com.example.co2sense_app;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.app.Activity;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class search_ble_devices_activity extends AppCompatActivity {
CO2Sensor sensor;
@RequiresApi(api = Build.VERSION_CODES.S)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_ble_devices);
RecyclerView resultsView = findViewById(R.id.devicesFoundList);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
resultsView.setLayoutManager(layoutManager);
ble_devices_adapter resultsAdapter = new ble_devices_adapter();
Activity thisActivity=this;
resultsAdapter.setSelectOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SharedPreferences sharedPref = thisActivity.getSharedPreferences(
getString(R.string.main_shared_pref),Context.MODE_PRIVATE);
SharedPreferences.Editor edit = sharedPref.edit();
int viewIndex = resultsView.getChildAdapterPosition((View)view.getParent());
ScanResult device = resultsAdapter.getDataByIndex(viewIndex);
String address = device.getDevice().getAddress();
Log.d("search_ble", "onClick: "+address);
edit.putString("target_device_mac", address);
edit.apply();
thisActivity.finish();
}
});
resultsView.setAdapter(resultsAdapter);
sensor = new CO2Sensor(this);
Log.d("search_ble", "onCreate: ");
sensor.startScan(new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
resultsAdapter.addDevice(result);
resultsAdapter.notifyDataSetChanged();
Log.d("search_ble", "onScanResult: "+result);
}
});
}
@RequiresApi(api = Build.VERSION_CODES.S)
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
sensor.onActivityResult(requestCode, resultCode, data);
}
@RequiresApi(api = Build.VERSION_CODES.S)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
sensor.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="1000"
android:viewportHeight="1000">
<path
android:fillColor="#FF000000"
android:pathData="M964.8,374.6h-34.6v-39.2c0,-27.9 -22.6,-50.5 -50.5,-50.5H60.5c-27.9,0 -50.5,22.6 -50.5,50.5v329.3c0,27.9 22.6,50.5 50.5,50.5h819.1c27.9,0 50.5,-22.6 50.5,-50.5v-39.2h34.6c14,0 25.2,-11.3 25.2,-25.2V399.9C990.1,385.9 978.7,374.6 964.8,374.6zM868.2,635.6c0,14 -11.3,25.2 -25.2,25.2H97.4c-14,0 -25.3,-11.3 -25.3,-25.2V364.3c0,-14 11.3,-25.2 25.3,-25.2H843c14,0 25.2,11.3 25.2,25.2V635.6L868.2,635.6z"/>
</vector>

View File

@ -0,0 +1,32 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape android:shape="rectangle"
android:tint="?attr/colorControlNormal">
<corners android:radius="8dp"/>
<size android:width="100dp" android:height="40dp" />
<solid android:color="#00000000" />
<stroke android:width="1dp" android:color="@color/black" />
</shape>
<shape android:shape="rectangle"
android:tint="?attr/colorControlNormal" >
<corners android:radius="1dp"/>
<size android:width="10dp" android:height="20dp" />
<solid android:color="@color/black" />
<stroke android:width="1dp" android:color="@color/black" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<gradient
android:startColor="#FF0000"
android:centerColor="#007A00"
android:centerY="1.0"
android:endColor="#06101d"
android:angle="0"
/>
</shape>
</clip>
</item>
</layer-list>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="217.5dp"
android:height="217.5dp"
android:viewportWidth="217.5"
android:viewportHeight="217.5">
<path
android:fillColor="#FF000000"
android:pathData="M123.26,108.75l45.6,-44.49c1.74,-1.69 2.71,-4.02 2.71,-6.44s-0.98,-4.75 -2.71,-6.44l-50.04,-48.82c-2.59,-2.53 -6.44,-3.26 -9.78,-1.85c-3.34,1.41 -5.51,4.67 -5.51,8.29v80.5l-42.33,-41.3c-3.56,-3.47 -9.26,-3.4 -12.73,0.16c-3.47,3.56 -3.4,9.26 0.16,12.73l48.85,47.66l-48.85,47.66c-3.56,3.47 -3.63,9.17 -0.16,12.73s9.17,3.63 12.73,0.16l42.33,-41.3v80.5c0,3.62 2.17,6.89 5.51,8.29c1.13,0.48 2.32,0.71 3.49,0.71c2.31,0 4.57,-0.89 6.29,-2.56l50.04,-48.82c1.74,-1.69 2.71,-4.02 2.71,-6.44s-0.98,-4.75 -2.71,-6.44L123.26,108.75zM121.54,30.35l28.15,27.47l-28.15,27.47V30.35zM121.54,187.14v-54.93l28.15,27.47L121.54,187.14z"/>
</vector>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle" android:tint="?attr/colorAccent">
<corners android:radius="8dp"/>
<size android:width="100dp" android:height="40dp" />
<stroke android:width="1dp" android:color="?attr/colorOnBackground"/>
</shape>
</item>
</selector>

View File

@ -7,22 +7,65 @@
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:id="@+id/metersLayout"
android:layout_width="0dp"
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
app:layout_constraintTop_toTopOf="parent"
app:menu="@menu/toolbar">
<com.example.co2sense_app.OMeter
android:id="@+id/CO2OMeter"
<TextView
android:id="@+id/status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:max="1700"
app:min="0">
android:layout_height="match_parent"
android:text="@string/status_erreur"
tools:layout_editor_absoluteX="16dp"
tools:layout_editor_absoluteY="28dp" />
</androidx.appcompat.widget.Toolbar>
<ScrollView
android:id="@+id/ES_widgets_sv"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/toolbar">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include
android:id="@+id/CO2_ES"
layout="@layout/es_widget"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<include
android:id="@+id/TEMP_ES"
layout="@layout/es_widget"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<include
android:id="@+id/HUM_ES"
layout="@layout/es_widget"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<include
android:id="@+id/BATT_ES"
layout="@layout/es_widget"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>
</com.example.co2sense_app.OMeter>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".search_ble_devices_activity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/devicesFoundList"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/status_erreur"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/select_ble_device"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/select_ble_device"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:background="@drawable/rounded_rectangle"
android:gravity="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.example.co2sense_app.OMeter
android:id="@+id/OMeter"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="8dp"
android:layout_marginVertical="8dp"
android:layout_weight="1"
app:textColor="?android:attr/textColorPrimaryNoDisable" />
<Space
android:layout_width="8dp"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/value"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:fontFamily="sans-serif-condensed"
android:text="@string/no_data"
android:textColor="?android:attr/textColorPrimaryNoDisable"
android:textSize="60sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/select_target"
android:icon="@drawable/bluetooth_icon"
android:iconTint="?attr/actionMenuTextColor"
android:title="Target"
app:showAsAction="ifRoom" />
</menu>

View File

@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.CO2Sense_app" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<style name="Theme.CO2Sense_app" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>

View File

@ -5,5 +5,6 @@
<attr name="max" format="float"/>
<attr name="minColor" format="color"/>
<attr name="maxColor" format="color"/>
<attr name="textColor" format="color"/>
</declare-styleable>
</resources>

View File

@ -1,3 +1,8 @@
<resources>
<string name="app_name">CO2Sense_app</string>
<string name="no_data">N/A</string>
<string name="no_devices">No Device</string>
<string name="status_erreur">erreur</string>
<string name="select_ble_device">select</string>
<string name="main_shared_pref">com.example.co2sense_app.SHARED_PREF_MAIN</string>
</resources>

View File

@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.CO2Sense_app" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<style name="Theme.CO2Sense_app" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
@ -10,7 +10,9 @@
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
<item name = "android:windowActionBar">false</item>
<item name = "android:windowNoTitle">true</item>
</style>
</resources>

7
battery_icon.svg Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
<g><path d="M964.8,374.6h-34.6v-39.2c0-27.9-22.6-50.5-50.5-50.5H60.5c-27.9,0-50.5,22.6-50.5,50.5v329.3c0,27.9,22.6,50.5,50.5,50.5h819.1c27.9,0,50.5-22.6,50.5-50.5v-39.2h34.6c14,0,25.2-11.3,25.2-25.2V399.9C990.1,385.9,978.7,374.6,964.8,374.6z M868.2,635.6c0,14-11.3,25.2-25.2,25.2H97.4c-14,0-25.3-11.3-25.3-25.2V364.3c0-14,11.3-25.2,25.3-25.2H843c14,0,25.2,11.3,25.2,25.2V635.6L868.2,635.6z"/></g>
</svg>

After

Width:  |  Height:  |  Size: 878 B

45
bluetooth-svgrepo-com.svg Normal file
View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 217.499 217.499" style="enable-background:new 0 0 217.499 217.499;" xml:space="preserve">
<g>
<path d="M123.264,108.749l45.597-44.488c1.736-1.693,2.715-4.016,2.715-6.441s-0.979-4.748-2.715-6.441l-50.038-48.82
c-2.591-2.528-6.444-3.255-9.78-1.853c-3.336,1.406-5.505,4.674-5.505,8.294v80.504l-42.331-41.3
c-3.558-3.471-9.255-3.402-12.727,0.156c-3.471,3.558-3.401,9.256,0.157,12.727l48.851,47.663l-48.851,47.663
c-3.558,3.471-3.628,9.169-0.157,12.727s9.17,3.628,12.727,0.156l42.331-41.3v80.504c0,3.62,2.169,6.888,5.505,8.294
c1.128,0.476,2.315,0.706,3.493,0.706c2.305,0,4.572-0.886,6.287-2.559l50.038-48.82c1.736-1.693,2.715-4.016,2.715-6.441
s-0.979-4.748-2.715-6.441L123.264,108.749z M121.539,30.354l28.15,27.465l-28.15,27.465V30.354z M121.539,187.143v-54.93
l28.15,27.465L121.539,187.143z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.1.3' apply false
id 'com.android.library' version '7.1.3' apply false
id 'com.android.application' version '7.3.1' apply false
id 'com.android.library' version '7.3.1' apply false
}
task clean(type: Delete) {

View File

@ -1,6 +1,6 @@
#Wed Apr 20 17:58:30 CEST 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME