Reader App

This commit is contained in:
Ramandeep
2022-02-25 16:33:45 +05:30
commit 0dfa2a50ca
285 changed files with 23159 additions and 0 deletions

2
app/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/build
*.iml

128
app/build.gradle Normal file
View File

@@ -0,0 +1,128 @@
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "no.Reader.android.iisc"
minSdkVersion 18
targetSdkVersion 29
versionCode 78
versionName "2.9.0"
resConfigs "en"
multiDexEnabled true
vectorDrawables.useSupportLibrary = true
}
buildTypes {
debug {
minifyEnabled false
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
// nRF Toolbox is using Play Service 10.2.0 in order to make the app working in China:
// https://developer.android.com/training/wearables/apps/creating-app-china.html
//noinspection GradleDependency
implementation 'com.google.android.gms:play-services-wearable:10.2.0'
implementation 'androidx.appcompat:appcompat:1.3.0-alpha01'
implementation 'androidx.preference:preference:1.1.1'
implementation 'de.hdodenhof:circleimageview:3.1.0'
implementation 'no.nordicsemi.android:log:2.2.0'
implementation 'no.nordicsemi.android.support.v18:scanner:1.4.3'
implementation 'org.apache.poi:poi:4.0.0'
implementation 'org.apache.poi:poi-ooxml:4.0.0'
implementation 'com.android.support:multidex:1.0.1'
// The DFU Library is imported automatically from jcenter:
implementation 'no.nordicsemi.android:dfu:1.10.3'
implementation 'com.github.PhilJay:MPAndroidChart:v2.2.4'
implementation 'androidx.appcompat:appcompat:1.1.0-alpha04'
implementation 'com.hbb20:ccp:2.4.0'
implementation 'androidx.preference:preference:1.1.0-alpha04'
implementation 'com.google.android.material:material:1.1.0-alpha05'
implementation 'com.google.android.material:material:1.1.0'
implementation 'com.google.firebase:firebase-database:16.0.4'
implementation 'androidx.appcompat:appcompat:1.1.0-alpha04'
implementation 'com.google.firebase:firebase-auth:16.0.5'
implementation 'androidx.preference:preference:1.1.0-alpha04'
implementation 'no.nordicsemi.android:log:2.2.0'
implementation 'com.chaos.view:pinview:1.4.3'
implementation "androidx.browser:browser:1.3.0"
implementation 'com.github.bumptech.glide:glide:4.11.0'
implementation 'com.firebaseui:firebase-ui-database:7.1.1'
implementation 'com.github.PhilJay:MPAndroidChart:v2.2.4'
implementation 'com.google.firebase:firebase-crashlytics:17.1.1'
implementation 'com.hbb20:ccp:2.4.0'
implementation 'com.google.firebase:firebase-auth:20.0.1'
implementation 'com.google.android.material:material:1.0.0'
implementation 'com.google.firebase:firebase-storage:16.0.4'
// if you desire to build the DFU Library, clone the
// https://github.com/NordicSemiconductor/Android-DFU-Library project into DFULibrary folder,
// add it as a module into the project structure and uncomment the following line
// (and also the according lines in the settings.gradle):
// implementation project(':dfu')
// Gson is needed for DFU to work. The DFU library dependency to Gson is internal and would
// not be attached to APK.
// See: https://github.com/NordicSemiconductor/Android-nRF-Toolbox/issues/86
// Import the BLE Common Library.
// The BLE Common Library depends on BLE Library. It is enough to include the first one.
implementation 'no.nordicsemi.android:ble-common:2.1.1'
// The BLE Common Library may be included from jcenter. If you want to modify the code,
// clone both projects from GitHub and replace the line above with the following
// (and also the according lines in the settings.gradle):
// implementation project(':ble-common')
implementation('org.simpleframework:simple-xml:2.7.1') {
exclude group: 'stax', module: 'stax-api'
exclude group: 'xpp3', module: 'xpp3'
}
}

48
app/google-services.json Normal file
View File

@@ -0,0 +1,48 @@
{
"project_info": {
"project_number": "168819095878",
"firebase_url": "https://reader-app-43cb6-default-rtdb.firebaseio.com",
"project_id": "reader-app-43cb6",
"storage_bucket": "reader-app-43cb6.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:168819095878:android:9d4989cee1616d1a444d47",
"android_client_info": {
"package_name": "no.Reader.android.iisc"
}
},
"oauth_client": [
{
"client_id": "168819095878-f1d70oknl1g9l4sbrrlb6eniqchmtgb7.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "no.Reader.android.iisc",
"certificate_hash": "cd10342afabfcce43c9dc370cf20c4c2d6e1b1dd"
}
},
{
"client_id": "168819095878-7a1tejv9lv3o144c9v5fj6bls8vi2soc.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyCdG2nyJYp-71n67JtjsfKJCS00XUzKFQk"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "168819095878-7a1tejv9lv3o144c9v5fj6bls8vi2soc.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
}
],
"configuration_version": "1"
}

Binary file not shown.

81
app/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,81 @@
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-dontpreverify
-dontshrink
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-keepattributes *Annotation*
-keepattributes Signature
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
# The AndroidX library contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older platform version.
-dontwarn androidx.**
-keep class com.google.android.gms.**
-dontwarn com.google.android.gms.**
# Java
-keep class java.** { *; }
-dontnote java.**
-dontwarn java.**
-keep class javax.** { *; }
-dontnote javax.**
-dontwarn javax.**
-keep class sun.misc.Unsafe { *; }
-dontnote sun.misc.Unsafe
-keep class javax.xml.stream.XMLOutputFactory { *; }
# (the rt.jar has them)
-dontwarn com.bea.xml.stream.XMLWriterBase
-dontwarn javax.xml.stream.events.**
-dontwarn javax.xml.stream.**
# Simple XML
-keep public class org.simpleframework.** { *; }
-keep class org.simpleframework.xml.** { *; }
-keep class org.simpleframework.xml.core.** { *; }
-keep class org.simpleframework.xml.util.** { *; }
-keepattributes ElementList, Root, InnerClasses, LineNumberTable
-keepclasseswithmembers class * {
@org.simpleframework.xml.* <fields>;
}
# Chart Engine
-keep class org.achartengine.** { *; }
-dontnote org.achartengine.**
# HTTP (might require legacyLibraries) ?
-dontnote org.apache.http.params.**
-dontnote org.apache.http.conn.scheme.**
-dontnote org.apache.http.conn.**
-dontnote android.net.http.**
# DFU Library
-keep class no.nordicsemi.android.dfu.** { *; }

View File

@@ -0,0 +1,13 @@
package no.Reader.android.iisc;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}

View File

@@ -0,0 +1,149 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="no.Reader.android.iisc"
android:installLocation="auto">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="no.nordicsemi.android.LOG" />
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="true" />
<application
android:name="no.Reader.android.iisc.NotificationData"
android:allowBackup="true"
android:fullBackupContent="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<activity android:name="no.Reader.android.iisc.Reader.ViewGraph"
android:screenOrientation="landscape"></activity>
<activity android:name="no.Reader.android.iisc.Reader.ViewSamples"
android:screenOrientation="landscape"/>
<activity android:name="no.Reader.android.iisc.Reader.Datashow" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_path" />
</provider>
<activity android:name="no.Reader.android.iisc.Reader.Try1" />
<activity
android:name="no.Reader.android.iisc.Reader.check1"
android:screenOrientation="portrait" />
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<activity
android:name="no.Reader.android.iisc.SplashscreenActivity"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.SplashScreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" />
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/vnd.no.nordicsemi.type.app" />
<data android:mimeType="application/vnd.no.nordicsemi.type.address" />
</intent-filter>
</activity>
<activity
android:name="no.Reader.android.iisc.FeaturesActivity"
android:label="@string/app_name"
android:launchMode="singleTask"
android:theme="@style/AppTheme.TranslucentStatusBar" />
<!--
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
-->
<!-- Template plugin activities -->
<!-- Remember to add your plug-in Activities to the Android Manifest file. -->
<activity
android:name="no.Reader.android.iisc.Reader.TemplateActivity"
android:screenOrientation="portrait"
android:icon="@drawable/ic_template_feature"
android:label="@string/template_feature_title" />
<activity android:name="no.Reader.android.iisc.Reader.TestDetails" android:screenOrientation="portrait"/>
<activity android:name="no.Reader.android.iisc.Reader.About" android:screenOrientation="portrait"/>
<activity
android:name="no.Reader.android.iisc.Reader.settings.SettingsActivity"
android:label="@string/template_settings_title" />
<service
android:name="no.Reader.android.iisc.Reader.SPCAService"
android:label="@string/template_feature_title" /> <!-- Plug-in activities -->
<activity android:name="no.Reader.android.iisc.Reader.TemplateActivity1"
android:screenOrientation="portrait"/>
<activity android:name="no.Reader.android.iisc.Reader.TemplateActivity2"
android:screenOrientation="portrait"/>
<activity android:name="no.Reader.android.iisc.Reader.PositiveResult"
android:screenOrientation="portrait"/>
<activity android:name="no.Reader.android.iisc.Reader.NegativeResults"
android:screenOrientation="portrait"/>
<activity android:name="no.Reader.android.iisc.Reader.TemplateActivity3"
android:screenOrientation="portrait"/>
<activity android:name="no.Reader.android.iisc.Reader.Register"
android:screenOrientation="portrait"/>
<activity android:name="no.Reader.android.iisc.Reader.CreatePassword"
android:screenOrientation="portrait"/>
<activity android:name="no.Reader.android.iisc.Reader.ForgetPasswordReset"
android:screenOrientation="portrait"/>
<activity android:name="no.Reader.android.iisc.Reader.LoginScreen"
android:screenOrientation="portrait"/>
<activity android:name="no.Reader.android.iisc.Reader.VerifyOTP.VerifyOtpForgetPassword"
android:screenOrientation="portrait"/>
<activity android:name="no.Reader.android.iisc.Reader.VerifyOTP.VerifyOtp"
android:screenOrientation="portrait"/>
<activity android:name="no.Reader.android.iisc.Reader.ForgetPassword"
android:screenOrientation="portrait"/>
<activity android:name="no.Reader.android.iisc.Reader.MainActivity"
android:screenOrientation="portrait"/>
<activity android:name="no.Reader.android.iisc.Reader.NavigationTop"
android:screenOrientation="portrait"/>
</application>
</manifest>

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

@@ -0,0 +1,50 @@
package no.Reader.android.iisc;
import android.util.Log;
public class DebugLogger {
public static void v(final String tag, final String text) {
if (BuildConfig.DEBUG)
Log.v(tag, text);
}
public static void d(final String tag, final String text) {
if (BuildConfig.DEBUG) {
Log.d(tag, text);
}
}
public static void i(final String tag, final String text) {
if (BuildConfig.DEBUG)
Log.i(tag, text);
}
public static void w(final String tag, final String text) {
if (BuildConfig.DEBUG) {
Log.w(tag, text);
}
}
public static void e(final String tag, final String text) {
if (BuildConfig.DEBUG)
Log.e(tag, text);
}
public static void e(final String tag, final String text, final Throwable e) {
if (BuildConfig.DEBUG)
Log.e(tag, text, e);
}
public static void wtf(final String tag, final String text) {
if (BuildConfig.DEBUG) {
Log.wtf(tag, text);
}
}
public static void wtf(final String tag, final String text, final Throwable e) {
if (BuildConfig.DEBUG) {
Log.wtf(tag, text, e);
}
}
}

View File

@@ -0,0 +1,169 @@
package no.Reader.android.iisc;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.view.View;
import android.widget.GridView;
import android.widget.Toast;
import no.Reader.android.iisc.adapter.AppAdapter;
public class FeaturesActivity extends AppCompatActivity {
private static final String NRF_CONNECT_CATEGORY = "no.Reader.android.iisc.LAUNCHER";
private static final String UTILS_CATEGORY = "no.Reader.android.iisc.UTILS";
private static final String NRF_CONNECT_PACKAGE = "no.nordicsemi.android.mcp";
private static final String NRF_CONNECT_CLASS = NRF_CONNECT_PACKAGE + ".DeviceListActivity";
private static final String NRF_CONNECT_MARKET_URI = "market://details?id=no.nordicsemi.android.mcp";
// Extras that can be passed from NFC (see SplashscreenActivity)
public static final String EXTRA_APP = "application/vnd.no.nordicsemi.type.app";
public static final String EXTRA_ADDRESS = "application/vnd.no.nordicsemi.type.address";
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_features);
final Toolbar toolbar = findViewById(R.id.toolbar_actionbar);
setSupportActionBar(toolbar);
// ensure that Bluetooth exists
if (!ensureBLEExists())
finish();
final DrawerLayout drawer = mDrawerLayout = findViewById(R.id.drawer_layout);
drawer.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
// Set the drawer toggle as the DrawerListener
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.string.drawer_open, R.string.drawer_close) {
@Override
public void onDrawerSlide(final View drawerView, final float slideOffset) {
// Disable the Hamburger icon animation
super.onDrawerSlide(drawerView, 0);
}
};
drawer.addDrawerListener(mDrawerToggle);
// setup plug-ins in the drawer
//setupPluginsInDrawer(drawer.findViewById(R.id.plugin_container));
// configure the app grid
final GridView grid = findViewById(R.id.grid);
grid.setAdapter(new AppAdapter(this));
grid.setEmptyView(findViewById(android.R.id.empty));
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
final Intent intent = getIntent();
if (intent.hasExtra(EXTRA_APP) && intent.hasExtra(EXTRA_ADDRESS)) {
final String app = intent.getStringExtra(EXTRA_APP);
switch (app) {
/*case "HRM":
final Intent newIntent = new Intent(this, HRSActivity.class);
newIntent.putExtra(EXTRA_ADDRESS, intent.getByteArrayExtra(EXTRA_ADDRESS));
newIntent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(newIntent);
break;*/
default:
// other are not supported yet
break;
}
}
}
@Override
protected void onPostCreate(final Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(@NonNull final Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
/*
private void setupPluginsInDrawer(final ViewGroup container) {
final LayoutInflater inflater = LayoutInflater.from(this);
final PackageManager pm = getPackageManager();
// look for nRF Connect
final Intent nrfConnectIntent = new Intent(Intent.ACTION_MAIN);
nrfConnectIntent.addCategory(NRF_CONNECT_CATEGORY);
nrfConnectIntent.setClassName(NRF_CONNECT_PACKAGE, NRF_CONNECT_CLASS);
final ResolveInfo nrfConnectInfo = pm.resolveActivity(nrfConnectIntent, 0);
// configure link to nRF Connect
final TextView nrfConnectItem = container.findViewById(R.id.link_mcp);
if (nrfConnectInfo == null) {
nrfConnectItem.setTextColor(Color.GRAY);
final ColorMatrix grayscale = new ColorMatrix();
grayscale.setSaturation(0.0f);
nrfConnectItem.getCompoundDrawables()[0].mutate().setColorFilter(new ColorMatrixColorFilter(grayscale));
}
nrfConnectItem.setOnClickListener(v -> {
Intent action = nrfConnectIntent;
if (nrfConnectInfo == null)
action = new Intent(Intent.ACTION_VIEW, Uri.parse(NRF_CONNECT_MARKET_URI));
action.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
action.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
startActivity(action);
} catch (final ActivityNotFoundException e) {
Toast.makeText(FeaturesActivity.this, R.string.no_application_play, Toast.LENGTH_SHORT).show();
}
mDrawerLayout.closeDrawers();
});
// look for other plug-ins
final Intent utilsIntent = new Intent(Intent.ACTION_MAIN);
utilsIntent.addCategory(UTILS_CATEGORY);
final List<ResolveInfo> appList = pm.queryIntentActivities(utilsIntent, 0);
for (final ResolveInfo info : appList) {
final View item = inflater.inflate(R.layout.drawer_plugin, container, false);
final ImageView icon = item.findViewById(android.R.id.icon);
final TextView label = item.findViewById(android.R.id.text1);
label.setText(info.loadLabel(pm));
icon.setImageDrawable(info.loadIcon(pm));
item.setOnClickListener(v -> {
final Intent intent = new Intent();
intent.setComponent(new ComponentName(info.activityInfo.packageName, info.activityInfo.name));
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
mDrawerLayout.closeDrawers();
});
container.addView(item);
}
}
*/
private boolean ensureBLEExists() {
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.no_ble, Toast.LENGTH_LONG).show();
return false;
}
return true;
}
}

View File

@@ -0,0 +1,35 @@
package no.Reader.android.iisc;
import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import androidx.appcompat.widget.AppCompatTextView;
public class FontAwesome extends AppCompatTextView {
public FontAwesome(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public FontAwesome(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public FontAwesome(Context context) {
super(context);
init();
}
private void init() {
Typeface tf = Typeface.createFromAsset(getContext().getAssets(),
"fa-solid-900.ttf");
setTypeface(tf);
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2017, Nordic Semiconductor
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package no.Reader.android.iisc;
import android.app.Application;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;
import no.nordicsemi.android.dfu.DfuServiceInitiator;
public class NotificationData extends Application {
public static final String CONNECTED_DEVICE_CHANNEL = "connected_device_channel";
public static final String FILE_SAVED_CHANNEL = "file_saved_channel";
public static final String PROXIMITY_WARNINGS_CHANNEL = "proximity_warnings_channel";
@Override
public void onCreate() {
super.onCreate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
DfuServiceInitiator.createDfuNotificationChannel(this);
final NotificationChannel channel = new NotificationChannel(CONNECTED_DEVICE_CHANNEL, getString(R.string.channel_connected_devices_title), NotificationManager.IMPORTANCE_LOW);
channel.setDescription(getString(R.string.channel_connected_devices_description));
channel.setShowBadge(false);
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
final NotificationChannel fileChannel = new NotificationChannel(FILE_SAVED_CHANNEL, getString(R.string.channel_files_title), NotificationManager.IMPORTANCE_LOW);
fileChannel.setDescription(getString(R.string.channel_files_description));
fileChannel.setShowBadge(false);
fileChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
final NotificationChannel proximityChannel = new NotificationChannel(PROXIMITY_WARNINGS_CHANNEL, getString(R.string.channel_proximity_warnings_title), NotificationManager.IMPORTANCE_LOW);
proximityChannel.setDescription(getString(R.string.channel_proximity_warnings_description));
proximityChannel.setShowBadge(false);
proximityChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
final NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
notificationManager.createNotificationChannel(fileChannel);
notificationManager.createNotificationChannel(proximityChannel);
}
}
}

View File

@@ -0,0 +1,58 @@
package no.Reader.android.iisc;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
import androidx.appcompat.app.AlertDialog;
public class PermissionRationaleFragment extends DialogFragment {
private static final String ARG_PERMISSION = "ARG_PERMISSION";
private static final String ARG_TEXT = "ARG_TEXT";
private PermissionDialogListener mListener;
public interface PermissionDialogListener {
void onRequestPermission(final String permission);
}
@Override
public void onAttach(final Context context) {
super.onAttach(context);
if (context instanceof PermissionDialogListener) {
mListener = (PermissionDialogListener) context;
} else {
throw new IllegalArgumentException("The parent activity must impelemnt PermissionDialogListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public static PermissionRationaleFragment getInstance(final int aboutResId, final String permission) {
final PermissionRationaleFragment fragment = new PermissionRationaleFragment();
final Bundle args = new Bundle();
args.putInt(ARG_TEXT, aboutResId);
args.putString(ARG_PERMISSION, permission);
fragment.setArguments(args);
return fragment;
}
@Override
@NonNull
public Dialog onCreateDialog(final Bundle savedInstanceState) {
final Bundle args = getArguments();
final StringBuilder text = new StringBuilder(getString(args.getInt(ARG_TEXT)));
return new AlertDialog.Builder(getActivity()).setTitle(R.string.permission_title).setMessage(text)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.ok, (dialog, which) -> mListener.onRequestPermission(args.getString(ARG_PERMISSION))).create();
}
}

View File

@@ -0,0 +1,24 @@
package no.Reader.android.iisc.Reader;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import no.Reader.android.iisc.R;
public class About extends NavigationTop {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater inflater = (LayoutInflater) this
.getSystemService(LAYOUT_INFLATER_SERVICE);
View contentView = inflater.inflate(R.layout.activity_about, null, false);
draw.addView(contentView, 0);
/* LayoutInflater inflater = (LayoutInflater) this
.getSystemService(LAYOUT_INFLATER_SERVICE);
View contentView = inflater.inflate(R.layout.activity_about, null, false);
*/
}
}

View File

@@ -0,0 +1,110 @@
package no.Reader.android.iisc.Reader;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import no.Reader.android.iisc.R;
import no.Reader.android.iisc.Reader.Model.RegisterHelper;
public class CreatePassword extends AppCompatActivity {
private Button next;
String name,phonenumber,num1,num2;
private EditText passworddata;
private EditText ConfirmPassword;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create__password);
passworddata=findViewById(R.id.password);
ConfirmPassword=findViewById(R.id.confirmpassword);
next=findViewById(R.id.next);
next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
num1 = ConfirmPassword.getText().toString();
num2 = passworddata.getText().toString();
if (!isOnline()) {
//Create an alertdialog
AlertDialog.Builder Checkbuilder = new AlertDialog.Builder(CreatePassword.this);
Checkbuilder.setTitle("No Internet Connection !");
Checkbuilder.setMessage("Check Your Internet Connection.");
//Builder Retry Button
Checkbuilder.setPositiveButton("Retry", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
Checkbuilder.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
AlertDialog alert = Checkbuilder.create();
alert.show();
} else {
if (num1.equals(num2)) {
Intent intent = new Intent(CreatePassword.this, LoginScreen.class);
name = getIntent().getStringExtra("username");
String phonenumberk = getIntent().getStringExtra("mobile");
phonenumber = phonenumberk;
FirebaseDatabase rootNode = FirebaseDatabase.getInstance();
DatabaseReference reference = rootNode.getReference("USERS");
RegisterHelper addNewUser = new RegisterHelper(name, phonenumber, num1);
reference.child(phonenumber).setValue(addNewUser);
intent.putExtra("mobile", phonenumber);
intent.putExtra("username", name);
Toast.makeText(CreatePassword.this, "You are Registered Successfully ", Toast.LENGTH_SHORT).show();
startActivity(intent);
} else {
ConfirmPassword.setError("Password does not match");
}
}
}
});
}
public boolean isOnline() {
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnected());
}
}

View File

@@ -0,0 +1,103 @@
package no.Reader.android.iisc.Reader;
import android.os.Bundle;
import android.content.SharedPreferences;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import no.Reader.android.iisc.Reader.Model.Tests;
import no.Reader.android.iisc.R;
public class Datashow extends NavigationTop {
private ImageView Imageview1;
TextView patient_id,patient_dob,patientnikshayid,agepatient,patientgender,patientsample,validatyd,spintubeid,nirtlab,dated,timed,resultd;
String date,time,number;
private String TestID = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater inflater = (LayoutInflater) this
.getSystemService(LAYOUT_INFLATER_SERVICE);
View contentView = inflater.inflate(R.layout.activity_datashow, null, false);
draw.addView(contentView, 0);
patient_id=findViewById(R.id.patient_idr);
patient_dob=findViewById(R.id.patien_dobr);
patientnikshayid=findViewById(R.id.patient_nikshayidr);
SharedPreferences preferences6 = getSharedPreferences("PhoneBook_number", MODE_PRIVATE);
number = preferences6.getString("Phone", null);
agepatient=findViewById(R.id.patient_ager);
date = String.valueOf(android.text.format.DateFormat.format("dd-MM-yyyy", new java.util.Date()));
DateFormat df = new SimpleDateFormat("h:mm a");
time = df.format(Calendar.getInstance().getTime());
patientgender=findViewById(R.id.patient_genderr);
patientsample=findViewById(R.id.patient_typesampler);
validatyd=findViewById(R.id.patient_tubevisibler);
spintubeid=findViewById(R.id.patient_spintuber);
nirtlab=findViewById(R.id.patient_nirtr);
timed=findViewById(R.id.timer);
resultd=findViewById(R.id.patient_resultr);
dated=findViewById(R.id.dater);
TestID = getIntent().getStringExtra("pid");
Log.e("main", "error id "+TestID);
getTestDetails(TestID);
}
private void getTestDetails(String TestID)
{
DatabaseReference productsRef = FirebaseDatabase.getInstance().getReference().child("Test_Data").child(number);
productsRef.child(TestID).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot)
{
if (dataSnapshot.exists())
{
Tests products = dataSnapshot.getValue(Tests.class);
patient_id.setText(products.getTest_Id());
patient_dob.setText(products.getSample_Date());
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}

View File

@@ -0,0 +1,35 @@
package no.Reader.android.iisc.Reader;
import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import androidx.appcompat.widget.AppCompatTextView;
public class FontAwesome extends AppCompatTextView {
public FontAwesome(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public FontAwesome(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public FontAwesome(Context context) {
super(context);
init();
}
private void init() {
Typeface tf = Typeface.createFromAsset(getContext().getAssets(),
"fa-solid-900.ttf");
setTypeface(tf);
}
}

View File

@@ -0,0 +1,260 @@
package no.Reader.android.iisc.Reader;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.chaos.view.PinView;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.TaskExecutors;
import com.google.firebase.FirebaseException;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.PhoneAuthCredential;
import com.google.firebase.auth.PhoneAuthProvider;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
import com.google.firebase.database.ValueEventListener;
import com.hbb20.CountryCodePicker;
import java.util.concurrent.TimeUnit;
import no.Reader.android.iisc.R;
import no.Reader.android.iisc.Reader.VerifyOTP.VerifyOtpForgetPassword;
public class ForgetPassword extends AppCompatActivity {
private String verificationid;
private FirebaseAuth mAuth;
private int code = 91;
private Button nextactivity;
private ProgressBar progressBar;
CountryCodePicker ccp;
PinView pinFromUser;
String mobile;
private EditText editTextnumber;
String codeBySystem;
boolean exists;
String address,name, state , city ,pincode,phonenumber,password2,num1,phonenum;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_forget__password);
editTextnumber=findViewById(R.id.editTextMobile);
ccp=findViewById(R.id.ccp);
ccp.registerCarrierNumberEditText(editTextnumber);
// nextactivity = findViewById(R.id.buttonSignIn);
mAuth = FirebaseAuth.getInstance();
findViewById(R.id.buttonSignIn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!isOnline()) {
//Create an alertdialog
AlertDialog.Builder Checkbuilder = new AlertDialog.Builder(ForgetPassword.this);
Checkbuilder.setTitle("No Internet Connection !");
Checkbuilder.setMessage("Check Your Internet Connection.");
//Builder Retry Button
Checkbuilder.setPositiveButton("Retry", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
/* //Restart The Activity
Intent intent = getIntent();
finish();
startActivity(intent);*/
dialog.cancel();
}
});
Checkbuilder.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
AlertDialog alert = Checkbuilder.create();
alert.show();
} else {
mobile = editTextnumber.getText().toString().trim();
mobile = mobile.replaceAll("[^0-9]", "");
phonenum = ccp.getFullNumberWithPlus();
if(mobile.equals(""))
{
editTextnumber.setError("Enter the contact number");
}
Query chekuser = FirebaseDatabase.getInstance().getReference("USERS").orderByChild("number").equalTo(mobile);
chekuser.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
Intent intent = new Intent(ForgetPassword.this, VerifyOtpForgetPassword.class);
Toast.makeText(ForgetPassword.this, "We Have Sent the OTP to your mentioned Number", Toast.LENGTH_SHORT).show();
intent.putExtra("mobilecode", phonenum);
intent.putExtra("mobile", mobile);
startActivity(intent);
} else {
// Toast.makeText(ForgetPassword.this,phonenum,Toast.LENGTH_SHORT).show();
editTextnumber.setError("No Such User Exists");
// Toast.makeText(ForgetPassword.this,"NO such user exists",Toast.LENGTH_SHORT).show();
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
Log.e("Raman", "Received an exception check chexk " + databaseError.getMessage());
// Toast.makeText(ForgetPassword.this,databaseError.getMessage(),Toast.LENGTH_SHORT).show();
}
});
}
}
});
}
private void verifyCode(String code){
PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationid, code);
signInWithCredential(credential);
}
private void signInWithCredential(PhoneAuthCredential credential) {
mAuth.signInWithCredential(credential)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
Intent intent = new Intent(ForgetPassword.this, ForgetPasswordReset.class);
intent.putExtra("mobile", mobile);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
} else {
Toast.makeText(ForgetPassword.this, task.getException().getMessage(), Toast.LENGTH_LONG).show();
}
}
});
}
private void sendVerificationCode(String number){
PhoneAuthProvider.getInstance().verifyPhoneNumber(
number,
60,
TimeUnit.SECONDS,
(Activity) TaskExecutors.MAIN_THREAD,
mCallBack
);
}
private PhoneAuthProvider.OnVerificationStateChangedCallbacks
mCallBack = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
@Override
public void onCodeSent(String s, PhoneAuthProvider.ForceResendingToken forceResendingToken) {
super.onCodeSent(s, forceResendingToken);
verificationid = s;
}
@Override
public void onVerificationCompleted(PhoneAuthCredential phoneAuthCredential) {
String code = phoneAuthCredential.getSmsCode();
if (code != null){
progressBar.setVisibility(View.VISIBLE);
pinFromUser.setText(code);
verifyCode(code);
}
}
@Override
public void onVerificationFailed(FirebaseException e) {
Toast.makeText(ForgetPassword.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
};
private void checkuserexist(String number)
{
Query chekuser= FirebaseDatabase.getInstance().getReference("USERS").orderByChild("number").equalTo(number);
chekuser.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists())
{
exists= true;
}
else
{
exists=false;
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
Toast.makeText(ForgetPassword.this,databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
public boolean isOnline() {
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnected());
}
}

View File

@@ -0,0 +1,69 @@
package no.Reader.android.iisc.Reader;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import no.Reader.android.iisc.R;
public class ForgetPasswordReset extends AppCompatActivity {
private Button next;
String phonenumber,num1,num2;
private EditText passworddata;
private EditText ConfirmPassword;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create__password);
passworddata=findViewById(R.id.password);
ConfirmPassword=findViewById(R.id.confirmpassword);
next=findViewById(R.id.next);
next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
num1 = ConfirmPassword.getText().toString();
num2=passworddata.getText().toString();
if(num1.equals(num2)) {
Intent intent = new Intent(ForgetPasswordReset.this, LoginScreen.class);
String phonenumberk = getIntent().getStringExtra("mobile");
phonenumber = phonenumberk;
FirebaseDatabase rootNode = FirebaseDatabase.getInstance();
DatabaseReference reference = rootNode.getReference("USERS");
reference.child(phonenumber).child("password").setValue(num1);
Toast.makeText(ForgetPasswordReset.this, "Password Reset Successfully ", Toast.LENGTH_SHORT).show();
startActivity(intent);
}
else
{
ConfirmPassword.setError("Password does not match");
}
}
});
}
}

View File

@@ -0,0 +1,9 @@
package no.Reader.android.iisc.Reader.Interface;
import android.view.View;
public interface ItemClickListner
{
void onClick(View view, int position, boolean isLongClick);
}

View File

@@ -0,0 +1,250 @@
package no.Reader.android.iisc.Reader;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.text.method.HideReturnsTransformationMethod;
import android.text.method.PasswordTransformationMethod;
import android.util.Patterns;
import android.view.View;
import android.view.animation.Animation;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.AppCompatCheckBox;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
import com.google.firebase.database.ValueEventListener;
import no.Reader.android.iisc.R;
public class LoginScreen extends AppCompatActivity {
private TextView createaccount, forgetpassword;
private Button login;
private DatabaseReference databaseReference;
private EditText phonenumber, password;
String passworddata, phonenum, phonenumbers, name;
private ProgressDialog loadingBar;
public static final String Name = "nameKey";
public static final String Phone = "phoneKey";
private ImageButton close;
Animation btnAnim ;
private AppCompatCheckBox checkbox;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login__screen);
createaccount = findViewById(R.id.createaccount);
phonenumber = findViewById(R.id.contactnumber);
checkbox = (AppCompatCheckBox) findViewById(R.id.showpassword);
password = findViewById(R.id.password);
checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
if (isChecked) {
// show password
password.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
} else {
// hide password
password.setTransformationMethod(PasswordTransformationMethod.getInstance());
}
}
});
// Paper.init(this);
loadingBar = new ProgressDialog(this);
// Paper.init(this);
login = findViewById(R.id.login);
forgetpassword = findViewById(R.id.forgetpassword);
forgetpassword.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(LoginScreen.this, ForgetPassword.class);
startActivity(intent);
}
});
login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!isOnline()) {
//Create an alertdialog
AlertDialog.Builder Checkbuilder = new AlertDialog.Builder(LoginScreen.this);
Checkbuilder.setTitle("No Internet Connection !");
Checkbuilder.setMessage("Check Your Internet Connection.");
//Builder Retry Button
Checkbuilder.setPositiveButton("Retry", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
Checkbuilder.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
AlertDialog alert = Checkbuilder.create();
alert.show();
} else {
String mobile = phonenumber.getText().toString().trim();
phonenum = mobile;
final String passwordj = password.getText().toString().trim();
if (mobile.equals("") || passwordj.equals("")) {
Toast.makeText(LoginScreen.this, "Please enter all the required fields", Toast.LENGTH_SHORT).show();
} else if (!Patterns.PHONE.matcher(mobile).matches()) {
phonenumber.setError("Enter a valid number");
} else {
loadingBar.setTitle("Login Account");
loadingBar.setMessage("Please wait, while we are checking the credentials.");
loadingBar.setCanceledOnTouchOutside(false);
loadingBar.show();
Query chekuser = FirebaseDatabase.getInstance().getReference("USERS").orderByChild("number").equalTo(phonenum);
chekuser.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
String systempassword = dataSnapshot.child(phonenum).child("password").getValue(String.class);
if (systempassword.equals(passwordj)) {
Toast.makeText(LoginScreen.this, "logged in Successfully...", Toast.LENGTH_SHORT).show();
loadingBar.dismiss();
String name = dataSnapshot.child(phonenum).child("name").getValue(String.class);
SharedPreferences preferences = getSharedPreferences("PhoneBook_number", MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
// editor.putString(Name, phonenum);
editor.putString("Phone", phonenum);
editor.putString("Name", name);
editor.commit();
Intent intent = new Intent(LoginScreen.this, MainActivity.class);
intent.putExtra("mobile", phonenum);
startActivity(intent);
} else {
loadingBar.dismiss();
Toast.makeText(LoginScreen.this, "Wrong Password", Toast.LENGTH_SHORT).show();
}
} else {
loadingBar.dismiss();
Toast.makeText(LoginScreen.this, "No such user exists", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
Toast.makeText(LoginScreen.this, databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
}
});
createaccount.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(LoginScreen.this, Register.class);
startActivity(intent);
}
});
}
private void finishQuiz() {
if (!isOnline()) {
AlertDialog.Builder Checkbuilder = new AlertDialog.Builder(LoginScreen.this);
Checkbuilder.setTitle("Error!");
Checkbuilder.setMessage("Enable your internet connection and Retry ");
Checkbuilder.setPositiveButton("Retry", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
Checkbuilder.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
}
);
AlertDialog alert = Checkbuilder.create();
alert.show();
}
}
@Override
public void onBackPressed() {
finishAffinity();
finish();
}
public boolean isOnline() {
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnected());
}
}

View File

@@ -0,0 +1,255 @@
package no.Reader.android.iisc.Reader;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SearchView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
import no.Reader.android.iisc.R;
import no.Reader.android.iisc.Reader.Model.Tests;
public class MainActivity extends NavigationTop {
private DatabaseReference TestRef;
private RecyclerView recyclerView;
private TextView info;
FloatingActionButton fasbs;
String number;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater inflater = (LayoutInflater) this
.getSystemService(LAYOUT_INFLATER_SERVICE);
View contentView = inflater.inflate(R.layout.activity_main, null, false);
draw.addView(contentView, 0);
SharedPreferences preferences6 = getSharedPreferences("PhoneBook_number", MODE_PRIVATE);
number = preferences6.getString("Phone", null);
fasbs=findViewById(R.id.fab);
info=findViewById(R.id.info);
info.setVisibility(View.VISIBLE);
Log.e("main", "error "+number);
TestRef = FirebaseDatabase.getInstance().getReference().child("Test_Data").child(number);
recyclerView = findViewById(R.id.recycler_view);
fasbs.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(MainActivity.this, TestDetails.class);
startActivity(intent);
}
});
LinearLayoutManager layoutManager1=new LinearLayoutManager(this);
recyclerView.setLayoutManager(new GridLayoutManager(this, 1));
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels / 8;
int spaceInPixel = 4;
recyclerView.addItemDecoration(new SpaceDecoration(spaceInPixel));
}
@Override
protected void onStart()
{
super.onStart();
FirebaseRecyclerOptions<Tests> options =
new FirebaseRecyclerOptions.Builder<Tests>()
.setQuery(TestRef, Tests.class)
.build();
FirebaseRecyclerAdapter<Tests, TestViewHolder> adapter =
new FirebaseRecyclerAdapter<Tests, TestViewHolder>(options) {
@Override
protected void onBindViewHolder(@NonNull TestViewHolder holder, int position, @NonNull final Tests model)
{
if(model.getInternal().contains("Yes") || model.getInternal().contains("No"))
{
info.setVisibility(View.INVISIBLE);
}
if(model.getInternal().contains("Yes") )
{
holder.iconfinder.setBackgroundResource(R.drawable.green_circle);
holder.iconfinder.setText("I");
}
holder.txtpatientid.setText("User Name :"+model.getUser_Name());
holder.txtsampletype.setText("Test Id :" +model.getTest_Id());
holder.nikshay.setText("Volume :"+model.getSample_volume());
holder.txttimestamp.setText(model.getSample_Date());
//holder.txtProductDescription.setText(model.getSample());
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(MainActivity.this, ViewSamples.class);
Log.e("main", "error id"+model.getTest_Id());
Log.e("main", "TestID"+model.getTest_Id());
intent.putExtra("pid",model.getTest_Id());
startActivity(intent);
}
});
}
@NonNull
@Override
public TestViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
TestViewHolder holder = new TestViewHolder(view);
return holder;
}
};
recyclerView.setAdapter(adapter);
adapter.startListening();
}
private void firebasesearch(String data)
{
{
Query firebaseSearchQuery = TestRef.orderByChild("Test_Id").startAt(data).endAt(data + "\uf8ff");
FirebaseRecyclerOptions<Tests> options =
new FirebaseRecyclerOptions.Builder<Tests>()
.setQuery(firebaseSearchQuery, Tests.class)
.build();
FirebaseRecyclerAdapter<Tests, TestViewHolder> adapter =
new FirebaseRecyclerAdapter<Tests, TestViewHolder>(options) {
@Override
protected void onBindViewHolder(@NonNull final TestViewHolder holder, int position, @NonNull final Tests model)
{
if(model.getInternal().contains("Yes") || model.getInternal().contains("No"))
{
info.setVisibility(View.INVISIBLE);
}
if(model.getInternal().contains("Yes") )
{
holder.iconfinder.setBackgroundResource(R.drawable.green_circle);
holder.iconfinder.setText("I");
}
holder.txtpatientid.setText("User Name :"+model.getUser_Name());
holder.txtsampletype.setText("Test Id :" +model.getTest_Id());
holder.nikshay.setText("Volume :"+model.getSample_volume());
holder.txttimestamp.setText(model.getSample_Date());
//holder.txtProductDescription.setText(model.getSample());
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(MainActivity.this, ViewSamples.class);
Log.e("main", "error id"+model.getTest_Id());
Log.e("main", "TestID"+model.getTest_Id());
intent.putExtra("pid",model.getTest_Id());
startActivity(intent);
}
});
}
@NonNull
@Override
public TestViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
TestViewHolder holder = new TestViewHolder(view);
return holder;
}
};
recyclerView.setAdapter(adapter);
adapter.startListening();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater=getMenuInflater();
inflater.inflate(R.menu.searchmenu,menu);
MenuItem item = menu.findItem(R.id.search);
SearchView searchView = (SearchView) item.getActionView();
//searchView.setIconified(false);
//searchView.setIconifiedByDefault(false);
searchView.setQueryHint("Search Test ID");
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
query=query.toLowerCase();
firebasesearch(query);
// processsearch(query);
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
newText=newText.toLowerCase();
firebasesearch(newText);
// processsearch(query);
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
@Override
public void onBackPressed() {
finishAffinity();
finish();
}
}

View File

@@ -0,0 +1,41 @@
package no.Reader.android.iisc.Reader.Model;
import java.io.Serializable;
public class RegisterHelper implements Serializable {
public String name, number, password;
public RegisterHelper(String name, String number, String password) {
this.name = name;
this.number = number;
this.password = password;
}
public RegisterHelper() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

View File

@@ -0,0 +1,77 @@
package no.Reader.android.iisc.Reader.Model;
public class Tests {
private String Test_Id, Time, User_Name, Sample_volume, Sample_Date, Percentage, Internal;
public Tests() {
}
public Tests(String test_Id, String time, String user_Name, String sample_volume, String sample_Date, String percentage, String internal) {
Test_Id = test_Id;
Time = time;
User_Name = user_Name;
Sample_volume = sample_volume;
Sample_Date = sample_Date;
Percentage = percentage;
Internal = internal;
}
public String getTest_Id() {
return Test_Id;
}
public void setTest_Id(String test_Id) {
Test_Id = test_Id;
}
public String getTime() {
return Time;
}
public void setTime(String time) {
Time = time;
}
public String getUser_Name() {
return User_Name;
}
public void setUser_Name(String user_Name) {
User_Name = user_Name;
}
public String getSample_volume() {
return Sample_volume;
}
public void setSample_volume(String sample_volume) {
Sample_volume = sample_volume;
}
public String getSample_Date() {
return Sample_Date;
}
public void setSample_Date(String sample_Date) {
Sample_Date = sample_Date;
}
public String getPercentage() {
return Percentage;
}
public void setPercentage(String percentage) {
Percentage = percentage;
}
public String getInternal() {
return Internal;
}
public void setInternal(String internal) {
Internal = internal;
}
}

View File

@@ -0,0 +1,140 @@
package no.Reader.android.iisc.Reader;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.FileProvider;
import androidx.drawerlayout.widget.DrawerLayout;
import com.google.android.material.navigation.NavigationView;
import java.io.File;
import no.Reader.android.iisc.R;
public class Nav_Two extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
protected DrawerLayout draw;
private LinearLayout line;
private Toolbar tool;
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
switch (menuItem.getItemId())
{
case R.id.nav_contact_us:
Intent intent1=new Intent(this,About.class);
startActivity(intent1);
break;
case R.id.nav_result:
Intent intent2=new Intent(this, MainActivity.class);
startActivity(intent2);
break;
case R.id.nav_add_Test:
Intent intent3=new Intent(this, TestDetails.class);
startActivity(intent3);
break;
case R.id.nav_sample:
Intent intent6=new Intent(this, TemplateActivity2.class);
startActivity(intent6);
break;
case R.id.nav_negative:
Intent intent4=new Intent(this, NegativeResults.class);
startActivity(intent4);
break;
case R.id.nav_positive:
Intent intent5=new Intent(this, PositiveResult.class);
startActivity(intent5);
break;
case R.id.nav_logout:
Intent intent8=new Intent(this, LoginScreen.class);
SharedPreferences preferences = getSharedPreferences("PhoneBook_number", MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
// editor.putString(Name, phonenum);
editor.putString("Phone", null);
editor.putString("Name",null);
editor.commit();
startActivity(intent8);
break;
}
return true;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.nav_two);
draw = findViewById(R.id.Drawer);
line = findViewById(R.id.line);
tool = findViewById(R.id.tollbar);
NavigationView navigationView = findViewById(R.id.navigation);
navigationView.setNavigationItemSelectedListener(this);
setSupportActionBar(tool);
Window window = getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, draw, tool, R.string.open_navigation_drawer, R.string.close_navigation_drawer) {
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
float sidebar = drawerView.getWidth() * slideOffset;
line.setTranslationX(sidebar);
}
};
draw.addDrawerListener(toggle);
toggle.syncState();
View headerView = navigationView.getHeaderView(0);
TextView textView=headerView.findViewById(R.id.text);
TextView textView1=headerView.findViewById(R.id.not_sign_in);
SharedPreferences preferences=getSharedPreferences("PhoneBook_number",MODE_PRIVATE);
String string1 = preferences.getString("Phone", null);
String string2 = preferences.getString("Name", null);
textView.setText(string2);
textView1.setText(string1);
}
public void shared( String testid) {
String directory_path = Environment.getExternalStorageDirectory().getPath() + "/Test Report/";
String pat= directory_path + "Report_" + testid + ".xls";
Intent intent = new Intent(Intent.ACTION_VIEW);
File file = new File(pat);
Uri path = FileProvider.getUriForFile(getApplicationContext(), "no.Reader.android.iisc.fileprovider", file);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(path, "application/vnd.ms-excel");
startActivity(intent);
}
}

View File

@@ -0,0 +1,122 @@
package no.Reader.android.iisc.Reader;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.drawerlayout.widget.DrawerLayout;
import com.google.android.material.navigation.NavigationView;
import no.Reader.android.iisc.R;
public class NavigationTop extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
protected DrawerLayout draw;
private LinearLayout line;
private Toolbar tool;
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
switch (menuItem.getItemId())
{
case R.id.nav_contact_us:
Intent intent1=new Intent(this,About.class);
startActivity(intent1);
break;
case R.id.nav_result:
Intent intent2=new Intent(this, MainActivity.class);
startActivity(intent2);
break;
case R.id.nav_add_Test:
Intent intent3=new Intent(this, TestDetails.class);
startActivity(intent3);
break;
case R.id.nav_sample:
Intent intent6=new Intent(this, TemplateActivity2.class);
startActivity(intent6);
break;
case R.id.nav_negative:
Intent intent4=new Intent(this, NegativeResults.class);
startActivity(intent4);
break;
case R.id.nav_positive:
Intent intent5=new Intent(this, PositiveResult.class);
startActivity(intent5);
break;
case R.id.nav_logout:
Intent intent8=new Intent(this, LoginScreen.class);
SharedPreferences preferences = getSharedPreferences("PhoneBook_number", MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
// editor.putString(Name, phonenum);
editor.putString("Phone", null);
editor.putString("Name",null);
editor.commit();
startActivity(intent8);
break;
}
return true;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_navigation__top);
draw = findViewById(R.id.Drawer);
line = findViewById(R.id.line);
tool = findViewById(R.id.tollbar);
NavigationView navigationView = findViewById(R.id.navigation);
navigationView.setNavigationItemSelectedListener(this);
setSupportActionBar(tool);
Window window = getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, draw, tool, R.string.open_navigation_drawer, R.string.close_navigation_drawer) {
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
float sidebar = drawerView.getWidth() * slideOffset;
line.setTranslationX(sidebar);
}
};
draw.addDrawerListener(toggle);
toggle.syncState();
View headerView = navigationView.getHeaderView(0);
TextView textView=headerView.findViewById(R.id.text);
TextView textView1=headerView.findViewById(R.id.not_sign_in);
SharedPreferences preferences=getSharedPreferences("PhoneBook_number",MODE_PRIVATE);
String string1 = preferences.getString("Phone", null);
String string2 = preferences.getString("Name", null);
textView.setText(string2);
textView1.setText(string1);
}
}

View File

@@ -0,0 +1,200 @@
package no.Reader.android.iisc.Reader;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
import no.Reader.android.iisc.R;
import no.Reader.android.iisc.Reader.Model.Tests;
public class NegativeResults extends NavigationTop {
private DatabaseReference TestRef;
private RecyclerView recyclerView;
private TextView info;
FloatingActionButton fasbs;
String number;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater inflater = (LayoutInflater) this
.getSystemService(LAYOUT_INFLATER_SERVICE);
View contentView = inflater.inflate(R.layout.activity_main, null, false);
draw.addView(contentView, 0);
SharedPreferences preferences6 = getSharedPreferences("PhoneBook_number", MODE_PRIVATE);
number = preferences6.getString("Phone", null);
fasbs=findViewById(R.id.fab);
info=findViewById(R.id.info);
info.setText("No Results ");
info.setVisibility(View.VISIBLE);
Log.e("main", "error "+number);
TestRef = FirebaseDatabase.getInstance().getReference().child("Test_Data").child(number);
recyclerView = findViewById(R.id.recycler_view);
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
fasbs.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(NegativeResults.this, TemplateActivity.class);
startActivity(intent);
}
});
LinearLayoutManager layoutManager1=new LinearLayoutManager(this);
recyclerView.setLayoutManager(new GridLayoutManager(this, 1));
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels / 8;
int spaceInPixel = 4;
recyclerView.addItemDecoration(new SpaceDecoration(spaceInPixel));
}
@Override
protected void onStart()
{
super.onStart();
FirebaseRecyclerOptions<Tests> options =
new FirebaseRecyclerOptions.Builder<Tests>()
.setQuery(TestRef.orderByChild("Internal").equalTo("No"), Tests.class)
.build();
FirebaseRecyclerAdapter<Tests, TestViewHolder> adapter =
new FirebaseRecyclerAdapter<Tests, TestViewHolder>(options) {
@Override
protected void onBindViewHolder(@NonNull TestViewHolder holder, int position, @NonNull final Tests model)
{
// holder.txtProductName.setText(model.getPatientid());
if(model.getInternal().contains("Yes") || model.getInternal().contains("No"))
{
info.setVisibility(View.INVISIBLE);
}
holder.txtpatientid.setText("User Name :"+model.getSample_volume());
holder.txtsampletype.setText("Test Id :" +model.getTest_Id());
holder.nikshay.setText("Volume :"+model.getSample_volume());
holder.txttimestamp.setText(model.getSample_Date());
//holder.txtProductDescription.setText(model.getSample());
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(NegativeResults.this, ViewSamples.class);
intent.putExtra("pid",model.getTest_Id());
startActivity(intent);
}
});
}
@NonNull
@Override
public TestViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
TestViewHolder holder = new TestViewHolder(view);
return holder;
}
};
recyclerView.setAdapter(adapter);
adapter.startListening();
}
private void firebasesearch(String data)
{
{
Query firebaseSearchQuery = TestRef.orderByChild("Test_Id").startAt(data).endAt(data + "\uf8ff") ;
FirebaseRecyclerOptions<Tests> options =
new FirebaseRecyclerOptions.Builder<Tests>()
.setQuery(firebaseSearchQuery, Tests.class)
.build();
FirebaseRecyclerAdapter<Tests, TestViewHolder> adapter =
new FirebaseRecyclerAdapter<Tests, TestViewHolder>(options) {
@Override
protected void onBindViewHolder(@NonNull final TestViewHolder holder, int position, @NonNull final Tests model)
{
holder.txtpatientid.setText("User Name :"+model.getSample_volume());
holder.txtsampletype.setText("Test Id :" +model.getTest_Id());
holder.nikshay.setText("Volume :"+model.getSample_volume());
holder.txttimestamp.setText(model.getSample_Date());
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(NegativeResults.this, ViewSamples.class);
intent.putExtra("pid",model.getTest_Id());
startActivity(intent);
Log.e("main", "TestID"+model.getTest_Id());
}
});
}
@NonNull
@Override
public TestViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
TestViewHolder holder = new TestViewHolder(view);
return holder;
}
};
recyclerView.setAdapter(adapter);
adapter.startListening();
}
}
}

View File

@@ -0,0 +1,203 @@
package no.Reader.android.iisc.Reader;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
import no.Reader.android.iisc.R;
import no.Reader.android.iisc.Reader.Model.Tests;
public class PositiveResult extends NavigationTop {
private DatabaseReference TestRef;
private RecyclerView recyclerView ;
FloatingActionButton fasbs;
private TextView info;
String number;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater inflater = (LayoutInflater) this
.getSystemService(LAYOUT_INFLATER_SERVICE);
View contentView = inflater.inflate(R.layout.activity_main, null, false);
draw.addView(contentView, 0);
info=findViewById(R.id.info);
SharedPreferences preferences6 = getSharedPreferences("PhoneBook_number", MODE_PRIVATE);
info.setText("No Results ");
info.setVisibility(View.VISIBLE);
number = preferences6.getString("Phone", null);
fasbs=findViewById(R.id.fab);
Log.e("main", "error "+number);
TestRef = FirebaseDatabase.getInstance().getReference().child("Test_Data").child(number);
recyclerView = findViewById(R.id.recycler_view);
fasbs.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(PositiveResult.this, TestDetails.class);
startActivity(intent);
}
});
LinearLayoutManager layoutManager1=new LinearLayoutManager(this);
/* layoutManager1.setOrientation(LinearLayoutManager.HORIZONTAL);
cA
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
*/ // recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new GridLayoutManager(this, 1));
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels / 8;
int spaceInPixel = 4;
recyclerView.addItemDecoration(new SpaceDecoration(spaceInPixel));
}
@Override
protected void onStart()
{
super.onStart();
FirebaseRecyclerOptions<Tests> options =
new FirebaseRecyclerOptions.Builder<Tests>()
.setQuery(TestRef.orderByChild("Internal").equalTo("Yes"), Tests.class)
.build();
FirebaseRecyclerAdapter<Tests, TestViewHolder> adapter =
new FirebaseRecyclerAdapter<Tests, TestViewHolder>(options) {
@Override
protected void onBindViewHolder(@NonNull TestViewHolder holder, int position, @NonNull final Tests model)
{
if(model.getInternal().contains("Yes") || model.getInternal().contains("No"))
{
info.setVisibility(View.INVISIBLE);
}
// holder.txtProductName.setText(model.getPatientid());
holder.iconfinder.setBackgroundResource(R.drawable.green_circle);
holder.iconfinder.setText("I");
holder.txtpatientid.setText("User Name :"+model.getSample_volume());
holder.txtsampletype.setText("Test Id :" +model.getTest_Id());
holder.nikshay.setText("Volume :"+model.getSample_volume());
holder.txttimestamp.setText(model.getSample_Date());
//holder.txtProductDescription.setText(model.getSample());
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(PositiveResult.this, ViewSamples.class);
Log.e("main", "TestID"+model.getTest_Id());
intent.putExtra("pid",model.getTest_Id());
startActivity(intent);
}
});
}
@NonNull
@Override
public TestViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
TestViewHolder holder = new TestViewHolder(view);
return holder;
}
};
recyclerView.setAdapter(adapter);
adapter.startListening();
}
private void firebasesearch(String data)
{
{
Query firebaseSearchQuery = TestRef.orderByChild("Patient_Id").startAt(data).endAt(data + "\uf8ff") ;
FirebaseRecyclerOptions<Tests> options =
new FirebaseRecyclerOptions.Builder<Tests>()
.setQuery(firebaseSearchQuery, Tests.class)
.build();
FirebaseRecyclerAdapter<Tests, TestViewHolder> adapter =
new FirebaseRecyclerAdapter<Tests, TestViewHolder>(options) {
@Override
protected void onBindViewHolder(@NonNull final TestViewHolder holder, int position, @NonNull final Tests model)
{
holder.txtpatientid.setText("User Name :"+model.getSample_volume());
holder.txtsampletype.setText("Test Id :" +model.getTest_Id());
holder.nikshay.setText("Volume :"+model.getSample_volume());
holder.txttimestamp.setText(model.getSample_Date());
holder.iconfinder.setBackgroundResource(R.drawable.green_circle);
holder.iconfinder.setText("I");
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(PositiveResult.this, ViewSamples.class);
intent.putExtra("pid",model.getTest_Id());
startActivity(intent);
}
});
}
@NonNull
@Override
public TestViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
TestViewHolder holder = new TestViewHolder(view);
return holder;
}
};
recyclerView.setAdapter(adapter);
adapter.startListening();
}
}
}

View File

@@ -0,0 +1,54 @@
nRF Toolbox demonstrates how to implement the Bluetooth Smart features in an Android application.
It consists of number of profiles, like Heart Rate, Blood Pressure etc. that may be use as is to communicate with real devices.
They use the Bluetooth SIG adopted profiles, that may be found here: https://developer.bluetooth.org/gatt/profiles/Pages/ProfilesHome.aspx
The Template Profile has been created to give a quick start with implementing proprietary services. Just start modifying 4 classes inside
the template package to implement features you need.
Below you will find a short step-by-step tutorial:
1. The template consists of the following files:
- TemplateActivity - the main class that is responsible for managing the view of your profile
- TemplateService - the service that is started whenever you connect to a device. I handles the Bluetooth Smart communication using the...
- TemplateManager - the manager that handles all the BLE logic required to communicate with the device. The TemplateManager derives from
the BleManager which handles most of the event itself and propagates the data-relevant to deriving class. You don't
have to, or even shouldn't modify the BleManager (unless you want to change the default behaviour).
- TemplateManagerCallbacks - the interface with a list of callbacks that the TemplateManager can call. Each method is usually related to one
BLE event, e.g. receiving a new value of the characteristic.\
- TemplateParser - an optional class in the .parser package that is responsible for converting the characteristic value to String.
This is used only for debugging. The String returned by the parse(..) method is then logged into the nRF Logger application
(if such installed).
- /settings/SettingsActivity and /settings/SettingsFragment - classes used to present user preferences. A stub implementation in the template.
- /res/layout/activity_feature_template.xml - the layout file for the TemplateActivity
- /res/values/strings_template.xml - a set of strings used in the layout file
- /res/xml/settings/template.xml - the user settings configuration
- /res/drawable/(x)hdpi/ic_template_feature.png - the template profile icon (HDPI, XHDPI). Please, keep the files size.
- /res/drawable/(x)hdpi/ic_stat_notify_template - the icon that is used in the notification
2. The communication between the components goes as follows:
- User clicks the CONNECT button and selects a target device on TemplateActivity.
- The base class of the TemplateActivity starts the service given by getServiceClass() method.
- The service starts and initializes the TemplateManager. TemplateActivity binds to the service and is being given the TemplateBinder object (the service API) as a result.
- The manager connects to the device using Bluetooth Smart and discovers its services.
- The manager initializes the device. Initialization is done using the list of actions given by the initGatt(..) method in the TemplateManager.
Initialization usually contains enabling notifications, writing some initial values etc.
- When initialization is complete the manager calls the onDeviceReady() callback.
- The service sends the BROADCAST_DEVICE_READY broadcast to the activity. Communication from the Service to the Activity is always done using the LocalBroadcastManager broadcasts.
- The base class of the TemplateActivity listens to the broadcasts and calls appropriate methods.
- When a custom event occurs, for example a notification is received, the manager parses the incoming data and calls the proper callback.
- The callback implementation in the TemplateService sends a broadcast message with values given in parameters.
- The TemplateActivity, which had registered a broadcast receiver before, listens to the broadcasts, reads the values and present them to users.
- Communication Activity->Service is done using the API in the TemplateBinder. You may find the example of how to use it in the ProximityActivity.
3. Please read the files listed above and the TODO messages for more information what to modify in the files.
4. Remember to add your activities and the service in the AndroidManifest.xml file. The nRF Toolbox lists all activities with the following intent filter:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="no.Reader.android.iisc.LAUNCHER" />
</intent-filter>
5. Feel free to rename the nRF Toolbox application (/res/values/strings.xml ->app_name), change the toolbar colors (/res/values/color.xml -> actionBarColor, actionBarColorDark).
In order to remove unused profiles from the main FeaturesActivity just comment out their intent-filter tags in the AndroidManifest.xml file.

View File

@@ -0,0 +1,200 @@
package no.Reader.android.iisc.Reader;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.util.Log;
import android.util.Patterns;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
import com.google.firebase.database.ValueEventListener;
import com.hbb20.CountryCodePicker;
import no.Reader.android.iisc.R;
import no.Reader.android.iisc.Reader.VerifyOTP.VerifyOtp;
public class Register extends AppCompatActivity {
String numberwithcode;
private Button next;
private EditText editTextMobile;
private ProgressDialog loadingBar;
private TextView login;
CountryCodePicker ccp;
String mobile,name;
private EditText editTextname;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
next=findViewById(R.id.buttonContinue);
editTextMobile = findViewById(R.id.editTextMobile);
ccp=findViewById(R.id.ccp);
ccp.registerCarrierNumberEditText(editTextMobile);
loadingBar = new ProgressDialog(this);
login=findViewById(R.id.login_account);
login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Register.this, LoginScreen.class);
startActivity(intent);
}
});
editTextname=findViewById(R.id.editTextName);
next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mobile = editTextMobile.getText().toString().trim();
mobile = mobile.replaceAll("[^0-9]", "");
name = editTextname.getText().toString().trim();
if (!isOnline()) {
//Create an alertdialog
AlertDialog.Builder Checkbuilder = new AlertDialog.Builder(Register.this);
Checkbuilder.setTitle("No Internet Connection !");
Checkbuilder.setMessage("Check Your Internet Connection.");
Checkbuilder.setPositiveButton("Retry", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
Checkbuilder.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
AlertDialog alert = Checkbuilder.create();
alert.show();
}
else {
if (mobile.equals("") || name.equals("")) {
Toast.makeText(Register.this, "please enter all the required fields", Toast.LENGTH_SHORT).show();
} else if (!Patterns.PHONE.matcher(mobile).matches()) {
editTextMobile.setError("Enter a valid Phone ");
// Toast.makeText(Consumer_register.this, "Please Enter a valid email", Toast.LENGTH_SHORT).show();
}
else if (mobile.length() <9 ) {
Toast.makeText(Register.this, "Enter a valid Phone", Toast.LENGTH_SHORT).show();
// Toast.makeText(Consumer_register.this, "Please Enter a valid email", Toast.LENGTH_SHORT).show();
}
else if (mobile.length() >=11 ) {
Toast.makeText(Register.this, "Enter a valid Phone", Toast.LENGTH_SHORT).show();
// Toast.makeText(Consumer_register.this, "Please Enter a valid email", Toast.LENGTH_SHORT).show();
}else {
Query chekuser = FirebaseDatabase.getInstance().getReference("USERS").orderByChild("number").equalTo(mobile);
chekuser.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
Toast.makeText(Register.this, "User Already Exist", Toast.LENGTH_SHORT).show();
// editTextMobile.setError("User Already Exist");
} else {
Intent intent = new Intent(Register.this, VerifyOtp.class);
Log.e("main", "error " + mobile);
numberwithcode = ccp.getFullNumberWithPlus();
Log.e("main", "error " + numberwithcode);
if (mobile.equals("") || name.equals("")) {
Toast.makeText(Register.this, "please enter all the required fields", Toast.LENGTH_SHORT).show();
} else if (!Patterns.PHONE.matcher(mobile).matches()) {
editTextMobile.setError("Enter a valid Phone ");
// Toast.makeText(Consumer_register.this, "Please Enter a valid email", Toast.LENGTH_SHORT).show();
} else {
loadingBar.setTitle("Create Account");
loadingBar.setMessage("Please wait ");
loadingBar.setCanceledOnTouchOutside(false);
loadingBar.show();
intent.putExtra("numberwithcode", numberwithcode);
intent.putExtra("mobile", mobile);
intent.putExtra("username", name);
startActivity(intent);
}
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
Log.e("Raman", "Received an exception check chexk " + databaseError.getMessage());
// Toast.makeText(ForgetPassword.this,databaseError.getMessage(),Toast.LENGTH_SHORT).show();
}
});
}
}
}
});
}
@Override
public void onBackPressed() {
Intent intent = new Intent(Register.this, LoginScreen.class);
startActivity(intent);
}
public boolean isOnline() {
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnected());
}
}

View File

@@ -0,0 +1,17 @@
package no.Reader.android.iisc.Reader;
import no.Reader.android.iisc.Reader.callback.SPCACharacteristicCallback;
import no.Reader.android.iisc.battery.BatteryManagerCallbacks;
/**
* Interface {@link SPCAManagerCallbacks} must be implemented by {@link SPCAService}
* in order to receive callbacks from {@link TemplateManager}
*/
interface SPCAManagerCallbacks extends BatteryManagerCallbacks, SPCACharacteristicCallback {
// Callbacks are called when a data has been received/written to a remote device.
// This is the way how the manager notifies the activity about this event.
// TODO add more callbacks.
// If you need, create more ...Callback interfaces and extend this interface with them.
}

View File

@@ -0,0 +1,204 @@
package no.Reader.android.iisc.Reader;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import no.nordicsemi.android.log.Logger;
import no.Reader.android.iisc.FeaturesActivity;
import no.Reader.android.iisc.R;
import no.Reader.android.iisc.NotificationData;
import no.Reader.android.iisc.profile.BleProfileService;
import no.Reader.android.iisc.profile.LoggableBleManager;
public class SPCAService extends BleProfileService implements SPCAManagerCallbacks {
public static final String BROADCAST_TEMPLATE_MEASUREMENT = "no.Reader.android.iisc.template.BROADCAST_MEASUREMENT";
public static final String EXTRA_DATA = "no.Reader.android.iisc.template.EXTRA_DATA";
public static final String BROADCAST_BATTERY_LEVEL = "no.Reader.android.iisc.BROADCAST_BATTERY_LEVEL";
public static final String EXTRA_BATTERY_LEVEL = "no.Reader.android.iisc.EXTRA_BATTERY_LEVEL";
private final static String ACTION_DISCONNECT = "no.Reader.android.iisc.template.ACTION_DISCONNECT";
private final static int NOTIFICATION_ID = 864;
private final static int OPEN_ACTIVITY_REQ = 0;
private final static int DISCONNECT_REQ = 1;
private TemplateManager mManager;
private final LocalBinder mBinder = new TemplateBinder();
/**
* This local binder is an interface for the bound activity to operate with the sensor.
*/
class TemplateBinder extends LocalBinder {
// TODO Define service API that may be used by a bound Activity
/**
* Sends some important data to the device.
*
* @param parameter some parameter.
*/
public void heatingSwitch(int state){
mManager.heatingSwitch(state);
}
public void sendDTemp(int d_temp) {
mManager.sendDTemp(d_temp);
}
public void sendATemp(int a_temp) {
mManager.sendATemp(a_temp);
}
public void sendETemp(int e_temp) {
mManager.sendETemp(e_temp);
}
public void sendLTemp(int l_temp) {
mManager.sendLTemp(l_temp);
}
public void sendOTemp(int o_temp) {
mManager.sendOTemp(o_temp);
}
public void sendDTime(int d_time) {
mManager.sendDTime(d_time);
}
public void sendATime(int a_time) {
mManager.sendATime(a_time);
}
public void sendETime(int e_time) {
mManager.sendETime(e_time);
}
public void sendLTime(int l_time) {
mManager.sendLTime(l_time);
}
public void sendOTime(int o_time) { mManager.sendOTime(o_time); }
public void sendNPcrN(int n_pcr_c) {
mManager.sendNPcrC(n_pcr_c);
}
}
@Override
protected LocalBinder getBinder() {
return mBinder;
}
@Override
protected LoggableBleManager<SPCAManagerCallbacks> initializeManager() {
return mManager = new TemplateManager(this);
}
@Override
public void onCreate() {
super.onCreate();
final IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_DISCONNECT);
registerReceiver(mDisconnectActionBroadcastReceiver, filter);
}
@Override
public void onDestroy() {
// when user has disconnected from the sensor, we have to cancel the notification that we've created some milliseconds before using unbindService
cancelNotification();
unregisterReceiver(mDisconnectActionBroadcastReceiver);
super.onDestroy();
}
@Override
protected void onRebind() {
// when the activity rebinds to the service, remove the notification
cancelNotification();
}
@Override
protected void onUnbind() {
// when the activity closes we need to show the notification that user is connected to the sensor
createNotification(R.string.template_notification_connected_message, 0);
}
@Override
public void onSampleValueReceived(@NonNull final BluetoothDevice device, final int value) {
final Intent broadcast = new Intent(BROADCAST_TEMPLATE_MEASUREMENT);
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
broadcast.putExtra(EXTRA_DATA, value);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
if (!mBound) {
// Here we may update the notification to display the current value.
// TODO modify the notification here
}
}
@Override
public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int batteryLevel) {
}
/**
* Creates the notification.
*
* @param messageResId message resource id. The message must have one String parameter,<br />
* f.e. <code>&lt;string name="name"&gt;%s is connected&lt;/string&gt;</code>
* @param defaults signals that will be used to notify the user
*/
private void createNotification(final int messageResId, final int defaults) {
final Intent parentIntent = new Intent(this, FeaturesActivity.class);
parentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
final Intent targetIntent = new Intent(this, TemplateActivity.class);
final Intent disconnect = new Intent(ACTION_DISCONNECT);
final PendingIntent disconnectAction = PendingIntent.getBroadcast(this, DISCONNECT_REQ, disconnect, PendingIntent.FLAG_UPDATE_CURRENT);
// both activities above have launchMode="singleTask" in the AndroidManifest.xml file, so if the task is already running, it will be resumed
final PendingIntent pendingIntent = PendingIntent.getActivities(this, OPEN_ACTIVITY_REQ, new Intent[]{parentIntent, targetIntent}, PendingIntent.FLAG_UPDATE_CURRENT);
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NotificationData.CONNECTED_DEVICE_CHANNEL);
builder.setContentIntent(pendingIntent);
builder.setContentTitle(getString(R.string.app_name)).setContentText(getString(messageResId, getDeviceName()));
builder.setSmallIcon(R.drawable.ic_stat_notify_template);
builder.setShowWhen(defaults != 0).setDefaults(defaults).setAutoCancel(true).setOngoing(true);
builder.addAction(new NotificationCompat.Action(R.drawable.ic_action_bluetooth, getString(R.string.template_notification_action_disconnect), disconnectAction));
final Notification notification = builder.build();
final NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(NOTIFICATION_ID, notification);
}
/**
* Cancels the existing notification. If there is no active notification this method does nothing
*/
private void cancelNotification() {
final NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
nm.cancel(NOTIFICATION_ID);
}
/**
* This broadcast receiver listens for {@link #ACTION_DISCONNECT} that may be fired by pressing Disconnect action button on the notification.
*/
private final BroadcastReceiver mDisconnectActionBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
Logger.i(getLogSession(), "[Notification] Disconnect action pressed");
if (isConnected())
getBinder().disconnect();
else
stopSelf();
}
};
}

View File

@@ -0,0 +1,20 @@
package no.Reader.android.iisc.Reader;
import android.graphics.Rect;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class SpaceDecoration extends RecyclerView.ItemDecoration {
private int space;
public SpaceDecoration(int space) {
this.space = space;
}
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
outRect.left=outRect.bottom=outRect.right=outRect.top=space;
}
}

View File

@@ -0,0 +1,527 @@
package no.Reader.android.iisc.Reader;
import android.app.AlertDialog;
import android.app.Dialog;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import java.util.UUID;
import no.Reader.android.iisc.R;
import no.Reader.android.iisc.profile.BleProfileService;
import no.Reader.android.iisc.profile.BleProfileServiceReadyActivity;
/**
* Modify the Template Activity to match your needs.
*/
public class TemplateActivity extends BleProfileServiceReadyActivity<SPCAService.TemplateBinder> {
@SuppressWarnings("unused")
private final String TAG = "TemplateActivity";
// TODO change view references to match your need
private TextView mValueView;
private TextView mHeatingStatusView;
private Switch mHeatingState ;
int p ,q,r;
int count =0;
int love=0;
int love1=0;
int love2=0;
int love3=0;
private TextView mClockView;
int act1_1=0;
int act1_2=0;
int act1_3=0;
private Button d,connect;
/*private EditText mDTimeValueView;
private Integer mDSetTime ;
private EditText mLTimeValueView;
private Integer mLSetTime ;
private EditText mOTimeValueView;
private Integer mOSetTime ;
private TextView mClockView;
private EditText mATimeValueView;
private Integer mASetTime ;
private EditText mETimeValueView;
private Integer mESetTime ;
private EditText mDTempValueView;
private Integer mDSetTemp ;
private EditText mATempValueView;
private Integer mASetTemp ;
private EditText mETempValueView;
private Integer mESetTemp ;
private EditText mLTempValueView;
private Integer mLSetTemp ;
private EditText mOTempValueView;
private Integer mOSetTemp ;
private EditText mNPcrCView;
private Integer mNPcrC ;
*/
@Override
protected void onCreateView(final Bundle savedInstanceState) {
// TODO modify the layout file(s). By default the activity shows only one field - the Heart Rate value as a sample
setContentView(R.layout.activity_feature_template);
BottomNavigationView bottomNav = findViewById(R.id.bottom_navigation);
bottomNav.setOnNavigationItemSelectedListener(navListener);
setGUI();
connect=findViewById(R.id.action_connect);
d.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SharedPreferences preferences = getSharedPreferences("PhoneBook_adc1", MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
// editor.putString(Name, phonenum);
mHeatingState.setChecked(false);
editor.putString("act1_1", String.valueOf(act1_1));
editor.putString("act1_2", String.valueOf(act1_2));
editor.putString("act1_3", String.valueOf(act1_3));
Log.d("Addact11", String.valueOf(act1_1));
Log.d("Addact12", String.valueOf(act1_2));
Log.d("Addact13", String.valueOf(act1_3));
editor.commit();
Intent intent = new Intent(TemplateActivity.this, TemplateActivity1.class);
startActivity(intent);
}
});
}
private void setGUI() {
// mClockView=findViewById(R.id.RemTime_Value);
// TODO assign your views to fields
mValueView = findViewById(R.id.Temp_Value);
d=findViewById(R.id.next);
/*mDTempValueView = findViewById(R.id.D_Temp_Set);
mDTimeValueView = findViewById(R.id.D_Time_Set);
mATempValueView = findViewById(R.id.A_Temp_Set);
mATimeValueView = findViewById(R.id.A_Time_Set);
mETempValueView = findViewById(R.id.E_Temp_Set);
mETimeValueView = findViewById(R.id.E_Time_Set);
mLTempValueView=findViewById(R.id.L_Temp_Set);
mOTempValueView=findViewById(R.id.O_Temp_Set);
mLTimeValueView = findViewById(R.id.L_Time_Set);
mOTimeValueView = findViewById(R.id.O_Time_Set);
*/
/*
mNPcrCView = findViewById(R.id.N_Pcr_C);
*/
mHeatingState = findViewById(R.id.heating_state);
mHeatingStatusView= findViewById(R.id.heating_status_text);
mHeatingState.setOnCheckedChangeListener((buttonView, isChecked) -> {
if(connect.getText().equals("CONNECT"))
{
Toast.makeText(TemplateActivity.this, "Please connect to device", Toast.LENGTH_SHORT).show();
}
else {
if (isChecked) {
getService().heatingSwitch(1);
/* mDSetTemp = Integer.parseInt(mDTempValueView.getText().toString());
getService().sendDTemp(mDSetTemp);
mDSetTime = Integer.parseInt(mDTimeValueView.getText().toString());
getService().sendDTime(mDSetTime);
mLSetTemp = Integer.parseInt(mLTempValueView.getText().toString());
getService().sendLTemp(mLSetTemp);
mLSetTime = Integer.parseInt(mLTimeValueView.getText().toString());
getService().sendLTime(mLSetTime);
mOSetTemp = Integer.parseInt(mOTempValueView.getText().toString());
getService().sendOTemp(mOSetTemp);
mOSetTime = Integer.parseInt(mOTimeValueView.getText().toString());
getService().sendOTime(mOSetTime);
// Log.d("Add", String.valueOf(m));
mASetTemp = Integer.parseInt(mATempValueView.getText().toString());
getService().sendATemp(mASetTemp);
mASetTime = Integer.parseInt(mATimeValueView.getText().toString());
getService().sendATime(mASetTime);
mESetTemp = Integer.parseInt(mETempValueView.getText().toString());
getService().sendETemp(mESetTemp);
mESetTime = Integer.parseInt(mETimeValueView.getText().toString());
getService().sendETime(mESetTime);
mNPcrC = Integer.parseInt(mNPcrCView.getText().toString());
getService().sendNPcrN(mNPcrC);
*/
} else {
getService().heatingSwitch(0);
}
mHeatingStatusView.setText(isChecked ? R.string.Heating_block_on : R.string.Heating_block_off);
}
});
/*findViewById(R.id.time_set_button).setOnClickListener(v -> {
if (isDeviceConnected()) {
mSetTime = Integer.parseInt(mTimeValueView.getText().toString());
getService().sendTimeDuration(mSetTime);
}
});
findViewById(R.id.temp_set_button).setOnClickListener(v -> {
if (isDeviceConnected()) {
mSetTemp = Integer.parseInt(mTempValueView.getText().toString());
getService().sendTemp(mSetTemp);
}
});*/
}
@Override
protected void onInitialize(final Bundle savedInstanceState) {
LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, makeIntentFilter());
}
@Override
protected void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
}
@Override
protected void setDefaultUI() {
// TODO clear your UI
mValueView.setText(R.string.not_available_value);
}
@Override
protected int getLoggerProfileTitle() {
return R.string.template_feature_title;
}
/*@Override
protected void getAboutTextId() {
Intent intent =new Intent (TemplateActivity.this,About.class);
startActivity(intent);
}
*/
/*@Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
@Override
protected boolean onOptionsItemSelected(final int itemId) {
switch (itemId) {
case R.id.action_about:
Intent intent =new Intent (TemplateActivity.this,About.class);
startActivity(intent);
break;
*//*case R.id.action_settings:
final Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
break;*//*
}
return true;
}
*/
@Override
protected int getDefaultDeviceName() {
return R.string.template_default_name;
}
@Override
protected UUID getFilterUUID() {
// TODO this method may return the UUID of the service that is required to be in the advertisement packet of a device in order to be listed on the Scanner dialog.
// If null is returned no filtering is done.
return TemplateManager.SERVICE_UUID;
}
@Override
protected Class<? extends BleProfileService> getServiceClass() {
return SPCAService.class;
}
@Override
protected void onServiceBound(final SPCAService.TemplateBinder binder) {
// not used
}
@Override
protected void onServiceUnbound() {
// not used
}
@Override
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
// this may notify user or show some views
}
@Override
public void onDeviceDisconnected(final BluetoothDevice device) {
super.onDeviceDisconnected(device);
}
// Handling updates from the device
@SuppressWarnings("unused")
private void setValueOnView(@NonNull final BluetoothDevice device, final int value) {
// TODO assign the value to a view
mValueView.setText(String.valueOf(value));
if(mHeatingState.isChecked())
{
d.postDelayed(new Runnable() {
public void run() {
d.setEnabled(true);
Log.d(TAG, "resend1");
}
}, 7000);
d.postDelayed(new Runnable() {
public void run() {
act1_1=value;
mValueView.setText(String.valueOf(act1_1));
Log.d(TAG, "resend1");
}
}, 5000);
d.postDelayed(new Runnable() {
public void run() {
act1_2=value;
mValueView.setText(String.valueOf(act1_2));
Log.d(TAG, "resend1");
}
}, 6000);
d.postDelayed(new Runnable() {
public void run() {
act1_3=value;
mValueView.setText(String.valueOf(act1_3));
Log.d(TAG, "resend1");
}
}, 7000);
}
/*else if (!mHeatingState.isChecked() && count ==1) {
love=1;
count=2;
Log.d("check1", String.valueOf(love));
mValueView.setText("_");
Log.d("love", String.valueOf(love));
Log.d("love", String.valueOf(p));
}
else if ( mHeatingState.isChecked() && love ==1 )
{
q=value;
final int d=value;
Log.d("Addq", String.valueOf(q));
mValueView.setText(String.valueOf(d));
love1=1;
}
else if(!mHeatingState.isChecked() && love1 ==1)
{
love3=1;
mValueView.setText("_");
Log.d("check1", String.valueOf(love));
}
else if(mHeatingState.isChecked() && love3 ==1)
{
r=value;
mValueView.setText(String.valueOf(value));
Log.d("Addr", String.valueOf(r));
}
*/
else
{
mValueView.setText("_");
}
}
@SuppressWarnings("unused")
public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int value) {
}
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
final String action = intent.getAction();
final BluetoothDevice device = intent.getParcelableExtra(SPCAService.EXTRA_DEVICE);
if (SPCAService.BROADCAST_TEMPLATE_MEASUREMENT.equals(action)) {
final int value = intent.getIntExtra(SPCAService.EXTRA_DATA, 0);
// Update GUI
setValueOnView(device, value);
} else if (SPCAService.BROADCAST_BATTERY_LEVEL.equals(action)) {
final int batteryLevel = intent.getIntExtra(SPCAService.EXTRA_BATTERY_LEVEL, 0);
// Update GUI
onBatteryLevelChanged(device, batteryLevel);
}
}
};
private static IntentFilter makeIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(SPCAService.BROADCAST_TEMPLATE_MEASUREMENT);
intentFilter.addAction(SPCAService.BROADCAST_BATTERY_LEVEL);
return intentFilter;
}
private BottomNavigationView.OnNavigationItemSelectedListener navListener =
new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_home:
Intent intent = new Intent(TemplateActivity.this, MainActivity.class);
startActivity(intent);
break;
case R.id.nav_addtest:
Intent intent2 = new Intent(TemplateActivity.this, TestDetails.class);
startActivity(intent2);
break;
case R.id.nav_add_sample:
Intent intent3 = new Intent(TemplateActivity.this, TemplateActivity2.class);
startActivity(intent3);
break;
}
return true;
}
};
@Override
public void onBackPressed() {
//super.onBackPressed();
IsFinish("Want to exit Test ?");
}
public void IsFinish(String alertmessage) {
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
Intent intent = new Intent(TemplateActivity.this, TestDetails.class);
startActivity(intent); // This above line close correctly
//finish();
break;
case DialogInterface.BUTTON_NEGATIVE:
break;
}
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(alertmessage)
.setPositiveButton("Yes", dialogClickListener)
.setNegativeButton("No", dialogClickListener).show();
AlertDialog alertDialog = builder.create();
alertDialog.show();
alertDialog.getButton(Dialog.BUTTON_NEGATIVE).setTextColor(Color.BLACK);
alertDialog.getButton(Dialog.BUTTON_POSITIVE).setTextColor(Color.BLACK);
alertDialog.getButton(Dialog.BUTTON_NEGATIVE).
setBackgroundColor(Color.TRANSPARENT);
alertDialog.getButton(Dialog.BUTTON_POSITIVE).
setBackgroundColor(Color.TRANSPARENT);
}
}

View File

@@ -0,0 +1,528 @@
package no.Reader.android.iisc.Reader;
import android.Manifest;
import android.app.AlertDialog;
import android.app.Dialog;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import java.util.UUID;
import no.Reader.android.iisc.R;
import no.Reader.android.iisc.profile.BleProfileService;
import no.Reader.android.iisc.profile.BleProfileServiceReadyActivity;
/**
* Modify the Template Activity to match your needs.
*/
public class TemplateActivity1 extends BleProfileServiceReadyActivity<SPCAService.TemplateBinder> {
@SuppressWarnings("unused")
private final String TAG = "TemplateActivity";
// TODO change view references to match your need
private TextView mValueView;
private TextView mHeatingStatusView;
private Switch mHeatingState ;
int p ,q,r;
int count =0;
int love=0;
int love1=0;
int act2_1=0;
int act2_2=0;
int act2_3=0;
int love2=0;
int love3=0;
private TextView mClockView;
int act2=0;
private Button d,connect;
/*private EditText mDTimeValueView;
private Integer mDSetTime ;
private EditText mLTimeValueView;
private Integer mLSetTime ;
private EditText mOTimeValueView;
private Integer mOSetTime ;
private TextView mClockView;
private EditText mATimeValueView;
private Integer mASetTime ;
private EditText mETimeValueView;
private Integer mESetTime ;
private EditText mDTempValueView;
private Integer mDSetTemp ;
private EditText mATempValueView;
private Integer mASetTemp ;
private EditText mETempValueView;
private Integer mESetTemp ;
private EditText mLTempValueView;
private Integer mLSetTemp ;
private EditText mOTempValueView;
private Integer mOSetTemp ;
private EditText mNPcrCView;
private Integer mNPcrC ;
*/
@Override
protected void onCreateView(final Bundle savedInstanceState) {
// TODO modify the layout file(s). By default the activity shows only one field - the Heart Rate value as a sample
setContentView(R.layout.activity_feature_template1);
BottomNavigationView bottomNav = findViewById(R.id.bottom_navigation);
bottomNav.setOnNavigationItemSelectedListener(navListener);
setGUI();
connect=findViewById(R.id.action_connect);
d.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(ContextCompat.checkSelfPermission(TemplateActivity1.this, Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(TemplateActivity1.this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},23);
}
SharedPreferences preferences = getSharedPreferences("PhoneBook_adc2", MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
// editor.putString(Name, phonenum);
editor.putString("act2_1", String.valueOf(act2_1));
editor.putString("act2_2", String.valueOf(act2_2));
editor.putString("act2_3", String.valueOf(act2_3));
Log.d("Addact21", String.valueOf(act2_1));
Log.d("Addact22", String.valueOf(act2_2));
Log.d("Addact23", String.valueOf(act2_3));
editor.commit();
mHeatingState.setChecked(false);
Intent intent = new Intent(TemplateActivity1.this, TemplateActivity2.class);
startActivity(intent);
}
});
}
private BottomNavigationView.OnNavigationItemSelectedListener navListener =
new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_home:
Intent intent = new Intent(TemplateActivity1.this, MainActivity.class);
startActivity(intent);
break;
case R.id.nav_addtest:
Intent intent2 = new Intent(TemplateActivity1.this, TestDetails.class);
startActivity(intent2);
break;
case R.id.nav_add_sample:
Intent intent3 = new Intent(TemplateActivity1.this, TemplateActivity2.class);
startActivity(intent3);
break;
}
return true;
}
};
private void setGUI() {
// mClockView=findViewById(R.id.RemTime_Value);
// TODO assign your views to fields
mValueView = findViewById(R.id.Temp_Value);
d=findViewById(R.id.next);
/*mDTempValueView = findViewById(R.id.D_Temp_Set);
mDTimeValueView = findViewById(R.id.D_Time_Set);
mATempValueView = findViewById(R.id.A_Temp_Set);
mATimeValueView = findViewById(R.id.A_Time_Set);
mETempValueView = findViewById(R.id.E_Temp_Set);
mETimeValueView = findViewById(R.id.E_Time_Set);
mLTempValueView=findViewById(R.id.L_Temp_Set);
mOTempValueView=findViewById(R.id.O_Temp_Set);
mLTimeValueView = findViewById(R.id.L_Time_Set);
mOTimeValueView = findViewById(R.id.O_Time_Set);
*/
/*
mNPcrCView = findViewById(R.id.N_Pcr_C);
*/
mHeatingState = findViewById(R.id.heating_state);
mHeatingStatusView= findViewById(R.id.heating_status_text);
mHeatingState.setOnCheckedChangeListener((buttonView, isChecked) -> {
if(connect.getText().equals("CONNECT"))
{
Toast.makeText(TemplateActivity1.this, "Please connect to device", Toast.LENGTH_SHORT).show();
}
else {
if (isChecked) {
getService().heatingSwitch(1);
/* mDSetTemp = Integer.parseInt(mDTempValueView.getText().toString());
getService().sendDTemp(mDSetTemp);
mDSetTime = Integer.parseInt(mDTimeValueView.getText().toString());
getService().sendDTime(mDSetTime);
mLSetTemp = Integer.parseInt(mLTempValueView.getText().toString());
getService().sendLTemp(mLSetTemp);
mLSetTime = Integer.parseInt(mLTimeValueView.getText().toString());
getService().sendLTime(mLSetTime);
mOSetTemp = Integer.parseInt(mOTempValueView.getText().toString());
getService().sendOTemp(mOSetTemp);
mOSetTime = Integer.parseInt(mOTimeValueView.getText().toString());
getService().sendOTime(mOSetTime);
// Log.d("Add", String.valueOf(m));
mASetTemp = Integer.parseInt(mATempValueView.getText().toString());
getService().sendATemp(mASetTemp);
mASetTime = Integer.parseInt(mATimeValueView.getText().toString());
getService().sendATime(mASetTime);
mESetTemp = Integer.parseInt(mETempValueView.getText().toString());
getService().sendETemp(mESetTemp);
mESetTime = Integer.parseInt(mETimeValueView.getText().toString());
getService().sendETime(mESetTime);
mNPcrC = Integer.parseInt(mNPcrCView.getText().toString());
getService().sendNPcrN(mNPcrC);
*/
} else {
getService().heatingSwitch(0);
}
mHeatingStatusView.setText(isChecked ? R.string.Heating_block_on : R.string.Heating_block_off);
}
});
/*findViewById(R.id.time_set_button).setOnClickListener(v -> {
if (isDeviceConnected()) {
mSetTime = Integer.parseInt(mTimeValueView.getText().toString());
getService().sendTimeDuration(mSetTime);
}
});
findViewById(R.id.temp_set_button).setOnClickListener(v -> {
if (isDeviceConnected()) {
mSetTemp = Integer.parseInt(mTempValueView.getText().toString());
getService().sendTemp(mSetTemp);
}
});*/
}
@Override
protected void onInitialize(final Bundle savedInstanceState) {
LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, makeIntentFilter());
}
@Override
protected void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
}
@Override
protected void setDefaultUI() {
// TODO clear your UI
mValueView.setText(R.string.not_available_value);
}
@Override
protected int getLoggerProfileTitle() {
return R.string.template_feature_title;
}
/*@Override
protected void getAboutTextId() {
Intent =new Intent (TemplateActivity1.this,About.class);
startActivity(intent);
}*/
/* @Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.settings_and_about, menu);
return true;
}
@Override
protected boolean onOptionsItemSelected(final int itemId) {
switch (itemId) {
*//*case R.id.action_settings:
final Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
break;*//*
}
return true;
}*/
@Override
protected int getDefaultDeviceName() {
return R.string.template_default_name;
}
@Override
protected UUID getFilterUUID() {
// TODO this method may return the UUID of the service that is required to be in the advertisement packet of a device in order to be listed on the Scanner dialog.
// If null is returned no filtering is done.
return TemplateManager.SERVICE_UUID;
}
@Override
protected Class<? extends BleProfileService> getServiceClass() {
return SPCAService.class;
}
@Override
protected void onServiceBound(final SPCAService.TemplateBinder binder) {
// not used
}
@Override
protected void onServiceUnbound() {
// not used
}
@Override
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
// this may notify user or show some views
}
@Override
public void onDeviceDisconnected(final BluetoothDevice device) {
super.onDeviceDisconnected(device);
}
// Handling updates from the device
@SuppressWarnings("unused")
private void setValueOnView(@NonNull final BluetoothDevice device, final int value) {
// TODO assign the value to a view
if(mHeatingState.isChecked())
{
mValueView.setText(String.valueOf(value));
d.postDelayed(new Runnable() {
public void run() {
d.setEnabled(true);
Log.d(TAG, "resend1");
}
}, 7000);
d.postDelayed(new Runnable() {
public void run() {
act2_1=value;
mValueView.setText(String.valueOf(act2_1));
Log.d(TAG, "resend1");
}
}, 5000);
d.postDelayed(new Runnable() {
public void run() {
act2_2=value;
mValueView.setText(String.valueOf(act2_2));
Log.d(TAG, "resend1");
}
}, 6000);
d.postDelayed(new Runnable() {
public void run() {
act2_3=value;
mValueView.setText(String.valueOf(act2_3));
Log.d(TAG, "resend1");
}
}, 7000);
}
/*else if (!mHeatingState.isChecked() && count ==1) {
love=1;
count=2;
Log.d("check1", String.valueOf(love));
mValueView.setText("_");
Log.d("love", String.valueOf(love));
Log.d("love", String.valueOf(p));
}
else if ( mHeatingState.isChecked() && love ==1 )
{
q=value;
final int d=value;
Log.d("Addq", String.valueOf(q));
mValueView.setText(String.valueOf(d));
love1=1;
}
else if(!mHeatingState.isChecked() && love1 ==1)
{
love3=1;
mValueView.setText("_");
Log.d("check1", String.valueOf(love));
}
else if(mHeatingState.isChecked() && love3 ==1)
{
r=value;
mValueView.setText(String.valueOf(value));
Log.d("Addr", String.valueOf(r));
}
*/
else
{
mValueView.setText("_");
}
}
@SuppressWarnings("unused")
public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int value) {
}
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
final String action = intent.getAction();
final BluetoothDevice device = intent.getParcelableExtra(SPCAService.EXTRA_DEVICE);
if (SPCAService.BROADCAST_TEMPLATE_MEASUREMENT.equals(action)) {
final int value = intent.getIntExtra(SPCAService.EXTRA_DATA, 0);
// Update GUI
setValueOnView(device, value);
} else if (SPCAService.BROADCAST_BATTERY_LEVEL.equals(action)) {
final int batteryLevel = intent.getIntExtra(SPCAService.EXTRA_BATTERY_LEVEL, 0);
// Update GUI
onBatteryLevelChanged(device, batteryLevel);
}
}
};
private static IntentFilter makeIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(SPCAService.BROADCAST_TEMPLATE_MEASUREMENT);
intentFilter.addAction(SPCAService.BROADCAST_BATTERY_LEVEL);
return intentFilter;
}
@Override
public void onBackPressed() {
//super.onBackPressed();
IsFinish("Want to exit Test ?");
}
public void IsFinish(String alertmessage) {
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
Intent intent = new Intent(TemplateActivity1.this, TestDetails.class);
startActivity(intent); // This above line close correctly
//finish();
break;
case DialogInterface.BUTTON_NEGATIVE:
break;
}
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(alertmessage)
.setPositiveButton("Yes", dialogClickListener)
.setNegativeButton("No", dialogClickListener).show();
AlertDialog alertDialog = builder.create();
alertDialog.show();
alertDialog.getButton(Dialog.BUTTON_NEGATIVE).setTextColor(Color.BLACK);
alertDialog.getButton(Dialog.BUTTON_POSITIVE).setTextColor(Color.BLACK);
alertDialog.getButton(Dialog.BUTTON_NEGATIVE).
setBackgroundColor(Color.TRANSPARENT);
alertDialog.getButton(Dialog.BUTTON_POSITIVE).
setBackgroundColor(Color.TRANSPARENT);
}
}

View File

@@ -0,0 +1,529 @@
package no.Reader.android.iisc.Reader;
import android.app.AlertDialog;
import android.app.Dialog;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import java.util.UUID;
import no.Reader.android.iisc.R;
import no.Reader.android.iisc.profile.BleProfileService;
import no.Reader.android.iisc.profile.BleProfileServiceReadyActivity;
/**
* Modify the Template Activity to match your needs.
*/
public class TemplateActivity2 extends BleProfileServiceReadyActivity<SPCAService.TemplateBinder> {
@SuppressWarnings("unused")
private final String TAG = "TemplateActivity";
// TODO change view references to match your need
private TextView mValueView;
private TextView mHeatingStatusView;
private Switch mHeatingState ;
int p ,q,r;
private EditText sampledata;
int act3_1=0;
int act3_2=0;
int act3_3=0;
int count =0;
int love=0;
int love1=0;
int love2=0;
int love3=0;
private TextView mClockView;
int act3=0;
private Button d,connect;
/*private EditText mDTimeValueView;
private Integer mDSetTime ;
private EditText mLTimeValueView;
private Integer mLSetTime ;
private EditText mOTimeValueView;
private Integer mOSetTime ;
private TextView mClockView;
private EditText mATimeValueView;
private Integer mASetTime ;
private EditText mETimeValueView;
private Integer mESetTime ;
private EditText mDTempValueView;
private Integer mDSetTemp ;
private EditText mATempValueView;
private Integer mASetTemp ;
private EditText mETempValueView;
private Integer mESetTemp ;
private EditText mLTempValueView;
private Integer mLSetTemp ;
private EditText mOTempValueView;
private Integer mOSetTemp ;
private EditText mNPcrCView;
private Integer mNPcrC ;
*/
@Override
protected void onCreateView(final Bundle savedInstanceState) {
// TODO modify the layout file(s). By default the activity shows only one field - the Heart Rate value as a sample
setContentView(R.layout.activity_feature_template2);
sampledata=findViewById(R.id.samplename);
BottomNavigationView bottomNav = findViewById(R.id.bottom_navigation);
bottomNav.setOnNavigationItemSelectedListener(navListener);
setGUI();
connect=findViewById(R.id.action_connect);
d.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SharedPreferences preferences = getSharedPreferences("PhoneBook_adc3", MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
// editor.putString(Name, phonenum);
/* editor.putString("act3", String.valueOf(act3));
Log.d("Addact1", String.valueOf(act3));
editor.commit();
*/
editor.putString("act3_1", String.valueOf(act3_1));
editor.putString("act3_2", String.valueOf(act3_2));
editor.putString("act3_3", String.valueOf(act3_3));
editor.putString("samplename", String.valueOf(sampledata.getText()));
Log.d("Addact21", String.valueOf(act3_1));
Log.d("Addact22", String.valueOf(act3_2));
Log.d("Addact23", String.valueOf(act3_3));
editor.commit();
mHeatingState.setChecked(false);
Intent intent = new Intent(TemplateActivity2.this, check1.class);
startActivity(intent);
}
});
}
private void setGUI() {
// mClockView=findViewById(R.id.RemTime_Value);
// TODO assign your views to fields
mValueView = findViewById(R.id.Temp_Value);
d=findViewById(R.id.next);
/*mDTempValueView = findViewById(R.id.D_Temp_Set);
mDTimeValueView = findViewById(R.id.D_Time_Set);
mATempValueView = findViewById(R.id.A_Temp_Set);
mATimeValueView = findViewById(R.id.A_Time_Set);
mETempValueView = findViewById(R.id.E_Temp_Set);
mETimeValueView = findViewById(R.id.E_Time_Set);
mLTempValueView=findViewById(R.id.L_Temp_Set);
mOTempValueView=findViewById(R.id.O_Temp_Set);
mLTimeValueView = findViewById(R.id.L_Time_Set);
mOTimeValueView = findViewById(R.id.O_Time_Set);
*/
/*
mNPcrCView = findViewById(R.id.N_Pcr_C);
*/
mHeatingState = findViewById(R.id.heating_state);
mHeatingStatusView= findViewById(R.id.heating_status_text);
mHeatingState.setOnCheckedChangeListener((buttonView, isChecked) -> {
if(connect.getText().equals("CONNECT"))
{
Toast.makeText(TemplateActivity2.this, "Please connect to device", Toast.LENGTH_SHORT).show();
}
else {
if (isChecked) {
getService().heatingSwitch(1);
/* mDSetTemp = Integer.parseInt(mDTempValueView.getText().toString());
getService().sendDTemp(mDSetTemp);
mDSetTime = Integer.parseInt(mDTimeValueView.getText().toString());
getService().sendDTime(mDSetTime);
mLSetTemp = Integer.parseInt(mLTempValueView.getText().toString());
getService().sendLTemp(mLSetTemp);
mLSetTime = Integer.parseInt(mLTimeValueView.getText().toString());
getService().sendLTime(mLSetTime);
mOSetTemp = Integer.parseInt(mOTempValueView.getText().toString());
getService().sendOTemp(mOSetTemp);
mOSetTime = Integer.parseInt(mOTimeValueView.getText().toString());
getService().sendOTime(mOSetTime);
// Log.d("Add", String.valueOf(m));
mASetTemp = Integer.parseInt(mATempValueView.getText().toString());
getService().sendATemp(mASetTemp);
mASetTime = Integer.parseInt(mATimeValueView.getText().toString());
getService().sendATime(mASetTime);
mESetTemp = Integer.parseInt(mETempValueView.getText().toString());
getService().sendETemp(mESetTemp);
mESetTime = Integer.parseInt(mETimeValueView.getText().toString());
getService().sendETime(mESetTime);
mNPcrC = Integer.parseInt(mNPcrCView.getText().toString());
getService().sendNPcrN(mNPcrC);
*/
}
else {
getService().heatingSwitch(0);
}
mHeatingStatusView.setText(isChecked ? R.string.Heating_block_on : R.string.Heating_block_off);
}});
/*findViewById(R.id.time_set_button).setOnClickListener(v -> {
if (isDeviceConnected()) {
mSetTime = Integer.parseInt(mTimeValueView.getText().toString());
getService().sendTimeDuration(mSetTime);
}
});
findViewById(R.id.temp_set_button).setOnClickListener(v -> {
if (isDeviceConnected()) {
mSetTemp = Integer.parseInt(mTempValueView.getText().toString());
getService().sendTemp(mSetTemp);
}
});*/
}
@Override
protected void onInitialize(final Bundle savedInstanceState) {
LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, makeIntentFilter());
}
@Override
protected void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
}
@Override
protected void setDefaultUI() {
// TODO clear your UI
mValueView.setText(R.string.not_available_value);
}
@Override
protected int getLoggerProfileTitle() {
return R.string.template_feature_title;
}
/*@Override
protected void getAboutTextId() {
Intent intent =new Intent (TemplateActivity2.this,About.class);
startActivity(intent);
}
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.settings_and_about, menu);
return true;
}
@Override
protected boolean onOptionsItemSelected(final int itemId) {
switch (itemId) {
*//*case R.id.action_settings:
final Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
break;*//*
}
return true;
}
*/
@Override
protected int getDefaultDeviceName() {
return R.string.template_default_name;
}
@Override
protected UUID getFilterUUID() {
// TODO this method may return the UUID of the service that is required to be in the advertisement packet of a device in order to be listed on the Scanner dialog.
// If null is returned no filtering is done.
return TemplateManager.SERVICE_UUID;
}
@Override
protected Class<? extends BleProfileService> getServiceClass() {
return SPCAService.class;
}
@Override
protected void onServiceBound(final SPCAService.TemplateBinder binder) {
// not used
}
@Override
protected void onServiceUnbound() {
// not used
}
@Override
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
// this may notify user or show some views
}
@Override
public void onDeviceDisconnected(final BluetoothDevice device) {
super.onDeviceDisconnected(device);
}
// Handling updates from the device
@SuppressWarnings("unused")
private void setValueOnView(@NonNull final BluetoothDevice device, final int value) {
mValueView.setText(String.valueOf(value));
// TODO assign the value to a view
if(mHeatingState.isChecked())
{
d.postDelayed(new Runnable() {
public void run() {
d.setEnabled(true);
Log.d(TAG, "resend1");
}
}, 7000);
d.postDelayed(new Runnable() {
public void run() {
act3_1=value;
mValueView.setText(String.valueOf(act3_1));
Log.d(TAG, "resend1");
}
}, 5000);
d.postDelayed(new Runnable() {
public void run() {
act3_2=value;
mValueView.setText(String.valueOf(act3_2));
Log.d(TAG, "resend1");
}
}, 6000);
d.postDelayed(new Runnable() {
public void run() {
act3_3=value;
mValueView.setText(String.valueOf(act3_3));
Log.d(TAG, "resend1");
}
}, 7000);
}
/*else if (!mHeatingState.isChecked() && count ==1) {
love=1;
count=2;
Log.d("check1", String.valueOf(love));
mValueView.setText("_");
Log.d("love", String.valueOf(love));
Log.d("love", String.valueOf(p));
}
else if ( mHeatingState.isChecked() && love ==1 )
{
q=value;
final int d=value;
Log.d("Addq", String.valueOf(q));
mValueView.setText(String.valueOf(d));
love1=1;
}
else if(!mHeatingState.isChecked() && love1 ==1)
{
love3=1;
mValueView.setText("_");
Log.d("check1", String.valueOf(love));
}
else if(mHeatingState.isChecked() && love3 ==1)
{
r=value;
mValueView.setText(String.valueOf(value));
Log.d("Addr", String.valueOf(r));
}
*/
else
{
mValueView.setText("_");
}
}
@SuppressWarnings("unused")
public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int value) {
}
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
final String action = intent.getAction();
final BluetoothDevice device = intent.getParcelableExtra(SPCAService.EXTRA_DEVICE);
if (SPCAService.BROADCAST_TEMPLATE_MEASUREMENT.equals(action)) {
final int value = intent.getIntExtra(SPCAService.EXTRA_DATA, 0);
// Update GUI
setValueOnView(device, value);
} else if (SPCAService.BROADCAST_BATTERY_LEVEL.equals(action)) {
final int batteryLevel = intent.getIntExtra(SPCAService.EXTRA_BATTERY_LEVEL, 0);
// Update GUI
onBatteryLevelChanged(device, batteryLevel);
}
}
};
private static IntentFilter makeIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(SPCAService.BROADCAST_TEMPLATE_MEASUREMENT);
intentFilter.addAction(SPCAService.BROADCAST_BATTERY_LEVEL);
return intentFilter;
}
private BottomNavigationView.OnNavigationItemSelectedListener navListener =
new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_home:
Intent intent = new Intent(TemplateActivity2.this, MainActivity.class);
startActivity(intent);
break;
case R.id.nav_addtest:
Intent intent2 = new Intent(TemplateActivity2.this, TestDetails.class);
startActivity(intent2);
break;
case R.id.nav_add_sample:
Intent intent3 = new Intent(TemplateActivity2.this, TemplateActivity2.class);
startActivity(intent3);
break;
}
return true;
}
};
@Override
public void onBackPressed() {
//super.onBackPressed();
IsFinish("Want to exit Test ?");
}
public void IsFinish(String alertmessage) {
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
Intent intent = new Intent(TemplateActivity2.this, TestDetails.class);
startActivity(intent);
break;
case DialogInterface.BUTTON_NEGATIVE:
break;
}
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(alertmessage)
.setPositiveButton("Yes", dialogClickListener)
.setNegativeButton("No", dialogClickListener).show();
AlertDialog alertDialog = builder.create();
alertDialog.show();
alertDialog.getButton(Dialog.BUTTON_NEGATIVE).setTextColor(Color.BLACK);
alertDialog.getButton(Dialog.BUTTON_POSITIVE).setTextColor(Color.BLACK);
alertDialog.getButton(Dialog.BUTTON_NEGATIVE).
setBackgroundColor(Color.TRANSPARENT);
alertDialog.getButton(Dialog.BUTTON_POSITIVE).
setBackgroundColor(Color.TRANSPARENT);
}
}

View File

@@ -0,0 +1,391 @@
package no.Reader.android.iisc.Reader;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Switch;
import android.widget.TextView;
import java.util.UUID;
import no.Reader.android.iisc.R;
import no.Reader.android.iisc.profile.BleProfileService;
import no.Reader.android.iisc.profile.BleProfileServiceReadyActivity;
/**
* Modify the Template Activity to match your needs.
*/
public class TemplateActivity3 extends BleProfileServiceReadyActivity<SPCAService.TemplateBinder> {
@SuppressWarnings("unused")
private final String TAG = "TemplateActivity";
// TODO change view references to match your need
private TextView mValueView;
private TextView mHeatingStatusView;
private Switch mHeatingState ;
int p ,q,r;
int count =0;
int love=0;
int love1=0;
int love2=0;
int love3=0;
private TextView mClockView;
int act1=0;
private Button d,next;
String value1,value2,value3;
/*private EditText mDTimeValueView;
private Integer mDSetTime ;
private EditText mLTimeValueView;
private Integer mLSetTime ;
private EditText mOTimeValueView;
private Integer mOSetTime ;
private TextView mClockView;
private EditText mATimeValueView;
private Integer mASetTime ;
private EditText mETimeValueView;
private Integer mESetTime ;
private EditText mDTempValueView;
private Integer mDSetTemp ;
private EditText mATempValueView;
private Integer mASetTemp ;
private EditText mETempValueView;
private Integer mESetTemp ;
private EditText mLTempValueView;
private Integer mLSetTemp ;
private EditText mOTempValueView;
private Integer mOSetTemp ;
private EditText mNPcrCView;
private Integer mNPcrC ;
*/
@Override
protected void onCreateView(final Bundle savedInstanceState) {
// TODO modify the layout file(s). By default the activity shows only one field - the Heart Rate value as a sample
setContentView(R.layout.activity_feature_template3);
setGUI();
SharedPreferences preferences6 = getSharedPreferences("PhoneBook", MODE_PRIVATE);
value1 = preferences6.getString("act1", null);
SharedPreferences preferences7 = getSharedPreferences("PhoneBook1", MODE_PRIVATE);
value2 = preferences7.getString("act2", null);
SharedPreferences preferences8 = getSharedPreferences("PhoneBook2", MODE_PRIVATE);
value3 = preferences8.getString("act3", null);
next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent =new Intent (TemplateActivity3.this,TemplateActivity.class);
startActivity(intent);
}
});
Log.d("value1", String.valueOf(value1));
Log.d("value2", String.valueOf(value2));
Log.d("value3", String.valueOf(value3));
}
private void setGUI() {
// mClockView=findViewById(R.id.RemTime_Value);
// TODO assign your views to fields
// mValueView = findViewById(R.id.Temp_Value);
// d=findViewById(R.id.next);
/*mDTempValueView = findViewById(R.id.D_Temp_Set);
mDTimeValueView = findViewById(R.id.D_Time_Set);
mATempValueView = findViewById(R.id.A_Temp_Set);
mATimeValueView = findViewById(R.id.A_Time_Set);
mETempValueView = findViewById(R.id.E_Temp_Set);
mETimeValueView = findViewById(R.id.E_Time_Set);
mLTempValueView=findViewById(R.id.L_Temp_Set);
mOTempValueView=findViewById(R.id.O_Temp_Set);
mLTimeValueView = findViewById(R.id.L_Time_Set);
mOTimeValueView = findViewById(R.id.O_Time_Set);
*/
/*
mNPcrCView = findViewById(R.id.N_Pcr_C);
*/
mHeatingState = findViewById(R.id.heating_state);
mHeatingStatusView= findViewById(R.id.heating_status_text);
next=findViewById(R.id.next);
mHeatingState.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) {
getService().heatingSwitch(1);
/* mDSetTemp = Integer.parseInt(mDTempValueView.getText().toString());
getService().sendDTemp(mDSetTemp);
mDSetTime = Integer.parseInt(mDTimeValueView.getText().toString());
getService().sendDTime(mDSetTime);
mLSetTemp = Integer.parseInt(mLTempValueView.getText().toString());
getService().sendLTemp(mLSetTemp);
mLSetTime = Integer.parseInt(mLTimeValueView.getText().toString());
getService().sendLTime(mLSetTime);
mOSetTemp = Integer.parseInt(mOTempValueView.getText().toString());
getService().sendOTemp(mOSetTemp);
mOSetTime = Integer.parseInt(mOTimeValueView.getText().toString());
getService().sendOTime(mOSetTime);
// Log.d("Add", String.valueOf(m));
mASetTemp = Integer.parseInt(mATempValueView.getText().toString());
getService().sendATemp(mASetTemp);
mASetTime = Integer.parseInt(mATimeValueView.getText().toString());
getService().sendATime(mASetTime);
mESetTemp = Integer.parseInt(mETempValueView.getText().toString());
getService().sendETemp(mESetTemp);
mESetTime = Integer.parseInt(mETimeValueView.getText().toString());
getService().sendETime(mESetTime);
mNPcrC = Integer.parseInt(mNPcrCView.getText().toString());
getService().sendNPcrN(mNPcrC);
*/
}
else {
getService().heatingSwitch(0);
}
mHeatingStatusView.setText(isChecked ? R.string.Heating_block_on : R.string.Heating_block_off);
});
/*findViewById(R.id.time_set_button).setOnClickListener(v -> {
if (isDeviceConnected()) {
mSetTime = Integer.parseInt(mTimeValueView.getText().toString());
getService().sendTimeDuration(mSetTime);
}
});
findViewById(R.id.temp_set_button).setOnClickListener(v -> {
if (isDeviceConnected()) {
mSetTemp = Integer.parseInt(mTempValueView.getText().toString());
getService().sendTemp(mSetTemp);
}
});*/
}
@Override
protected void onInitialize(final Bundle savedInstanceState) {
LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, makeIntentFilter());
}
@Override
protected void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
}
@Override
protected void setDefaultUI() {
// TODO clear your UI
mValueView.setText(R.string.not_available_value);
}
@Override
protected int getLoggerProfileTitle() {
return R.string.template_feature_title;
}
/*@Override
protected void getAboutTextId() {
Intent intent =new Intent (TemplateActivity3.this,About.class);
startActivity(intent);
}
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.settings_and_about, menu);
return true;
}
@Override
protected boolean onOptionsItemSelected(final int itemId) {
switch (itemId) {
*//*case R.id.action_settings:
final Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
break;*//*
}
return true;
}
*/
@Override
protected int getDefaultDeviceName() {
return R.string.template_default_name;
}
@Override
protected UUID getFilterUUID() {
// TODO this method may return the UUID of the service that is required to be in the advertisement packet of a device in order to be listed on the Scanner dialog.
// If null is returned no filtering is done.
return TemplateManager.SERVICE_UUID;
}
@Override
protected Class<? extends BleProfileService> getServiceClass() {
return SPCAService.class;
}
@Override
protected void onServiceBound(final SPCAService.TemplateBinder binder) {
// not used
}
@Override
protected void onServiceUnbound() {
// not used
}
@Override
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
// this may notify user or show some views
}
@Override
public void onDeviceDisconnected(final BluetoothDevice device) {
super.onDeviceDisconnected(device);
}
// Handling updates from the device
@SuppressWarnings("unused")
private void setValueOnView(@NonNull final BluetoothDevice device, final int value) {
// TODO assign the value to a view
if(mHeatingState.isChecked())
{
act1=value;
mValueView.setText(String.valueOf(act1));
}
/*else if (!mHeatingState.isChecked() && count ==1) {
love=1;
count=2;
Log.d("check1", String.valueOf(love));
mValueView.setText("_");
Log.d("love", String.valueOf(love));
Log.d("love", String.valueOf(p));
}
else if ( mHeatingState.isChecked() && love ==1 )
{
q=value;
final int d=value;
Log.d("Addq", String.valueOf(q));
mValueView.setText(String.valueOf(d));
love1=1;
}
else if(!mHeatingState.isChecked() && love1 ==1)
{
love3=1;
mValueView.setText("_");
Log.d("check1", String.valueOf(love));
}
else if(mHeatingState.isChecked() && love3 ==1)
{
r=value;
mValueView.setText(String.valueOf(value));
Log.d("Addr", String.valueOf(r));
}
*/
else
{
mValueView.setText("_");
}
}
@SuppressWarnings("unused")
public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int value) {
}
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
final String action = intent.getAction();
final BluetoothDevice device = intent.getParcelableExtra(SPCAService.EXTRA_DEVICE);
if (SPCAService.BROADCAST_TEMPLATE_MEASUREMENT.equals(action)) {
final int value = intent.getIntExtra(SPCAService.EXTRA_DATA, 0);
// Update GUI
setValueOnView(device, value);
} else if (SPCAService.BROADCAST_BATTERY_LEVEL.equals(action)) {
final int batteryLevel = intent.getIntExtra(SPCAService.EXTRA_BATTERY_LEVEL, 0);
// Update GUI
onBatteryLevelChanged(device, batteryLevel);
}
}
};
private static IntentFilter makeIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(SPCAService.BROADCAST_TEMPLATE_MEASUREMENT);
intentFilter.addAction(SPCAService.BROADCAST_BATTERY_LEVEL);
return intentFilter;
}
}

View File

@@ -0,0 +1,959 @@
package no.Reader.android.iisc.Reader;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import androidx.annotation.NonNull;
import android.util.Log;
import java.util.UUID;
import no.nordicsemi.android.ble.BleManager;
import no.nordicsemi.android.ble.data.Data;
import no.nordicsemi.android.log.LogContract;
import no.Reader.android.iisc.battery.BatteryManager;
import no.Reader.android.iisc.parser.SPCAParser;
import no.Reader.android.iisc.Reader.callback.SPCADataCallback;
/**
* Modify to template manager to match your requirements.
* The TemplateManager extends {@link BatteryManager}, but it may easily extend {@link BleManager}
* instead if you don't need Battery Service support. If not, also modify the
* {@link SPCAManagerCallbacks} to extend {@link no.nordicsemi.android.ble.BleManagerCallbacks}
* and replace BatteryManagerGattCallback to BleManagerGattCallback in this class.
*/
public class TemplateManager extends BatteryManager<SPCAManagerCallbacks> {
// TODO Replace the services and characteristics below to match your device.
/**
* The service UUID.
*/
/*static final UUID SERVICE_UUID = UUID.fromString("00001500-1212-efde-1523-785feabcd123"); // Heart Rate service
*//**
* A UUID of a characteristic with notify property.
*//*
//private static final UUID MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00001501-1212-efde-1523-785feabcd123"); // Heart Rate Measurement
//private static final UUID TEMPERATURE_CHARACTERISTIC_UUID = UUID.fromString("00001501-1212-efde-1523-785feabcd123"); // Heart Rate Measurement
*//**
* A UUID of a characteristic with read property.
*//*
//private static final UUID READABLE_CHARACTERISTIC_UUID = UUID.fromString("00001502-1212-efde-1523-785feabcd123"); // Body Sensor Location
private static final UUID TEMP_READABLE_CHARACTERISTIC_UUID = UUID.fromString("00001501-1212-efde-1523-785feabcd123"); // Body Sensor Location
*//**
* A UUID of a characteristic with write property.
*//*
private static final UUID D_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001503-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID A_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001504-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID E_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001505-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID L_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001514-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID O_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001502-1212-efde-1523-785feabcd123"); // Device Name
*//**
* A UUID of a characteristic with write property.
*//*
private static final UUID D_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001509-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID A_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001510-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID E_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001511-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID L_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001515-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID O_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001508-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID N_PCR_C_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001512-1212-efde-1523-785feabcd123"); // Device Name
*//**
* A UUID of a characteristic with write property.
*//*
private static final UUID AMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001513-1212-efde-1523-785feabcd123"); // Device Name
*//**
* Some other service UUID.
*//*
private static final UUID OTHER_SERVICE_UUID = UUID.fromString("00001800-0000-1000-8000-00805f9b34fb"); // Generic Access service
*//**
* A UUID of a characteristic with write property.
*//*
private static final UUID READABLE_CHARACTERISTIC_UUID = UUID.fromString("00001801-0000-1000-8000-00805f9b34fb"); // Device Name
*/
static final UUID SERVICE_UUID = UUID.fromString("00001600-1212-efde-1523-785feabcd123"); // Heart Rate service
/**
* A UUID of a characteristic with notify property.
*/
//private static final UUID MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00001501-1212-efde-1523-785feabcd123"); // Heart Rate Measurement
//private static final UUID TEMPERATURE_CHARACTERISTIC_UUID = UUID.fromString("00001501-1212-efde-1523-785feabcd123"); // Heart Rate Measurement
/**
* A UUID of a characteristic with read property.
*/
//private static final UUID READABLE_CHARACTERISTIC_UUID = UUID.fromString("00001502-1212-efde-1523-785feabcd123"); // Body Sensor Location
private static final UUID TEMP_READABLE_CHARACTERISTIC_UUID = UUID.fromString("00001601-1212-efde-1523-785feabcd123"); // Body Sensor Location
private static final UUID CLOCK_READABLE_CHARACTERISTIC_UUID = UUID.fromString("00001604-1212-efde-1523-785feabcd123"); // Body Sensor Location
/**
* A UUID of a characteristic with write property.
*/
private static final UUID D_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001604-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID A_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001604-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID E_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001604-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID L_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001604-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID O_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001604-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID S_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001604-1212-efde-1523-785feabcd123"); // Device Name
/**
* A UUID of a characteristic with write property.
*/
private static final UUID D_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001604-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID A_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001604-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID E_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001604-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID L_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001604-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID O_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001604-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID S_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001604-1212-efde-1523-785feabcd123"); // Device Name00001604-1212-efde-1523-785feabcd123
private static final UUID N_PCR_C_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001604-1212-efde-1523-785feabcd123"); // Device Name
/**
* A UUID of a characteristic with write property.
*/
private static final UUID AMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001604-1212-efde-1523-785feabcd123"); // Device Name
/**
* Some other service UUID.
*/
private static final UUID OTHER_SERVICE_UUID = UUID.fromString("00001800-0000-1000-8000-00805f9b34fb"); // Generic Access service
/**
* A UUID of a characteristic with write property.
*/
private static final UUID READABLE_CHARACTERISTIC_UUID = UUID.fromString("00001801-0000-1000-8000-00805f9b34fb"); // Device Name
// TODO Add more services and characteristics references.
private BluetoothGattCharacteristic mReadBlockTempCharacteristic, mSetDTempCharacteristic, mSetDTimeCharacteristic, mSetATempCharacteristic, mSetATimeCharacteristic, mSetETempCharacteristic, mSetETimeCharacteristic, mSetNPcrCCharacteristic, mAmpStartStopCharacteristic, mDeviceNameCharacteristic, mRequiredCharacteristic, mOptionalCharacteristic
,mSetLTempCharacteristic,mSetOTempCharacteristic,mSetLTimeCharacteristic,mSetOTimeCharacteristic;
public TemplateManager(final Context context) {
super(context);
}
@NonNull
@Override
protected BatteryManagerGattCallback getGattCallback() {
return mGattCallback;
}
/**
* BluetoothGatt callbacks for connection/disconnection, service discovery,
* receiving indication, etc.
*/
private final BatteryManagerGattCallback mGattCallback = new BatteryManagerGattCallback() {
@Override
protected void initialize() {
// Initialize the Battery Manager. It will enable Battery Level notifications.
// Remove it if you don't need this feature.
super.initialize();
// TODO Initialize your manager here.
// Initialization is done once, after the device is connected. Usually it should
// enable notifications or indications on some characteristics, write some data or
// read some features / version.
// After the initialization is complete, the onDeviceReady(...) method will be called.
// Increase the MTU
requestMtu(43)//requestMtu(43)
.with((device, mtu) -> log(LogContract.Log.Level.APPLICATION, "MTU changed to " + mtu))
.done(device -> {
// You may do some logic in here that should be done when the request finished successfully.
// In case of MTU this method is called also when the MTU hasn't changed, or has changed
// to a different (lower) value. Use .with(...) to get the MTU value.
})
.fail((device, status) -> log(Log.WARN, "MTU change not supported"))
.enqueue();
// Set notification callback
setNotificationCallback(mReadBlockTempCharacteristic)
// This callback will be called each time the notification is received
.with(new SPCADataCallback() {
@Override
public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
if(data!=null) {
log(LogContract.Log.Level.APPLICATION, SPCAParser.parse(data));
super.onDataReceived(device, data);
}
}
@Override
public void onSampleValueReceived(@NonNull final BluetoothDevice device, final int value) {
// Let's lass received data to the service
mCallbacks.onSampleValueReceived(device, value);
}
@Override
public void onInvalidDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
log(Log.WARN, "Invalid data received: " + data);
}
});
// Enable notifications
enableNotifications(mReadBlockTempCharacteristic)
// Method called after the data were sent (data will contain 0x0100 in this case)
.with((device, data) -> log(Log.DEBUG, "Data sent: " + data))
// Method called when the request finished successfully. This will be called after .with(..) callback
.done(device -> log(LogContract.Log.Level.APPLICATION, "Notifications enabled successfully"))
// Methods called in case of an error, for example when the characteristic does not have Notify property
.fail((device, status) -> log(Log.WARN, "Failed to enable notifications"))
.enqueue();
}
@Override
protected boolean isRequiredServiceSupported(@NonNull final BluetoothGatt gatt) {
// TODO Initialize required characteristics.
// It should return true if all has been discovered (that is that device is supported).
final BluetoothGattService service = gatt.getService(SERVICE_UUID);
if (service != null) {
mReadBlockTempCharacteristic = service.getCharacteristic(TEMP_READABLE_CHARACTERISTIC_UUID);
mSetDTempCharacteristic = service.getCharacteristic(D_TEMP_WRITABLE_CHARACTERISTIC_UUID);
mSetDTimeCharacteristic = service.getCharacteristic(D_TIME_WRITABLE_CHARACTERISTIC_UUID);
mSetATempCharacteristic = service.getCharacteristic(A_TEMP_WRITABLE_CHARACTERISTIC_UUID);
mSetATimeCharacteristic = service.getCharacteristic(A_TIME_WRITABLE_CHARACTERISTIC_UUID);
mSetETempCharacteristic = service.getCharacteristic(E_TEMP_WRITABLE_CHARACTERISTIC_UUID);
mSetETimeCharacteristic = service.getCharacteristic(E_TIME_WRITABLE_CHARACTERISTIC_UUID);
mSetLTempCharacteristic = service.getCharacteristic(L_TEMP_WRITABLE_CHARACTERISTIC_UUID);
mSetLTimeCharacteristic = service.getCharacteristic(L_TIME_WRITABLE_CHARACTERISTIC_UUID);
mSetOTempCharacteristic = service.getCharacteristic(O_TEMP_WRITABLE_CHARACTERISTIC_UUID);
mSetOTimeCharacteristic = service.getCharacteristic(O_TIME_WRITABLE_CHARACTERISTIC_UUID);
mSetNPcrCCharacteristic = service.getCharacteristic(N_PCR_C_WRITABLE_CHARACTERISTIC_UUID);
mAmpStartStopCharacteristic = service.getCharacteristic(AMP_WRITABLE_CHARACTERISTIC_UUID);
}
final BluetoothGattService otherService = gatt.getService(OTHER_SERVICE_UUID);
if (otherService != null) {
mDeviceNameCharacteristic = otherService.getCharacteristic(READABLE_CHARACTERISTIC_UUID);
}
return mReadBlockTempCharacteristic != null && mSetDTempCharacteristic != null && mSetDTimeCharacteristic!= null && mSetATempCharacteristic != null && mSetATimeCharacteristic!= null && mSetETempCharacteristic != null && mSetLTempCharacteristic != null && mSetETimeCharacteristic!= null && mSetOTempCharacteristic != null && mSetLTimeCharacteristic!= null && mSetOTimeCharacteristic!= null && mSetNPcrCCharacteristic!= null && mAmpStartStopCharacteristic != null ;
}
@Override
protected boolean isOptionalServiceSupported(@NonNull final BluetoothGatt gatt) {
// Initialize Battery characteristic
super.isOptionalServiceSupported(gatt);
// TODO If there are some optional characteristics, initialize them there.
final BluetoothGattService service = gatt.getService(SERVICE_UUID);
if (service != null) {
mOptionalCharacteristic = service.getCharacteristic(READABLE_CHARACTERISTIC_UUID);
}
return mOptionalCharacteristic != null;
}
@Override
protected void onDeviceDisconnected() {
// Release Battery Service
super.onDeviceDisconnected();
// TODO Release references to your characteristics.
mRequiredCharacteristic = null;
mDeviceNameCharacteristic = null;
mOptionalCharacteristic = null;
}
@Override
protected void onDeviceReady() {
super.onDeviceReady();
// Initialization is now ready.
// The service or activity has been notified with no.nordicsemi.android.ble.BatteryManagerCallbacks#onDeviceReady().
// TODO Do some extra logic here, of remove onDeviceReady().
// Device is ready, let's read something here. Usually there is nothing else to be done
// here, as all had been done during initialization.
readCharacteristic(mReadBlockTempCharacteristic)
.with((device, data) -> {
// Characteristic value has been read
// Let's do some magic with it.
if (data.size() > 0) {
final Integer value = data.getIntValue(Data.FORMAT_UINT8, 0);
log(LogContract.Log.Level.APPLICATION, "Value '" + value + "' has been read!");
} else {
log(Log.WARN, "Value is empty!");
}
})
.enqueue();
}
};
// TODO Define manager's API
/**
* This method will write important data to the device.
*
* @param parameter parameter to be written.
*/
//Heating Switch
void heatingSwitch(int state) {
log(Log.WARN, "Write time duration \"" + state + "\"");
//final byte time_in_byte = time_duration.getBytes()[0];
final byte state_in_byte = (byte) state;
writeCharacteristic(mAmpStartStopCharacteristic, Data.opCode(state_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Heating State"))
.split()
.enqueue();
}
//Set Time
void sendDTime(int d_time) {
log(Log.WARN, "Write D Time Duration \"" + d_time + "\"");
final byte d_time_in_byte = (byte) d_time;
writeCharacteristic(mSetDTimeCharacteristic, Data.opCode(d_time_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Time"))
.split()
.enqueue();
}
void sendATime(int a_time) {
log(Log.WARN, "Write A Time Duration \"" + a_time + "\"");
final byte a_time_in_byte = (byte) a_time;
writeCharacteristic(mSetATimeCharacteristic, Data.opCode(a_time_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Time"))
.split()
.enqueue();
}
void sendLTime(int l_time) {
log(Log.WARN, "Write A Time Duration \"" + l_time + "\"");
final byte l_time_in_byte = (byte) l_time;
writeCharacteristic(mSetLTimeCharacteristic, Data.opCode(l_time_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Time"))
.split()
.enqueue();
}
void sendOTime(int o_time) {
log(Log.WARN, "Write A Time Duration \"" + o_time + "\"");
final byte a_time_in_byte = (byte) o_time;
writeCharacteristic(mSetOTimeCharacteristic, Data.opCode(a_time_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Time"))
.split()
.enqueue();
}
void sendETime(int e_time) {
log(Log.WARN, "Write E Time Duration \"" + e_time + "\"");
final byte e_time_in_byte = (byte) e_time;
writeCharacteristic(mSetETimeCharacteristic, Data.opCode(e_time_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Time"))
.split()
.enqueue();
}
//Set Temp
void sendDTemp(int d_temp) {
log(Log.WARN, "Write D temp \"" + d_temp + "\"");
final byte d_temp_in_byte = (byte) d_temp;
writeCharacteristic(mSetDTempCharacteristic, Data.opCode(d_temp_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Temp"))
.split()
.enqueue();
}
void sendLTemp(int l_temp) {
log(Log.WARN, "Write D temp \"" + l_temp + "\"");
final byte d_temp_in_byte = (byte) l_temp;
writeCharacteristic(mSetLTempCharacteristic, Data.opCode(d_temp_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Temp"))
.split()
.enqueue();
}
void sendOTemp(int o_temp) {
log(Log.WARN, "Write D temp \"" + o_temp + "\"");
final byte d_temp_in_byte = (byte) o_temp;
writeCharacteristic(mSetOTempCharacteristic, Data.opCode(d_temp_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Temp"))
.split()
.enqueue();
}
void sendATemp(int a_temp) {
log(Log.WARN, "Write A temp \"" + a_temp + "\"");
final byte a_temp_in_byte = (byte) a_temp;
writeCharacteristic(mSetATempCharacteristic, Data.opCode(a_temp_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Temp"))
.split()
.enqueue();
}
void sendETemp(int e_temp) {
log(Log.WARN, "Write E temp \"" + e_temp + "\"");
final byte e_temp_in_byte = (byte) e_temp;
writeCharacteristic(mSetETempCharacteristic, Data.opCode(e_temp_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Temp"))
.split()
.enqueue();
}
void sendNPcrC(int n_pcr_c) {
log(Log.WARN, "Write E temp \"" + n_pcr_c + "\"");
final byte n_pcr_c_in_byte = (byte) n_pcr_c;
writeCharacteristic(mSetNPcrCCharacteristic, Data.opCode(n_pcr_c_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Temp"))
.split()
.enqueue();
}
}
/*
* Copyright (c) 2015, Nordic Semiconductor
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*//*
package no.Reader.android.iisc.template;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import androidx.annotation.NonNull;
import android.util.Log;
import java.util.UUID;
import no.nordicsemi.android.ble.BleManager;
import no.nordicsemi.android.ble.data.Data;
import no.nordicsemi.android.log.LogContract;
import no.Reader.android.iisc.battery.BatteryManager;
import no.Reader.android.iisc.parser.SPCAParser;
import no.Reader.android.iisc.template.callback.SPCADataCallback;
*/
/**
* Modify to template manager to match your requirements.
* The TemplateManager extends {@link BatteryManager}, but it may easily extend {@link BleManager}
* instead if you don't need Battery Service support. If not, also modify the
* {@link TemplateManagerCallbacks} to extend {@link no.nordicsemi.android.ble.BleManagerCallbacks}
* and replace BatteryManagerGattCallback to BleManagerGattCallback in this class.
*//*
public class TemplateManager extends BatteryManager<SPCAManagerCallbacks> {
// TODO Replace the services and characteristics below to match your device.
*/
/**
* The service UUID.
*//*
*/
/*static final UUID SERVICE_UUID = UUID.fromString("00001500-1212-efde-1523-785feabcd123"); // Heart Rate service
*//*
*/
/**
* A UUID of a characteristic with notify property.
*//*
*/
/*
//private static final UUID MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00001501-1212-efde-1523-785feabcd123"); // Heart Rate Measurement
//private static final UUID TEMPERATURE_CHARACTERISTIC_UUID = UUID.fromString("00001501-1212-efde-1523-785feabcd123"); // Heart Rate Measurement
*//*
*/
/**
* A UUID of a characteristic with read property.
*//*
*/
/*
//private static final UUID READABLE_CHARACTERISTIC_UUID = UUID.fromString("00001502-1212-efde-1523-785feabcd123"); // Body Sensor Location
private static final UUID TEMP_READABLE_CHARACTERISTIC_UUID = UUID.fromString("00001501-1212-efde-1523-785feabcd123"); // Body Sensor Location
*//*
*/
/**
* A UUID of a characteristic with write property.
*//*
*/
/*
private static final UUID D_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001503-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID A_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001504-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID E_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001505-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID L_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001514-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID O_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001502-1212-efde-1523-785feabcd123"); // Device Name
*//*
*/
/**
* A UUID of a characteristic with write property.
*//*
*/
/*
private static final UUID D_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001509-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID A_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001510-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID E_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001511-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID L_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001515-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID O_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001508-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID N_PCR_C_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001512-1212-efde-1523-785feabcd123"); // Device Name
*//*
*/
/**
* A UUID of a characteristic with write property.
*//*
*/
/*
private static final UUID AMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001513-1212-efde-1523-785feabcd123"); // Device Name
*//*
*/
/**
* Some other service UUID.
*//*
*/
/*
private static final UUID OTHER_SERVICE_UUID = UUID.fromString("00001800-0000-1000-8000-00805f9b34fb"); // Generic Access service
*//*
*/
/**
* A UUID of a characteristic with write property.
*//*
*/
/*
private static final UUID READABLE_CHARACTERISTIC_UUID = UUID.fromString("00001801-0000-1000-8000-00805f9b34fb"); // Device Name
*//*
static final UUID SERVICE_UUID = UUID.fromString("00001500-1212-efde-1523-785feabcd123"); // Heart Rate service
*/
/**
* A UUID of a characteristic with notify property.
*//*
//private static final UUID MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00001501-1212-efde-1523-785feabcd123"); // Heart Rate Measurement
//private static final UUID TEMPERATURE_CHARACTERISTIC_UUID = UUID.fromString("00001501-1212-efde-1523-785feabcd123"); // Heart Rate Measurement
*/
/**
* A UUID of a characteristic with read property.
*//*
//private static final UUID READABLE_CHARACTERISTIC_UUID = UUID.fromString("00001502-1212-efde-1523-785feabcd123"); // Body Sensor Location
private static final UUID TEMP_READABLE_CHARACTERISTIC_UUID = UUID.fromString("00001514-1212-efde-1523-785feabcd123"); // Body Sensor Location
private static final UUID CLOCK_READABLE_CHARACTERISTIC_UUID = UUID.fromString("00001514-1212-efde-1523-785feabcd123"); // Body Sensor Location
*/
/**
* A UUID of a characteristic with write property.
*//*
private static final UUID D_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001504-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID A_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001506-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID E_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001508-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID L_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001515-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID O_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001502-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID S_TEMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001510-1212-efde-1523-785feabcd123"); // Device Name
*/
/**
* A UUID of a characteristic with write property.
*//*
private static final UUID D_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001505-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID A_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001507-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID E_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001509-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID L_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001516-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID O_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001503-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID S_TIME_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001511-1212-efde-1523-785feabcd123"); // Device Name
private static final UUID N_PCR_C_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001512-1212-efde-1523-785feabcd123"); // Device Name
*/
/**
* A UUID of a characteristic with write property.
*//*
private static final UUID AMP_WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00001513-1212-efde-1523-785feabcd123"); // Device Name
*/
/**
* Some other service UUID.
*//*
private static final UUID OTHER_SERVICE_UUID = UUID.fromString("00001800-0000-1000-8000-00805f9b34fb"); // Generic Access service
*/
/**
* A UUID of a characteristic with write property.
*//*
private static final UUID READABLE_CHARACTERISTIC_UUID = UUID.fromString("00001801-0000-1000-8000-00805f9b34fb"); // Device Name
// TODO Add more services and characteristics references.
private BluetoothGattCharacteristic mReadBlockTempCharacteristic, mSetDTempCharacteristic, mSetDTimeCharacteristic, mSetATempCharacteristic, mSetATimeCharacteristic, mSetETempCharacteristic, mSetETimeCharacteristic, mSetNPcrCCharacteristic, mAmpStartStopCharacteristic, mDeviceNameCharacteristic, mRequiredCharacteristic, mOptionalCharacteristic
,mSetLTempCharacteristic,mSetOTempCharacteristic,mSetLTimeCharacteristic,mSetOTimeCharacteristic;
public TemplateManager(final Context context) {
super(context);
}
@NonNull
@Override
protected BatteryManagerGattCallback getGattCallback() {
return mGattCallback;
}
*/
/**
* BluetoothGatt callbacks for connection/disconnection, service discovery,
* receiving indication, etc.
*//*
private final BatteryManagerGattCallback mGattCallback = new BatteryManagerGattCallback() {
@Override
protected void initialize() {
// Initialize the Battery Manager. It will enable Battery Level notifications.
// Remove it if you don't need this feature.
super.initialize();
// TODO Initialize your manager here.
// Initialization is done once, after the device is connected. Usually it should
// enable notifications or indications on some characteristics, write some data or
// read some features / version.
// After the initialization is complete, the onDeviceReady(...) method will be called.
// Increase the MTU
requestMtu(43)//requestMtu(43)
.with((device, mtu) -> log(LogContract.Log.Level.APPLICATION, "MTU changed to " + mtu))
.done(device -> {
// You may do some logic in here that should be done when the request finished successfully.
// In case of MTU this method is called also when the MTU hasn't changed, or has changed
// to a different (lower) value. Use .with(...) to get the MTU value.
})
.fail((device, status) -> log(Log.WARN, "MTU change not supported"))
.enqueue();
// Set notification callback
setNotificationCallback(mReadBlockTempCharacteristic)
// This callback will be called each time the notification is received
.with(new SPCADataCallback() {
@Override
public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
log(LogContract.Log.Level.APPLICATION, SPCAParser.parse(data));
super.onDataReceived(device, data);
}
@Override
public void onSampleValueReceived(@NonNull final BluetoothDevice device, final int value) {
// Let's lass received data to the service
mCallbacks.onSampleValueReceived(device, value);
}
@Override
public void onInvalidDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
log(Log.WARN, "Invalid data received: " + data);
}
});
// Enable notifications
enableNotifications(mReadBlockTempCharacteristic)
// Method called after the data were sent (data will contain 0x0100 in this case)
.with((device, data) -> log(Log.DEBUG, "Data sent: " + data))
// Method called when the request finished successfully. This will be called after .with(..) callback
.done(device -> log(LogContract.Log.Level.APPLICATION, "Notifications enabled successfully"))
// Methods called in case of an error, for example when the characteristic does not have Notify property
.fail((device, status) -> log(Log.WARN, "Failed to enable notifications"))
.enqueue();
}
@Override
protected boolean isRequiredServiceSupported(@NonNull final BluetoothGatt gatt) {
// TODO Initialize required characteristics.
// It should return true if all has been discovered (that is that device is supported).
final BluetoothGattService service = gatt.getService(SERVICE_UUID);
if (service != null) {
mReadBlockTempCharacteristic = service.getCharacteristic(TEMP_READABLE_CHARACTERISTIC_UUID);
mSetDTempCharacteristic = service.getCharacteristic(D_TEMP_WRITABLE_CHARACTERISTIC_UUID);
mSetDTimeCharacteristic = service.getCharacteristic(D_TIME_WRITABLE_CHARACTERISTIC_UUID);
mSetATempCharacteristic = service.getCharacteristic(A_TEMP_WRITABLE_CHARACTERISTIC_UUID);
mSetATimeCharacteristic = service.getCharacteristic(A_TIME_WRITABLE_CHARACTERISTIC_UUID);
mSetETempCharacteristic = service.getCharacteristic(E_TEMP_WRITABLE_CHARACTERISTIC_UUID);
mSetETimeCharacteristic = service.getCharacteristic(E_TIME_WRITABLE_CHARACTERISTIC_UUID);
mSetLTempCharacteristic = service.getCharacteristic(L_TEMP_WRITABLE_CHARACTERISTIC_UUID);
mSetLTimeCharacteristic = service.getCharacteristic(L_TIME_WRITABLE_CHARACTERISTIC_UUID);
mSetOTempCharacteristic = service.getCharacteristic(O_TEMP_WRITABLE_CHARACTERISTIC_UUID);
mSetOTimeCharacteristic = service.getCharacteristic(O_TIME_WRITABLE_CHARACTERISTIC_UUID);
mSetNPcrCCharacteristic = service.getCharacteristic(N_PCR_C_WRITABLE_CHARACTERISTIC_UUID);
mAmpStartStopCharacteristic = service.getCharacteristic(AMP_WRITABLE_CHARACTERISTIC_UUID);
}
final BluetoothGattService otherService = gatt.getService(OTHER_SERVICE_UUID);
if (otherService != null) {
mDeviceNameCharacteristic = otherService.getCharacteristic(READABLE_CHARACTERISTIC_UUID);
}
return mReadBlockTempCharacteristic != null && mSetDTempCharacteristic != null && mSetDTimeCharacteristic!= null && mSetATempCharacteristic != null && mSetATimeCharacteristic!= null && mSetETempCharacteristic != null && mSetLTempCharacteristic != null && mSetETimeCharacteristic!= null && mSetOTempCharacteristic != null && mSetLTimeCharacteristic!= null && mSetOTimeCharacteristic!= null && mSetNPcrCCharacteristic!= null && mAmpStartStopCharacteristic != null ;
}
@Override
protected boolean isOptionalServiceSupported(@NonNull final BluetoothGatt gatt) {
// Initialize Battery characteristic
super.isOptionalServiceSupported(gatt);
// TODO If there are some optional characteristics, initialize them there.
final BluetoothGattService service = gatt.getService(SERVICE_UUID);
if (service != null) {
mOptionalCharacteristic = service.getCharacteristic(READABLE_CHARACTERISTIC_UUID);
}
return mOptionalCharacteristic != null;
}
@Override
protected void onDeviceDisconnected() {
// Release Battery Service
super.onDeviceDisconnected();
// TODO Release references to your characteristics.
mRequiredCharacteristic = null;
mDeviceNameCharacteristic = null;
mOptionalCharacteristic = null;
}
@Override
protected void onDeviceReady() {
super.onDeviceReady();
// Initialization is now ready.
// The service or activity has been notified with no.nordicsemi.android.ble.BatteryManagerCallbacks#onDeviceReady().
// TODO Do some extra logic here, of remove onDeviceReady().
// Device is ready, let's read something here. Usually there is nothing else to be done
// here, as all had been done during initialization.
readCharacteristic(mReadBlockTempCharacteristic)
.with((device, data) -> {
// Characteristic value has been read
// Let's do some magic with it.
if (data.size() > 0) {
final Integer value = data.getIntValue(Data.FORMAT_UINT8, 0);
log(LogContract.Log.Level.APPLICATION, "Value '" + value + "' has been read!");
} else {
log(Log.WARN, "Value is empty!");
}
})
.enqueue();
}
};
// TODO Define manager's API
*/
/**
* This method will write important data to the device.
*
* @param parameter parameter to be written.
*//*
//Heating Switch
void heatingSwitch(int state) {
log(Log.WARN, "Write time duration \"" + state + "\"");
//final byte time_in_byte = time_duration.getBytes()[0];
final byte state_in_byte = (byte) state;
writeCharacteristic(mAmpStartStopCharacteristic, Data.opCode(state_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Heating State"))
.split()
.enqueue();
}
//Set Time
void sendDTime(int d_time) {
log(Log.WARN, "Write D Time Duration \"" + d_time + "\"");
final byte d_time_in_byte = (byte) d_time;
writeCharacteristic(mSetDTimeCharacteristic, Data.opCode(d_time_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Time"))
.split()
.enqueue();
}
void sendATime(int a_time) {
log(Log.WARN, "Write A Time Duration \"" + a_time + "\"");
final byte a_time_in_byte = (byte) a_time;
writeCharacteristic(mSetATimeCharacteristic, Data.opCode(a_time_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Time"))
.split()
.enqueue();
}
void sendLTime(int l_time) {
log(Log.WARN, "Write A Time Duration \"" + l_time + "\"");
final byte a_time_in_byte = (byte) l_time;
writeCharacteristic(mSetLTimeCharacteristic, Data.opCode(a_time_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Time"))
.split()
.enqueue();
}
void sendOTime(int o_time) {
log(Log.WARN, "Write A Time Duration \"" + o_time + "\"");
final byte a_time_in_byte = (byte) o_time;
writeCharacteristic(mSetOTimeCharacteristic, Data.opCode(a_time_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Time"))
.split()
.enqueue();
}
void sendETime(int e_time) {
log(Log.WARN, "Write E Time Duration \"" + e_time + "\"");
final byte e_time_in_byte = (byte) e_time;
writeCharacteristic(mSetETimeCharacteristic, Data.opCode(e_time_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Time"))
.split()
.enqueue();
}
//Set Temp
void sendDTemp(int d_temp) {
log(Log.WARN, "Write D temp \"" + d_temp + "\"");
final byte d_temp_in_byte = (byte) d_temp;
writeCharacteristic(mSetDTempCharacteristic, Data.opCode(d_temp_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Temp"))
.split()
.enqueue();
}
void sendLTemp(int l_temp) {
log(Log.WARN, "Write D temp \"" + l_temp + "\"");
final byte d_temp_in_byte = (byte) l_temp;
writeCharacteristic(mSetLTempCharacteristic, Data.opCode(d_temp_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Temp"))
.split()
.enqueue();
}
void sendOTemp(int o_temp) {
log(Log.WARN, "Write D temp \"" + o_temp + "\"");
final byte d_temp_in_byte = (byte) o_temp;
writeCharacteristic(mSetOTempCharacteristic, Data.opCode(d_temp_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Temp"))
.split()
.enqueue();
}
void sendATemp(int a_temp) {
log(Log.WARN, "Write A temp \"" + a_temp + "\"");
final byte a_temp_in_byte = (byte) a_temp;
writeCharacteristic(mSetATempCharacteristic, Data.opCode(a_temp_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Temp"))
.split()
.enqueue();
}
void sendETemp(int e_temp) {
log(Log.WARN, "Write E temp \"" + e_temp + "\"");
final byte e_temp_in_byte = (byte) e_temp;
writeCharacteristic(mSetETempCharacteristic, Data.opCode(e_temp_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Temp"))
.split()
.enqueue();
}
void sendNPcrC(int n_pcr_c) {
log(Log.WARN, "Write E temp \"" + n_pcr_c + "\"");
final byte n_pcr_c_in_byte = (byte) n_pcr_c;
writeCharacteristic(mSetNPcrCCharacteristic, Data.opCode(n_pcr_c_in_byte))
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
"\"" + data.size() + "\" Set Temp"))
.split()
.enqueue();
}
}
*/

View File

@@ -0,0 +1,150 @@
package no.Reader.android.iisc.Reader;
import android.Manifest;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Environment;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.widget.AppCompatCheckBox;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.io.File;
import no.Reader.android.iisc.R;
public class TestDetails extends NavigationTop {
private EditText user_name,test_id, per,volume;
private Button Createtest;
int i=0;
File filePath=null;
private AppCompatCheckBox checkbox;
String flag="false",username,testid,percentage,vol;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater inflater = (LayoutInflater) this
.getSystemService(LAYOUT_INFLATER_SERVICE);
View contentView = inflater.inflate(R.layout.testdetails, null, false);
draw.addView(contentView, 0);
/* LayoutInflater inflater = (LayoutInflater) this
.getSystemService(LAYOUT_INFLATER_SERVICE);
View contentView = inflater.inflate(R.layout.activity_about, null, false);
*/
// setContentView(R.layout.testdetails);
if(ContextCompat.checkSelfPermission(TestDetails.this, Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(TestDetails.this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},23);
}
user_name=findViewById(R.id.username);
test_id=findViewById(R.id.test_id);
per=findViewById(R.id.percent);
volume=findViewById(R.id.volume);
Createtest=findViewById(R.id.createtest);
checkbox = (AppCompatCheckBox) findViewById(R.id.positivesample);
checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
if (isChecked) {
i=1;
flag="true";
// show password
}
}
});
Createtest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (ContextCompat.checkSelfPermission(TestDetails.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(TestDetails.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 23);
}
username = user_name.getText().toString();
percentage = per.getText().toString();
testid = test_id.getText().toString();
File filePath1 = new File(Environment.getExternalStorageDirectory() + "/" + testid + ".xls");
vol = volume.getText().toString();
if (username.equals("") || percentage.equals("") || testid.equals("") || vol.equals("")) {
Toast.makeText(TestDetails.this, "Please fill all fields", Toast.LENGTH_SHORT).show();
} else if (Integer.parseInt(String.valueOf(percentage)) > 100 || Integer.parseInt(String.valueOf(percentage)) < 1) {
Toast.makeText(TestDetails.this, "Enter a valid Percentage Data", Toast.LENGTH_SHORT).show();
} else if (Integer.parseInt(String.valueOf(percentage)) > 100 || Integer.parseInt(String.valueOf(percentage)) < 1) {
Toast.makeText(TestDetails.this, "Enter a valid Percentage Data", Toast.LENGTH_SHORT).show();
} else if (filePath1.exists()) {
Toast.makeText(TestDetails.this, "File With this testid already exists please fill other test id", Toast.LENGTH_SHORT).show();
} else {
if (i == 1) {
Intent intent = new Intent(TestDetails.this, TemplateActivity.class);
SharedPreferences preferences = getSharedPreferences("TestEntry", MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
// editor.putString(Name, phonenum);
editor.putString("testid", testid);
editor.putString("username", username);
editor.putString("percentage", percentage);
editor.putString("internal", flag);
editor.putString("volume", vol);
editor.commit();
startActivity(intent);
} else {
Intent intent = new Intent(TestDetails.this, TemplateActivity1.class);
SharedPreferences preferences = getSharedPreferences("TestEntry", MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
// editor.putString(Name, phonenum);
editor.putString("testid", testid);
editor.putString("username", username);
editor.putString("percentage", percentage);
editor.putString("internal", flag);
editor.putString("volume", vol);
editor.commit();
startActivity(intent);
}
}
}
});
}
}

View File

@@ -0,0 +1,48 @@
package no.Reader.android.iisc.Reader;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import no.Reader.android.iisc.R;
import no.Reader.android.iisc.Reader.Interface.ItemClickListner;
public class TestViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
public TextView txtpatientid, txttimestamp,nikshay,iconfinder,txtsampletype;
public ImageView imageView;
public ItemClickListner listner;
public TestViewHolder(View itemView)
{
super(itemView);
imageView = (ImageView) itemView.findViewById(R.id.icon_profile);
iconfinder=(TextView) itemView.findViewById(R.id.icon_text);
txtpatientid = (TextView) itemView.findViewById(R.id.patient_Id);
txtsampletype = (TextView) itemView.findViewById(R.id.sample_type);
txttimestamp=itemView.findViewById(R.id.timestamp);
nikshay=itemView.findViewById(R.id.nikshayid);
//txtProductDescription= (TextView) itemView.findViewById(R.id.switch_toggle);
}
public void setItemClickListner(ItemClickListner listner)
{
this.listner = listner;
}
@Override
public void onClick(View view)
{
listner.onClick(view, getAdapterPosition(), false);
}
}

View File

@@ -0,0 +1,293 @@
package no.Reader.android.iisc.Reader;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.os.Bundle;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.github.mikephil.charting.charts.BarChart;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.utils.ColorTemplate;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import no.Reader.android.iisc.R;
public class Try1 extends AppCompatActivity {
String TAG ="main";
private TextView textView;
BarChart barChart;
ArrayList<String> adcVal;
ArrayList<String> samplelabel;
ArrayList<BarEntry> entries = new ArrayList<>();
ArrayList<String> labels = new ArrayList<String>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_try1);
textView = findViewById(R.id.textview);
barChart = (BarChart) findViewById(R.id.barchart);
if(ContextCompat.checkSelfPermission(Try1.this, Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(Try1.this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},23);
}
readExcelFileFromAssets();
}
public void readExcelFileFromAssets() {
if(ContextCompat.checkSelfPermission(Try1.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(Try1.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},23);
}
try {
InputStream myInput;
Context context = null;
File filePath1 = new File(Environment.getExternalStorageDirectory() + "/" +"do.xls");
File file = new File(getApplicationContext().getExternalFilesDir(null), "do.xls");
/* fis = new FileInputStream(file);
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
File sdcard = Environment.getExternalStorageDirectory();
File file = new File("/sdcard/Demo.xls");
if(file.exists()){
*/
if(filePath1.exists()){
Toast.makeText(Try1.this, "id exist", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(Try1.this, "nooo", Toast.LENGTH_SHORT).show();
}
myInput = new FileInputStream(filePath1);
// initialize asset manager
/* AssetManager assetManager = getAssets();
// open excel sheet
myInput = assetManager.open("file_example_XLS_50.xls");
*/ // Create a POI File System object
POIFSFileSystem myFileSystem = new POIFSFileSystem(myInput);
// Create a workbook using the File System
HSSFWorkbook myWorkBook = new HSSFWorkbook(myFileSystem);
// Get the first sheet from workbook
HSSFSheet mySheet = myWorkBook.getSheetAt(0);
int rowCount = mySheet.getLastRowNum();
// We now need something to iterate through the cells.
Iterator<Row> rowIter = mySheet.rowIterator();
int[][] arr = new int[0][];
for(int i=11;i<=rowCount;i++)
{
Row row = mySheet.getRow(i);
//Create a loop to print cell values in a row
int j =1;
//Print Excel data in console
labels.add(String.valueOf(row.getCell(j).getStringCellValue()));
samplelabel.add(String.valueOf(row.getCell(j).getStringCellValue()));
int k=3;
entries.add(new BarEntry(Float.parseFloat(String.valueOf(i)), i-11));
System.out.println();
}
BarDataSet bardataset = new BarDataSet(entries, "Result");
BarData data = new BarData(labels, bardataset);
barChart.setData(data); // set the data and list of labels into chart
barChart.setDescription("Bar Graph for Result"); // set the description
bardataset.setColors(ColorTemplate.COLORFUL_COLORS);
barChart.animateY(1000);
/* int rowno =0;
textView.append("\n");
while (rowIter.hasNext()) {
Log.e(TAG, " row no "+ rowno );
HSSFRow myRow = (HSSFRow) rowIter.next();
if(rowno !=0) {
Iterator<Cell> cellIter = myRow.cellIterator();
Log.e(TAG, " Cell "+ myRow.cellIterator() );
int colno =0;
String sno="";
String date="";
String det="";
int value = 0;
while (cellIter.hasNext()) {
HSSFCell myCell = (HSSFCell) cellIter.next();
if (colno==0){
value= Integer.parseInt(String.valueOf(myCell));
Log.e(TAG, " Cell value 1 "+ value );
}
if (colno==1){
sno = myCell.toString();
Log.e(TAG, " Cell value 2 "+ sno );
}else if (colno==2){
date = myCell.toString();
Log.e(TAG, " Cell value 3 "+ date );
}
colno++;
Log.e(TAG, " Index :" + myCell.getColumnIndex() + " -- " + myCell.toString());
}*/
} catch (Exception e) {
Log.e(TAG, "error "+ e.toString());
}
change();
}
private void change()
{
try {
InputStream myInput;
File filePath1 = new File(Environment.getExternalStorageDirectory() + "/" +"file_example_XLS_50.xls");
myInput = new FileInputStream(filePath1);
Workbook workbook = WorkbookFactory.create(myInput);
Sheet sheet = workbook.getSheetAt(0);
Object[][] bookData = {
{51,"love1", "Chad Fowler", "Chad Fowler","Chad Fowler",45,"fff",5555},
{51,"love2", "Chad Fowler", "Chad Fowler","Chad Fowler",45,"fff",5555},
{51,"Thggggg", "Chad Fowler", "Chad Fowler","Chad Fowler",45,"fff",5555},
{51,"The Passionate Program", "Chad Fowler", "Chad Fowler","Chad Fowler",45,"fff",5555},
};
int rowCount = sheet.getLastRowNum();
for (Object[] aBook : bookData) {
Row row = sheet.createRow(++rowCount);
int columnCount = 0;
Cell cell = row.createCell(columnCount);
cell.setCellValue(rowCount);
for (Object field : aBook) {
cell = row.createCell(++columnCount);
if (field instanceof String) {
cell.setCellValue((String) field);
} else if (field instanceof Integer) {
cell.setCellValue((Integer) field);
}
}
}
myInput.close();
FileOutputStream outputStream = new FileOutputStream(filePath1);
workbook.write(outputStream);
workbook.close();
outputStream.close();
} catch (IOException | EncryptedDocumentException ex) {
ex.printStackTrace();
}
}
}

View File

@@ -0,0 +1,155 @@
package no.Reader.android.iisc.Reader.VerifyOTP;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.chaos.view.PinView;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.FirebaseException;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.PhoneAuthCredential;
import com.google.firebase.auth.PhoneAuthOptions;
import com.google.firebase.auth.PhoneAuthProvider;
import java.util.concurrent.TimeUnit;
import no.Reader.android.iisc.R;
import no.Reader.android.iisc.Reader.CreatePassword;
public class VerifyOtp extends AppCompatActivity {
private String verificationid;
private FirebaseAuth mAuth;
private Button nextactivity;
private ProgressBar progressBar;
PinView pinFromUser;
private EditText editText;
String codeBySystem;
String address,name, state , city ,pincode,phonenumber,password2,num1,phonenumberke;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_verify__o_t_p);
pinFromUser = findViewById(R.id.firstPinView);
nextactivity = findViewById(R.id.buttonSignIn);
mAuth = FirebaseAuth.getInstance();
String phonenumberk = getIntent().getStringExtra("numberwithcode");
phonenumberke = getIntent().getStringExtra("mobile");
phonenumber = phonenumberk;
name = getIntent().getStringExtra("username");
sendVerificationCode(phonenumber);
findViewById(R.id.buttonSignIn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String code = pinFromUser.getText().toString().trim();
if ((code.isEmpty() || code.length() < 6)) {
editText.setError("Enter code...");
editText.requestFocus();
return;
}
verifyCode(code);
}
});
}
private void verifyCode(String code){
PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationid, code);
signInWithCredential(credential);
}
private void signInWithCredential(PhoneAuthCredential credential) {
mAuth.signInWithCredential(credential)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
Intent intent = new Intent(VerifyOtp.this, CreatePassword.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.putExtra("mobile", phonenumberke);
intent.putExtra("username", name);
startActivity(intent);
} else {
// Toast.makeText(VerifyOTP.this, task.getException().getMessage(), Toast.LENGTH_LONG).show();
}
}
});
}
private void sendVerificationCode(String number){
PhoneAuthOptions options =
PhoneAuthOptions.newBuilder(mAuth)
.setPhoneNumber(number) // Phone number to verify
.setTimeout(60L, TimeUnit.SECONDS) // Timeout and unit
.setActivity(this) // Activity (for callback binding)
.setCallbacks(mCallBack) // OnVerificationStateChangedCallbacks
.build();
PhoneAuthProvider.verifyPhoneNumber(options);
}
private PhoneAuthProvider.OnVerificationStateChangedCallbacks
mCallBack = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
@Override
public void onCodeSent(String s, PhoneAuthProvider.ForceResendingToken forceResendingToken) {
super.onCodeSent(s, forceResendingToken);
verificationid = s;
}
@Override
public void onVerificationCompleted(PhoneAuthCredential phoneAuthCredential) {
String code = phoneAuthCredential.getSmsCode();
if (code != null){
// progressBar.setVisibility(View.VISIBLE);
pinFromUser.setText(code);
verifyCode(code);
}
}
@Override
public void onVerificationFailed(FirebaseException e) {
Toast.makeText(VerifyOtp.this, e.getMessage(),Toast.LENGTH_LONG).show();
}
};
}

View File

@@ -0,0 +1,154 @@
package no.Reader.android.iisc.Reader.VerifyOTP;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.chaos.view.PinView;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.FirebaseException;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.PhoneAuthCredential;
import com.google.firebase.auth.PhoneAuthOptions;
import com.google.firebase.auth.PhoneAuthProvider;
import java.util.concurrent.TimeUnit;
import no.Reader.android.iisc.R;
import no.Reader.android.iisc.Reader.ForgetPassword;
import no.Reader.android.iisc.Reader.ForgetPasswordReset;
public class VerifyOtpForgetPassword extends AppCompatActivity {
private String verificationid;
private FirebaseAuth mAuth;
private Button nextactivity;
private ProgressBar progressBar;
PinView pinFromUser;
private EditText editText;
String codeBySystem;
String address,name, state , city ,pincode,phonenumber,password2,num1,mobile;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_verify__o_t_p);
pinFromUser = findViewById(R.id.firstPinView);
nextactivity = findViewById(R.id.buttonSignIn);
mAuth = FirebaseAuth.getInstance();
String phonenumberk = getIntent().getStringExtra("mobilecode");
phonenumber = phonenumberk;
mobile= getIntent().getStringExtra("mobile");
sendVerificationCode(phonenumber);
findViewById(R.id.buttonSignIn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String code = pinFromUser.getText().toString().trim();
if ((code.isEmpty() || code.length() < 6)) {
editText.setError("Enter code...");
editText.requestFocus();
return;
}
verifyCode(code);
}
});
}
private void verifyCode(String code){
PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationid, code);
signInWithCredential(credential);
}
private void signInWithCredential(PhoneAuthCredential credential) {
mAuth.signInWithCredential(credential)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
Intent intent = new Intent(VerifyOtpForgetPassword.this, ForgetPasswordReset.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.putExtra("mobile", mobile);
startActivity(intent);
} else {
Toast.makeText(VerifyOtpForgetPassword.this, task.getException().getMessage(), Toast.LENGTH_LONG).show();
}
}
});
}
private void sendVerificationCode(String number){
PhoneAuthOptions options =
PhoneAuthOptions.newBuilder(mAuth)
.setPhoneNumber(number) // Phone number to verify
.setTimeout(60L, TimeUnit.SECONDS) // Timeout and unit
.setActivity(this) // Activity (for callback binding)
.setCallbacks(mCallBack) // OnVerificationStateChangedCallbacks
.build();
PhoneAuthProvider.verifyPhoneNumber(options);
}
private PhoneAuthProvider.OnVerificationStateChangedCallbacks
mCallBack = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
@Override
public void onCodeSent(String s, PhoneAuthProvider.ForceResendingToken forceResendingToken) {
super.onCodeSent(s, forceResendingToken);
verificationid = s;
}
@Override
public void onVerificationCompleted(PhoneAuthCredential phoneAuthCredential) {
String code = phoneAuthCredential.getSmsCode();
if (code != null){
// progressBar.setVisibility(View.VISIBLE);
pinFromUser.setText(code);
verifyCode(code);
}
}
@Override
public void onVerificationFailed(FirebaseException e) {
Toast.makeText(VerifyOtpForgetPassword.this, e.getMessage(),Toast.LENGTH_LONG).show();
}
};
@Override
public void onBackPressed() {
Intent intent = new Intent(VerifyOtpForgetPassword.this, ForgetPassword.class);
startActivity(intent);
}
}

View File

@@ -0,0 +1,429 @@
package no.Reader.android.iisc.Reader;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import android.Manifest;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.StrictMode;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.ImageButton;
import android.widget.TextView;
import com.github.mikephil.charting.charts.BarChart;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.utils.ColorTemplate;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import no.Reader.android.iisc.R;
public class ViewGraph extends AppCompatActivity {
private TextView result, textadc;
String value1_1, value1_2, value1_3, value2_1, value2_2, value2_3, value3_1, value3_2, value3_3, testid, username, percentage, internal, samplename, volume;
BarChart barChart;
BarData barData;
String string1,string2,string3,string4,string5,string6,string7,string8,string9,number,logi,lati;
private ProgressDialog loadingBar;
private String TestRandomKey, downloadImageUrl1,saveCurrentDate, saveCurrentTime;
Uri path;
File filePath3 = null;
private DatabaseReference TestRef;
File filePath1 = null;
File filePath = null;
String directory_path;
int love = 0;
BarDataSet barDataSet;
ArrayList barEntries;
int positive, negative, sample, positive_value, negative_value, sample_value, sampleraw, sampleraw1, sampleraw2;
int delta = 0;
String resultdata;
int count = 0;
ImageButton dowbloadd;
ImageButton save;
String date, time;
private String TestID = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_graph);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
/* BottomNavigationView bottomNav = findViewById(R.id.bottom_navigation);
bottomNav.setOnNavigationItemSelectedListener(navListener);
*/ StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
builder.detectFileUriExposure();
barChart = (BarChart) findViewById(R.id.barchart);
loadingBar = new ProgressDialog(this);
textadc = findViewById(R.id.textadc);
testid = getIntent().getStringExtra("pid");
Log.e("main", "error id "+TestID);
SharedPreferences preferences689 = getSharedPreferences("PhoneBook_number", MODE_PRIVATE);
number = preferences689.getString("Phone", null);
Log.e("main", "error "+number);
TestRef = FirebaseDatabase.getInstance().getReference().child("Test_Data").child(number);
/* LayoutInflater inflater = (LayoutInflater) this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View contentView = inflater.inflate(R.layout.activity_feature_template3, null, false);
draw.addView(contentView, 0);
*/
if (ContextCompat.checkSelfPermission(ViewGraph.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(ViewGraph.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 23);
} else {
readExcelFileFromAssets();
}
}
/* private BottomNavigationView.OnNavigationItemSelectedListener navListener =
new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_result:
Intent intent=new Intent(ViewGraph.this, ViewSamples.class);
intent.putExtra("pid",testid);
startActivity(intent);
break;
case R.id.nav_home:
Intent intent2 = new Intent(ViewGraph.this, MainActivity.class);
startActivity(intent2);
break;
case R.id.nav_excel:
shared();
}
return true;
}
};
*/
public void readExcelFileFromAssets() {
if (ContextCompat.checkSelfPermission(ViewGraph.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(ViewGraph.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 23);
}
try {
InputStream myInput;
Context context = null;
String directory_path = Environment.getExternalStorageDirectory().getPath() + "/Test Report/";
String targetPdf = directory_path + "Report_" + testid + ".xls";
filePath1 = new File(targetPdf);
if (filePath1.exists()) {
} else {
// Toast.makeText(ViewGraph.this, "nooo", Toast.LENGTH_SHORT).show();
}
myInput = new FileInputStream(filePath1);
POIFSFileSystem myFileSystem = new POIFSFileSystem(myInput);
// Create a workbook using the File System
HSSFWorkbook myWorkBook = new HSSFWorkbook(myFileSystem);
ArrayList<BarEntry> entries = new ArrayList<>();
BarDataSet bardataset = new BarDataSet(entries, "Result");
ArrayList<String> labels = new ArrayList<String>();
// Get the first sheet from workbook
HSSFSheet mySheet = myWorkBook.getSheetAt(0);
// We now need something to iterate through the cells.
Iterator<Row> rowIter = mySheet.rowIterator();
int rowCount = mySheet.getLastRowNum();
int rowno = 0;
while (rowIter.hasNext()) {
HSSFRow myRow = (HSSFRow) rowIter.next();
// 5
if (rowno != 0 && rowno > 5) {
if (rowno == rowCount - 1) {
Iterator<Cell> cellIter = myRow.cellIterator();
int colno = 0;
String sno = "", date = "", det = "", vald = "", adcvals = "", result = "";
while (cellIter.hasNext()) {
HSSFCell myCell = (HSSFCell) cellIter.next();
if (colno == 0) {
sno = myCell.toString();
} else if (colno == 1) {
date = myCell.toString();
} else if (colno == 2) {
adcvals = myCell.toString();
} else if (colno == 3) {
det = myCell.toString();
} else if (colno == 4) {
vald = myCell.toString();
} else if (colno == 5) {
result = myCell.toString();
}
colno++;
}
if (!result.contains("Positive")) {
// Toast.makeText(ViewGraph.this, "positive " + result + " File ", Toast.LENGTH_LONG).show();
} else {
// Toast.makeText(ViewGraph.this, "positive " + result + " File ", Toast.LENGTH_LONG).show();
bardataset.setColors(ColorTemplate.COLORFUL_COLORS);
}
if (!det.equals("-")) {
entries.add(new BarEntry(Float.parseFloat((det)), rowno - 6));
labels.add(date + "(" + result + ")");
} else {
entries.add(new BarEntry(Float.parseFloat(String.valueOf((0))), rowno - 6));
labels.add(date + "(" + result + ")");
}
textadc.append("Test ID : " +testid+ "\n");
} else {
Iterator<Cell> cellIter = myRow.cellIterator();
int colno = 0;
String sno = "", date = "", det = "", result1 = "";
while (cellIter.hasNext()) {
HSSFCell myCell = (HSSFCell) cellIter.next();
if (colno == 0) {
sno = myCell.toString();
} else if (colno == 1) {
date = myCell.toString();
} else if (colno == 3) {
det = myCell.toString();
} else if (colno == 5) {
result1 = myCell.toString();
}
colno++;
}
if (!det.equals("-")) {
entries.add(new BarEntry(Float.parseFloat((det)), rowno - 6));
labels.add(date + "(" + result1 + ")");
} else {
entries.add(new BarEntry(Float.parseFloat(String.valueOf((0))), rowno - 6));
labels.add(date + "(" + result1 + ")");
}
}
}
rowno++;
}
BarData data = new BarData(labels, bardataset);
barChart.setData(data); // set the data and list of labels into chart
barChart.setDescription("Bar Graph for Result"); // set the description
barChart.animateY(1000);
} catch (Exception e) {
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu1, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_samples:
Intent intent=new Intent(ViewGraph.this, ViewSamples.class);
intent.putExtra("pid",testid);
startActivity(intent);
return true;
case R.id.nav_home:
Intent intent2 = new Intent(ViewGraph.this, MainActivity.class);
startActivity(intent2);
return true;
case R.id.nav_excel:
shared();
return true;
case R.id.nav_share:
srk();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void srk()
{
if(ContextCompat.checkSelfPermission(ViewGraph.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(ViewGraph.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},23);
}
else
{
String directory_path = Environment.getExternalStorageDirectory().getPath() + "/Test Report/";
String pat= directory_path + "Report_" + testid + ".xls";
File file = new File(pat);
Intent intent=new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT,"Report");
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N) {
Uri path= FileProvider.getUriForFile(ViewGraph.this,"no.Reader.android.iisc.fileprovider",file);
intent.putExtra(Intent.EXTRA_STREAM,path);
}
else{
intent.putExtra(Intent.EXTRA_STREAM,Uri.fromFile(file));
}
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(path, "application/vnd.ms-excel");
startActivity(intent);
}
}
public void shared() {
String directory_path = Environment.getExternalStorageDirectory().getPath() + "/Test Report/";
String pat= directory_path + "Report_" + testid + ".xls";
Intent intent = new Intent(Intent.ACTION_VIEW);
File file = new File(pat);
Uri path = FileProvider.getUriForFile(getApplicationContext(), "no.Reader.android.iisc.fileprovider", file);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(path, "application/vnd.ms-excel");
startActivity(intent);
}
}

View File

@@ -0,0 +1,548 @@
package no.Reader.android.iisc.Reader;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import android.Manifest;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.StrictMode;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.ImageButton;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import com.github.mikephil.charting.charts.BarChart;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.google.firebase.database.DatabaseReference;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import no.Reader.android.iisc.R;
public class ViewSamples extends AppCompatActivity {
private TextView result, textadc;
String value1_1, value1_2, value1_3, value2_1, value2_2, value2_3, value3_1, value3_2, value3_3, testid, username, percentage, internal, samplename, volume;
BarChart barChart;
Uri path;
BarData barData;
String string1,string2,string3,string4,string5,string6,string7,string8,string9,number,logi,lati;
private ProgressDialog loadingBar;
private String TestRandomKey, downloadImageUrl1,saveCurrentDate, saveCurrentTime;
File filePath3 = null;
private DatabaseReference TestRef;
File filePath1 = null;
File filePath = null;
String directory_path;
int love = 0;
BarDataSet barDataSet;
ArrayList barEntries;
int positive, negative, sample, positive_value, negative_value, sample_value, sampleraw, sampleraw1, sampleraw2;
int delta = 0;
String resultdata;
int count = 0;
ImageButton dowbloadd;
ImageButton share;
String date, time;
private String TestID = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_samples);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// BottomNavigationView bottomNav = findViewById(R.id.bottom_navigation);
// bottomNav.setOnNavigationItemSelectedListener(navListener);
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
builder.detectFileUriExposure();
loadingBar = new ProgressDialog(this);
testid = getIntent().getStringExtra("pid");
Log.e("TestIdll",testid);
textadc = findViewById(R.id.textadc);
/* share=findViewById(R.id.share);
share.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(ContextCompat.checkSelfPermission(ViewSamples.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(ViewSamples.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},23);
}
else
{
String directory_path = Environment.getExternalStorageDirectory().getPath() + "/Test Report/";
String pat= directory_path + "Report_" + testid + ".xls";
File file = new File(pat);
Intent intent=new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT,"Report");
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N) {
Uri path= FileProvider.getUriForFile(ViewSamples.this,"no.Reader.android.iisc.fileprovider",file);
intent.putExtra(Intent.EXTRA_STREAM,path);
}
else{
intent.putExtra(Intent.EXTRA_STREAM,Uri.fromFile(file));
}
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(path, "application/vnd.ms-excel");
startActivity(intent);
}
}
});
*/ textadc.append("Test ID : " +testid+ "\n");
/* LayoutInflater inflater = (LayoutInflater) this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View contentView = inflater.inflate(R.layout.activity_feature_template3, null, false);
draw.addView(contentView, 0);
*/
if(ContextCompat.checkSelfPermission(ViewSamples.this, Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(ViewSamples.this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},23);
}
// init("1","1","1","1","1","1");
readExcelFileFromAssets();
}
public void readExcelFileFromAssets() {
if(ContextCompat.checkSelfPermission(ViewSamples.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(ViewSamples.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},23);
}
try {
InputStream myInput;
Context context = null;
String directory_path = Environment.getExternalStorageDirectory().getPath() + "/Test Report/";
String targetPdf = directory_path + "Report_" +testid+".xls";
filePath1 = new File(targetPdf);
File file = new File(getApplicationContext().getExternalFilesDir(null), "78.xls");
/* fis = new FileInputStream(file);
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
File sdcard = Environment.getExternalStorageDirectory();
File file = new File("/sdcard/Demo.xls");
if(file.exists()){
*/
if(filePath1.exists()){
// Toast.makeText(ViewSamples.this, "id exist", Toast.LENGTH_SHORT).show();
}
else
{
// Toast.makeText(ViewSamples.this, "nooo", Toast.LENGTH_SHORT).show();
}
myInput = new FileInputStream(filePath1);
// initialize asset manager
/* AssetManager assetManager = getAssets();
// open excel sheet
myInput = assetManager.open("file_example_XLS_50.xls");
*/ // Create a POI File System object
POIFSFileSystem myFileSystem = new POIFSFileSystem(myInput);
// Create a workbook using the File System
HSSFWorkbook myWorkBook = new HSSFWorkbook(myFileSystem);
// Get the first sheet from workbook
HSSFSheet mySheet = myWorkBook.getSheetAt(0);
// We now need something to iterate through the cells.
Iterator<Row> rowIter = mySheet.rowIterator();
int rowno =0;
// textView.append("\n");
while (rowIter.hasNext()) {
HSSFRow myRow = (HSSFRow) rowIter.next();
if(rowno !=0) {
Iterator<Cell> cellIter = myRow.cellIterator();
int colno =0;
String sno="", sampletype="", adcval="",delta="",result="",avgadc="";
while (cellIter.hasNext()) {
HSSFCell myCell = (HSSFCell) cellIter.next();
if (colno==0){
sno = myCell.toString();
}else if (colno==1){
sampletype = myCell.toString();
}else if (colno==2){
adcval= myCell.toString();
}
else if (colno==3){
avgadc= myCell.toString();
}
else if (colno==4){
delta= myCell.toString();
}
else if (colno==5){
result= myCell.toString();
}
colno++;
}
// init1(sno);
Log.e("s",sno);
init(sno,sampletype,adcval,avgadc,delta,result);
// textView.append( sno + " "+ sampletype+" "+ adcval+" "+avgadc+" "+delta+" "+result+ " "+"\n");
}
rowno++;
}
} catch (Exception e) {
}
}
public void init(String sno ,String sampletype,String adcval,String avgadc ,String delta,String result) {
TableLayout stk = (TableLayout) findViewById(R.id.table_main);
/* TableRow tbrow0 = new TableRow(this);
TextView tv0 = new TextView(this);
tv0.setText(" Sl.No ");
tv0.setTextColor(Color.WHITE);
tbrow0.addView(tv0);
TextView tv1 = new TextView(this);
tv1.setText(" Product ");
tv1.setTextColor(Color.WHITE);
tbrow0.addView(tv1);
TextView tv2 = new TextView(this);
tv2.setText(" Unit Price ");
tv2.setTextColor(Color.WHITE);
tbrow0.addView(tv2);
TextView tv3 = new TextView(this);
tv3.setText(" Stock Remaining ");
tv3.setTextColor(Color.WHITE);
tbrow0.addView(tv3);
stk.addView(tbrow0);*/
TableRow tbrow = new TableRow(this);
TextView t1v = new TextView(this);
t1v.setText("" + sno +" ");
t1v.setGravity(Gravity.CENTER);
tbrow.addView(t1v);
TextView t2v = new TextView(this);
t2v.setText(sampletype+" ");
t2v.setGravity(Gravity.CENTER);
tbrow.addView(t2v);
TextView t3v = new TextView(this);
t3v.setText(adcval+" ");
t3v.setGravity(Gravity.CENTER);
tbrow.addView(t3v);
TextView t4v = new TextView(this);
t4v.setText(avgadc+" ");
t4v.setGravity(Gravity.CENTER);
tbrow.addView(t4v);
TextView t5v = new TextView(this);
t5v.setText(delta+" ");
t5v.setGravity(Gravity.CENTER);
tbrow.addView(t5v);
TextView t6v = new TextView(this);
t6v.setText(" "+result);
t6v.setGravity(Gravity.CENTER);
tbrow.addView(t6v);
stk.addView(tbrow);
/* TableRow tbrow0 = new TableRow(this);
TextView tv0 = new TextView(this);
tv0.setText(" Sl.No ");
tv0.setTextColor(Color.WHITE);
tbrow0.addView(tv0);
TextView tv1 = new TextView(this);
tv1.setText(" Product ");
tv1.setTextColor(Color.WHITE);
tbrow0.addView(tv1);
TextView tv2 = new TextView(this);
tv2.setText(" Unit Price ");
tv2.setTextColor(Color.WHITE);
tbrow0.addView(tv2);
TextView tv3 = new TextView(this);
tv3.setText(" Stock Remaining ");
tv3.setTextColor(Color.WHITE);
tbrow0.addView(tv3);
stk.addView(tbrow0);*/
}
public void init1(String sno ) {
TableLayout stk = (TableLayout) findViewById(R.id.table_main);
TableRow tbrow0 = new TableRow(this);
TextView tv0 = new TextView(this);
tv0.setText(" Sl.No ");
tbrow0.addView(tv0);
TextView tv1 = new TextView(this);
tv1.setText(" Product ");
tbrow0.addView(tv1);
TextView tv2 = new TextView(this);
tv2.setText(" Unit Price ");
tbrow0.addView(tv2);
TextView tv3 = new TextView(this);
tv3.setText(" Stock Remaining ");
tbrow0.addView(tv3);
stk.addView(tbrow0);
TableRow tbrow = new TableRow(this);
TextView t1v = new TextView(this);
t1v.setText("" + sno);
t1v.setGravity(Gravity.CENTER);
tbrow.addView(t1v);
stk.addView(tbrow);
/* TableRow tbrow0 = new TableRow(this);
TextView tv0 = new TextView(this);
tv0.setText(" Sl.No ");
tv0.setTextColor(Color.WHITE);
tbrow0.addView(tv0);
TextView tv1 = new TextView(this);
tv1.setText(" Product ");
tv1.setTextColor(Color.WHITE);
tbrow0.addView(tv1);
TextView tv2 = new TextView(this);
tv2.setText(" Unit Price ");
tv2.setTextColor(Color.WHITE);
tbrow0.addView(tv2);
TextView tv3 = new TextView(this);
tv3.setText(" Stock Remaining ");
tv3.setTextColor(Color.WHITE);
tbrow0.addView(tv3);
stk.addView(tbrow0);*/
}
/*
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu2, menu);
return true;
}
*/
/*
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_graph:
startActivity(new Intent(this, ViewGraph.class));
return true;
*/
/* return true;
case R.id.help:
startActivity(new Intent(this, Help.class));
return true;*//*
default:
return super.onOptionsItemSelected(item);
}
}
*/
/* private BottomNavigationView.OnNavigationItemSelectedListener navListener =
new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_graph:
Intent intent=new Intent(ViewSamples.this, ViewGraph.class);
intent.putExtra("pid",testid);
startActivity(intent);
break;
case R.id.nav_home:
Intent intent2 = new Intent(ViewSamples.this, MainActivity.class);
startActivity(intent2);
break;
case R.id.nav_excel:
shared();
}
return true;
}
};
*/
public void shared() {
String directory_path = Environment.getExternalStorageDirectory().getPath() + "/Test Report/";
String pat= directory_path + "Report_" + testid + ".xls";
Intent intent = new Intent(Intent.ACTION_VIEW);
File file = new File(pat);
Uri path = FileProvider.getUriForFile(getApplicationContext(), "no.Reader.android.iisc.fileprovider", file);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(path, "application/vnd.ms-excel");
startActivity(intent);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu2, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_graph:
Intent intent=new Intent(ViewSamples.this, ViewGraph.class);
intent.putExtra("pid",testid);
startActivity(intent);
return true;
case R.id.nav_home:
Intent intent2 = new Intent(ViewSamples.this, MainActivity.class);
startActivity(intent2);
return true;
case R.id.nav_excel:
shared();
return true;
case R.id.nav_share:
srk();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void srk()
{
if(ContextCompat.checkSelfPermission(ViewSamples.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(ViewSamples.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},23);
}
else
{
String directory_path = Environment.getExternalStorageDirectory().getPath() + "/Test Report/";
String pat= directory_path + "Report_" + testid + ".xls";
File file = new File(pat);
Intent intent=new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT,"Report");
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N) {
Uri path= FileProvider.getUriForFile(ViewSamples.this,"no.Reader.android.iisc.fileprovider",file);
intent.putExtra(Intent.EXTRA_STREAM,path);
}
else{
intent.putExtra(Intent.EXTRA_STREAM,Uri.fromFile(file));
}
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(path, "application/vnd.ms-excel");
startActivity(intent);
}
}
}

View File

@@ -0,0 +1,21 @@
package no.Reader.android.iisc.Reader.callback;
import android.bluetooth.BluetoothDevice;
import androidx.annotation.NonNull;
/**
* This class defines your characteristic API.
* In this example (that is the HRM characteristic, which the template is based on), is notifying
* with a value (Heart Rate). The single method just returns the value and ignores other
* optional data from Heart Rate Measurement characteristic for simplicity.
*/
public interface SPCACharacteristicCallback {
/**
* Called when a value is received.
*
* @param device a device from which the value was obtained.
* @param value the new value.
*/
void onSampleValueReceived(@NonNull final BluetoothDevice device, int value);
}

View File

@@ -0,0 +1,47 @@
package no.Reader.android.iisc.Reader.callback;
import android.bluetooth.BluetoothDevice;
import androidx.annotation.NonNull;
import no.nordicsemi.android.ble.callback.profile.ProfileDataCallback;
import no.nordicsemi.android.ble.data.Data;
/**
* This is a sample data callback, that's based on Heart Rate Measurement characteristic.
* It parses the HR value and ignores other optional data for simplicity.
* Check {@link no.nordicsemi.android.ble.common.callback.hr.HeartRateMeasurementDataCallback}
* for full implementation.
*
* TODO Modify the content to parse your data.
*/
@SuppressWarnings("ConstantConditions")
public abstract class SPCADataCallback implements ProfileDataCallback, SPCACharacteristicCallback {
@Override
public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
if (data.size() < 2) {
onInvalidDataReceived(device, data);
return;
}
// Read flags
int offset = 0;
final int flags = data.getIntValue(Data.FORMAT_UINT8, offset);
final int hearRateType = (flags & 0x01) == 0 ? Data.FORMAT_UINT8 : Data.FORMAT_UINT16;
offset += 1;
// Validate packet length. The type's lower nibble is its length.
if (data.size() < 1 + (hearRateType & 0x0F)) {
onInvalidDataReceived(device, data);
return;
}
final int value = data.getIntValue(hearRateType, offset);
// offset += hearRateType & 0xF;
// ...
// Report the parsed value(s)
onSampleValueReceived(device, value);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
package no.Reader.android.iisc.Reader.settings;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.view.MenuItem;
import no.Reader.android.iisc.R;
public class SettingsActivity extends AppCompatActivity {
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
final Toolbar toolbar = findViewById(R.id.toolbar_actionbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// Display the fragment as the main content.
getSupportFragmentManager().beginTransaction().replace(R.id.content, new SettingsFragment()).commit();
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
}

View File

@@ -0,0 +1,18 @@
package no.Reader.android.iisc.Reader.settings;
import android.os.Bundle;
import androidx.preference.PreferenceFragmentCompat;
import no.Reader.android.iisc.R;
public class SettingsFragment extends PreferenceFragmentCompat {
public static final String SETTINGS_DATA = "settings_template_data"; // TODO values matching those in settings_template.xml file in /res/xml
public static final int SETTINGS_VARIANT_A = 0;
public static final int SETTINGS_VARIANT_B = 1;
public static final int SETTINGS_VARIANT_DEFAULT = SETTINGS_VARIANT_A;
@Override
public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) {
addPreferencesFromResource(R.xml.settings_template);
}
}

View File

@@ -0,0 +1,144 @@
package no.Reader.android.iisc;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.os.Parcelable;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import no.Reader.android.iisc.Reader.LoginScreen;
import no.Reader.android.iisc.Reader.MainActivity;
public class SplashscreenActivity extends Activity {
/** Splash screen duration time inew n milliseconds */
private static final int DELAY = 1000;
Animation btnAnim ;
Button btnGetStarted;
private static int SPLASH_TIME_OUT=3000;
String number;
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splashscreen);
SharedPreferences preferences6 = getSharedPreferences("PhoneBook_number", MODE_PRIVATE);
number = preferences6.getString("Phone", null);
btnGetStarted=findViewById(R.id.started);
btnGetStarted.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (number == null ) {
Intent home = new Intent(SplashscreenActivity.this, LoginScreen.class);
startActivity(home);
finish();
}
else {
final Intent newIntent = new Intent(SplashscreenActivity.this, MainActivity.class);
newIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
btnGetStarted.setAnimation(btnAnim);
// Handle NFC message, if app was opened using NFC AAR record
final Intent intent = getIntent();
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
final Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMsgs != null) {
for (Parcelable rawMsg : rawMsgs) {
final NdefMessage msg = (NdefMessage) rawMsg;
final NdefRecord[] records = msg.getRecords();
for (NdefRecord record : records) {
if (record.getTnf() == NdefRecord.TNF_MIME_MEDIA) {
switch (record.toMimeType()) {
case FeaturesActivity.EXTRA_APP:
newIntent.putExtra(FeaturesActivity.EXTRA_APP, new String(record.getPayload()));
break;
case FeaturesActivity.EXTRA_ADDRESS:
newIntent.putExtra(FeaturesActivity.EXTRA_ADDRESS, invertEndianness(record.getPayload()));
break;
}
}
}
}
}
}
startActivity(newIntent);
finish();
}
}
});
btnAnim = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.button_animation);
btnGetStarted.setAnimation(btnAnim);
// Jump to SensorsActivity after DELAY milliseconds
/*
new Handler().postDelayed(() -> {
final Intent newIntent = new Intent(SplashscreenActivity.this, TemplateActivity.class);
newIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
// Handle NFC message, if app was opened using NFC AAR record
final Intent intent = getIntent();
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
final Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMsgs != null) {
for (Parcelable rawMsg : rawMsgs) {
final NdefMessage msg = (NdefMessage) rawMsg;
final NdefRecord[] records = msg.getRecords();
for (NdefRecord record : records) {
if (record.getTnf() == NdefRecord.TNF_MIME_MEDIA) {
switch (record.toMimeType()) {
case FeaturesActivity.EXTRA_APP:
newIntent.putExtra(FeaturesActivity.EXTRA_APP, new String(record.getPayload()));
break;
case FeaturesActivity.EXTRA_ADDRESS:
newIntent.putExtra(FeaturesActivity.EXTRA_ADDRESS, invertEndianness(record.getPayload()));
break;
}
}
}
}
}
}
startActivity(newIntent);
finish();
}, DELAY);
*/
}
@Override
public void onBackPressed() {
// do nothing. Protect from exiting the application when splash screen is shown
}
/**
* Inverts endianness of the byte array.
* @param bytes input byte array
* @return byte array in opposite order
*/
private byte[] invertEndianness(final byte[] bytes) {
if (bytes == null)
return null;
final int length = bytes.length;
final byte[] result = new byte[length];
for (int i = 0; i < length; i++)
result[i] = bytes[length - i - 1];
return result;
}
}

View File

@@ -0,0 +1,100 @@
package no.Reader.android.iisc.adapter;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import no.Reader.android.iisc.R;
public class AppAdapter extends BaseAdapter {
private static final String CATEGORY = "no.Reader.android.iisc.LAUNCHER";
private static final String NRF_CONNECT_PACKAGE = "no.nordicsemi.android.mcp";
private final Context mContext;
private final PackageManager mPackageManager;
private final LayoutInflater mInflater;
private final List<ResolveInfo> mApplications;
public AppAdapter(final Context context) {
mContext = context;
mInflater = LayoutInflater.from(context);
// get nRF installed app plugins from package manager
final PackageManager pm = mPackageManager = context.getPackageManager();
final Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(CATEGORY);
final List<ResolveInfo> appList = mApplications = pm.queryIntentActivities(intent, 0);
// TODO remove the following loop after some time, when there will be no more MCP 1.1 at the market.
for (final ResolveInfo info : appList) {
if (NRF_CONNECT_PACKAGE.equals(info.activityInfo.packageName)) {
appList.remove(info);
break;
}
}
Collections.sort(appList, new ResolveInfo.DisplayNameComparator(pm));
}
@Override
public int getCount() {
return mApplications.size();
}
@Override
public Object getItem(int position) {
return mApplications.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
view = mInflater.inflate(R.layout.feature_icon, parent, false);
final ViewHolder holder = new ViewHolder();
holder.view = view;
holder.icon = view.findViewById(R.id.icon);
holder.label = view.findViewById(R.id.label);
view.setTag(holder);
}
final ResolveInfo info = mApplications.get(position);
final PackageManager pm = mPackageManager;
final ViewHolder holder = (ViewHolder) view.getTag();
holder.icon.setImageDrawable(info.loadIcon(pm));
holder.label.setText(info.loadLabel(pm).toString().toUpperCase(Locale.US));
holder.view.setOnClickListener(v -> {
final Intent intent = new Intent();
intent.setComponent(new ComponentName(info.activityInfo.packageName, info.activityInfo.name));
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
mContext.startActivity(intent);
});
return view;
}
private class ViewHolder {
private View view;
private ImageView icon;
private TextView label;
}
}

View File

@@ -0,0 +1,300 @@
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package no.Reader.android.iisc.app;
import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View;
import android.view.View.OnCreateContextMenuListener;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.SimpleCursorTreeAdapter;
import android.widget.SimpleExpandableListAdapter;
import java.util.List;
import java.util.Map;
import no.Reader.android.iisc.R;
/**
* An activity that displays an expandable list of items by binding to a data source implementing the ExpandableListAdapter, and exposes event handlers when the
* user selects an item.
* <p>
* ExpandableListActivity hosts a {@link android.widget.ExpandableListView ExpandableListView} object that can be bound to different data sources that provide a
* two-levels of data (the top-level is group, and below each group are children). Binding, screen layout, and row layout are discussed in the following
* sections.
* <p>
* <strong>Screen Layout</strong>
* </p>
* <p>
* ExpandableListActivity has a default layout that consists of a single, full-screen, centered expandable list. However, if you desire, you can customize the
* screen layout by setting your own view layout with setContentView() in onCreate(). To do this, your own view MUST contain an ExpandableListView object with
* the id "@android:id/list" (or {@link android.R.id#list} if it's in code)
* <p>
* Optionally, your custom view can contain another view object of any type to display when the list view is empty. This "empty list" notifier must have an id
* "android:empty". Note that when an empty view is present, the expandable list view will be hidden when there is no data to display.
* <p>
* The following code demonstrates an (ugly) custom screen layout. It has a list with a green background, and an alternate red "no data" message.
* </p>
*
* <pre>
* &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
* &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
* android:orientation=&quot;vertical&quot;
* android:layout_width=&quot;match_parent&quot;
* android:layout_height=&quot;match_parent&quot;
* android:paddingLeft=&quot;8dp&quot;
* android:paddingRight=&quot;8dp&quot;&gt;
*
* &lt;ExpandableListView android:id=&quot;@id/android:list&quot;
* android:layout_width=&quot;match_parent&quot;
* android:layout_height=&quot;match_parent&quot;
* android:background=&quot;#00FF00&quot;
* android:layout_weight=&quot;1&quot;
* android:drawSelectorOnTop=&quot;false&quot;/&gt;
*
* &lt;TextView android:id=&quot;@id/android:empty&quot;
* android:layout_width=&quot;match_parent&quot;
* android:layout_height=&quot;match_parent&quot;
* android:background=&quot;#FF0000&quot;
* android:text=&quot;No data&quot;/&gt;
* &lt;/LinearLayout&gt;
* </pre>
*
* <p>
* <strong>Row Layout</strong>
* </p>
* The {@link ExpandableListAdapter} set in the {@link ExpandableListActivity} via {@link #setListAdapter(ExpandableListAdapter)} provides the {@link View}s for
* each row. This adapter has separate methods for providing the group {@link View}s and child {@link View}s. There are a couple provided
* {@link ExpandableListAdapter}s that simplify use of adapters: {@link SimpleCursorTreeAdapter} and {@link SimpleExpandableListAdapter}.
* <p>
* With these, you can specify the layout of individual rows for groups and children in the list. These constructor takes a few parameters that specify layout
* resources for groups and children. It also has additional parameters that let you specify which data field to associate with which object in the row layout
* resource. The {@link SimpleCursorTreeAdapter} fetches data from {@link Cursor}s and the {@link SimpleExpandableListAdapter} fetches data from {@link List}s
* of {@link Map}s.
* </p>
* <p>
* Android provides some standard row layout resources. These are in the {@link android.R.layout} class, and have names such as simple_list_item_1,
* simple_list_item_2, and two_line_list_item. The following layout XML is the source for the resource two_line_list_item, which displays two data fields,one
* above the other, for each list row.
* </p>
*
* <pre>
* &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
* &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
* android:layout_width=&quot;match_parent&quot;
* android:layout_height=&quot;wrap_content&quot;
* android:orientation=&quot;vertical&quot;&gt;
*
* &lt;TextView android:id=&quot;@+id/text1&quot;
* android:textSize=&quot;16sp&quot;
* android:textStyle=&quot;bold&quot;
* android:layout_width=&quot;match_parent&quot;
* android:layout_height=&quot;wrap_content&quot;/&gt;
*
* &lt;TextView android:id=&quot;@+id/text2&quot;
* android:textSize=&quot;16sp&quot;
* android:layout_width=&quot;match_parent&quot;
* android:layout_height=&quot;wrap_content&quot;/&gt;
* &lt;/LinearLayout&gt;
* </pre>
*
* <p>
* You must identify the data bound to each TextView object in this layout. The syntax for this is discussed in the next section.
* </p>
* <p>
* <strong>Binding to Data</strong>
* </p>
* <p>
* You bind the ExpandableListActivity's ExpandableListView object to data using a class that implements the {@link android.widget.ExpandableListAdapter
* ExpandableListAdapter} interface. Android provides two standard list adapters: {@link android.widget.SimpleExpandableListAdapter SimpleExpandableListAdapter}
* for static data (Maps), and {@link android.widget.SimpleCursorTreeAdapter SimpleCursorTreeAdapter} for Cursor query results.
* </p>
*
* @see #setListAdapter
* @see android.widget.ExpandableListView
*/
public class ExpandableListActivity extends AppCompatActivity implements
OnCreateContextMenuListener,
ExpandableListView.OnChildClickListener, ExpandableListView.OnGroupCollapseListener,
ExpandableListView.OnGroupExpandListener {
ExpandableListAdapter mAdapter;
ExpandableListView mList;
boolean mFinishedStart = false;
/**
* Override this to populate the context menu when an item is long pressed. menuInfo will contain an
* {@link android.widget.ExpandableListView.ExpandableListContextMenuInfo} whose packedPosition is a packed position that should be used with
* {@link ExpandableListView#getPackedPositionType(long)} and the other similar methods.
* <p>
* {@inheritDoc}
*/
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
}
/**
* Override this for receiving callbacks when a child has been clicked.
* <p>
* {@inheritDoc}
*/
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
int childPosition, long id) {
return false;
}
/**
* Override this for receiving callbacks when a group has been collapsed.
*/
@Override
public void onGroupCollapse(int groupPosition) {
}
/**
* Override this for receiving callbacks when a group has been expanded.
*/
@Override
public void onGroupExpand(int groupPosition) {
}
/**
* Ensures the expandable list view has been created before Activity restores all of the view states.
*
* @see Activity#onRestoreInstanceState(Bundle)
*/
@Override
protected void onRestoreInstanceState(@NonNull Bundle state) {
ensureList();
super.onRestoreInstanceState(state);
}
/**
* Updates the screen state (current list and other views) when the content changes.
*
* @see androidx.appcompat.app.AppCompatActivity#onContentChanged()
*/
@Override
public void onContentChanged() {
super.onContentChanged();
View emptyView = findViewById(R.id.empty);
mList = findViewById(R.id.list);
if (mList == null) {
throw new RuntimeException(
"Your content must have a ExpandableListView whose id attribute is " +
"'R.id.list'");
}
if (emptyView != null) {
mList.setEmptyView(emptyView);
}
mList.setOnChildClickListener(this);
mList.setOnGroupExpandListener(this);
mList.setOnGroupCollapseListener(this);
if (mFinishedStart) {
setListAdapter(mAdapter);
}
mFinishedStart = true;
}
/**
* Provide the adapter for the expandable list.
*/
public void setListAdapter(ExpandableListAdapter adapter) {
synchronized (this) {
ensureList();
mAdapter = adapter;
mList.setAdapter(adapter);
}
}
/**
* Get the activity's expandable list view widget. This can be used to get the selection, set the selection, and many other useful functions.
*
* @see ExpandableListView
*/
public ExpandableListView getExpandableListView() {
ensureList();
return mList;
}
/**
* Get the ExpandableListAdapter associated with this activity's ExpandableListView.
*/
public ExpandableListAdapter getExpandableListAdapter() {
return mAdapter;
}
private void ensureList() {
if (mList != null) {
return;
}
setContentView(R.layout.expandable_list_content);
}
/**
* Gets the ID of the currently selected group or child.
*
* @return The ID of the currently selected group or child.
*/
public long getSelectedId() {
return mList.getSelectedId();
}
/**
* Gets the position (in packed position representation) of the currently selected group or child. Use {@link ExpandableListView#getPackedPositionType},
* {@link ExpandableListView#getPackedPositionGroup}, and {@link ExpandableListView#getPackedPositionChild} to unpack the returned packed position.
*
* @return A packed position representation containing the currently selected group or child's position and type.
*/
public long getSelectedPosition() {
return mList.getSelectedPosition();
}
/**
* Sets the selection to the specified child. If the child is in a collapsed group, the group will only be expanded and child subsequently selected if
* shouldExpandGroup is set to true, otherwise the method will return false.
*
* @param groupPosition
* The position of the group that contains the child.
* @param childPosition
* The position of the child within the group.
* @param shouldExpandGroup
* Whether the child's group should be expanded if it is collapsed.
* @return Whether the selection was successfully set on the child.
*/
public boolean setSelectedChild(int groupPosition, int childPosition, boolean shouldExpandGroup) {
return mList.setSelectedChild(groupPosition, childPosition, shouldExpandGroup);
}
/**
* Sets the selection to the specified group.
*
* @param groupPosition
* The position of the group that should be selected.
*/
public void setSelectedGroup(int groupPosition) {
mList.setSelectedGroup(groupPosition);
}
}

View File

@@ -0,0 +1,124 @@
package no.Reader.android.iisc.battery;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import androidx.annotation.NonNull;
import android.util.Log;
import java.util.UUID;
import no.nordicsemi.android.ble.BleManager;
import no.nordicsemi.android.ble.callback.DataReceivedCallback;
import no.nordicsemi.android.ble.common.callback.battery.BatteryLevelDataCallback;
import no.nordicsemi.android.ble.data.Data;
import no.nordicsemi.android.log.LogContract;
import no.Reader.android.iisc.profile.LoggableBleManager;
/**
* The Ble Manager with Battery Service support.
*
* @param <T> The profile callbacks type.
* @see BleManager
*/
@SuppressWarnings("WeakerAccess")
public abstract class BatteryManager<T extends BatteryManagerCallbacks> extends LoggableBleManager<T> {
/** Battery Service UUID. */
private final static UUID BATTERY_SERVICE_UUID = UUID.fromString("0000180F-0000-1000-8000-00805f9b34fb");
/** Battery Level characteristic UUID. */
private final static UUID BATTERY_LEVEL_CHARACTERISTIC_UUID = UUID.fromString("00002A19-0000-1000-8000-00805f9b34fb");
private BluetoothGattCharacteristic mBatteryLevelCharacteristic;
/** Last received Battery Level value. */
private Integer mBatteryLevel;
/**
* The manager constructor.
*
* @param context context.
*/
public BatteryManager(final Context context) {
super(context);
}
private DataReceivedCallback mBatteryLevelDataCallback = new BatteryLevelDataCallback() {
@Override
public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int batteryLevel) {
log(LogContract.Log.Level.APPLICATION,"Battery Level received: " + batteryLevel + "%");
mBatteryLevel = batteryLevel;
mCallbacks.onBatteryLevelChanged(device, batteryLevel);
}
@Override
public void onInvalidDataReceived(@NonNull final BluetoothDevice device, final @NonNull Data data) {
log(Log.WARN, "Invalid Battery Level data received: " + data);
}
};
public void readBatteryLevelCharacteristic() {
if (isConnected()) {
readCharacteristic(mBatteryLevelCharacteristic)
.with(mBatteryLevelDataCallback)
.fail((device, status) -> log(Log.WARN,"Battery Level characteristic not found"))
.enqueue();
}
}
public void enableBatteryLevelCharacteristicNotifications() {
if (isConnected()) {
// If the Battery Level characteristic is null, the request will be ignored
setNotificationCallback(mBatteryLevelCharacteristic)
.with(mBatteryLevelDataCallback);
enableNotifications(mBatteryLevelCharacteristic)
.done(device -> log(Log.INFO, "Battery Level notifications enabled"))
.fail((device, status) -> log(Log.WARN, "Battery Level characteristic not found"))
.enqueue();
}
}
/**
* Disables Battery Level notifications on the Server.
*/
public void disableBatteryLevelCharacteristicNotifications() {
if (isConnected()) {
disableNotifications(mBatteryLevelCharacteristic)
.done(device -> log(Log.INFO, "Battery Level notifications disabled"))
.enqueue();
}
}
/**
* Returns the last received Battery Level value.
* The value is set to null when the device disconnects.
* @return Battery Level value, in percent.
*/
public Integer getBatteryLevel() {
return mBatteryLevel;
}
protected abstract class BatteryManagerGattCallback extends BleManagerGattCallback {
@Override
protected void initialize() {
readBatteryLevelCharacteristic();
enableBatteryLevelCharacteristicNotifications();
}
@Override
protected boolean isOptionalServiceSupported(@NonNull final BluetoothGatt gatt) {
final BluetoothGattService service = gatt.getService(BATTERY_SERVICE_UUID);
if (service != null) {
mBatteryLevelCharacteristic = service.getCharacteristic(BATTERY_LEVEL_CHARACTERISTIC_UUID);
}
return mBatteryLevelCharacteristic != null;
}
@Override
protected void onDeviceDisconnected() {
mBatteryLevelCharacteristic = null;
mBatteryLevel = null;
}
}
}

View File

@@ -0,0 +1,7 @@
package no.Reader.android.iisc.battery;
import no.nordicsemi.android.ble.BleManagerCallbacks;
import no.nordicsemi.android.ble.common.profile.battery.BatteryLevelCallback;
public interface BatteryManagerCallbacks extends BleManagerCallbacks, BatteryLevelCallback {
}

View File

@@ -0,0 +1,48 @@
package no.Reader.android.iisc.parser;
import no.nordicsemi.android.ble.data.Data;
// TODO this method may be used for developing purposes to log the data from your device using the nRF Logger application.
@SuppressWarnings("ConstantConditions")
public class SPCAParser {
// TODO add some flags, if needed
private static final byte HEART_RATE_VALUE_FORMAT = 0x01; // 1 bit
/**
* This method converts the value of the characteristic to the String. The String is then logged in the nRF logger log session
* @param data the characteristic data to be parsed
* @return human readable value of the characteristic
*/
@SuppressWarnings("UnusedAssignment")
public static String parse(final Data data) {
int offset = 0;
int flags = 0;
int value=0;
if(data.getIntValue(Data.FORMAT_UINT8, offset++)!=null) {
flags = data.getIntValue(Data.FORMAT_UINT8, offset++);
}
/*
* In the template we are using the HRM values as an example.
* false Heart Rate Value Format is set to UINT8. Units: beats per minute (bpm)
* true Heart Rate Value Format is set to UINT16. Units: beats per minute (bpm)
*/
final boolean value16bit = (flags & HEART_RATE_VALUE_FORMAT) > 0;
// heart rate value is 8 or 16 bit long
if((data.getIntValue(value16bit ? Data.FORMAT_UINT16 : Data.FORMAT_UINT8, offset++)!=null))
{
value = data.getIntValue(value16bit ? Data.FORMAT_UINT16 : Data.FORMAT_UINT8, offset++); // bits per minute
}
if (value16bit)
offset++;
// TODO parse more data
return "Template Measurement: " + value + " bpm";
}
}

View File

@@ -0,0 +1,398 @@
package no.Reader.android.iisc.profile;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.util.UUID;
import no.nordicsemi.android.ble.BleManagerCallbacks;
import no.nordicsemi.android.log.ILogSession;
import no.nordicsemi.android.log.LocalLogSession;
import no.nordicsemi.android.log.Logger;
import no.Reader.android.iisc.R;
import no.Reader.android.iisc.scanner.ScannerFragment;
import no.Reader.android.iisc.DebugLogger;
@SuppressWarnings("unused")
public abstract class BleProfileActivity extends AppCompatActivity implements BleManagerCallbacks, ScannerFragment.OnDeviceSelectedListener {
private static final String TAG = "BaseProfileActivity";
private static final String SIS_CONNECTION_STATUS = "connection_status";
private static final String SIS_DEVICE_NAME = "device_name";
protected static final int REQUEST_ENABLE_BT = 2;
private LoggableBleManager<? extends BleManagerCallbacks> mBleManager;
private TextView mDeviceNameView;
private Button mConnectButton;
private ILogSession mLogSession;
private boolean mDeviceConnected = false;
private String mDeviceName;
@Override
protected final void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ensureBLESupported();
if (!isBLEEnabled()) {
showBLEDialog();
}
/*
* We use the managers using a singleton pattern. It's not recommended for the Android, because the singleton instance remains after Activity has been
* destroyed but it's simple and is used only for this demo purpose. In final application Managers should be created as a non-static objects in
* Services. The Service should implement ManagerCallbacks interface. The application Activity may communicate with such Service using binding,
* broadcast listeners, local broadcast listeners (see support.v4 library), or messages. See the Proximity profile for Service approach.
*/
mBleManager = initializeManager();
// In onInitialize method a final class may register local broadcast receivers that will listen for events from the service
onInitialize(savedInstanceState);
// The onCreateView class should... create the view
onCreateView(savedInstanceState);
final Toolbar toolbar = findViewById(R.id.toolbar_actionbar);
setSupportActionBar(toolbar);
// Common nRF Toolbox view references are obtained here
setUpView();
// View is ready to be used
onViewCreated(savedInstanceState);
}
/**
* You may do some initialization here. This method is called from {@link #onCreate(Bundle)} before the view was created.
*/
protected void onInitialize(final Bundle savedInstanceState) {
// empty default implementation
}
/**
* Called from {@link #onCreate(Bundle)}. This method should build the activity UI, i.e. using {@link #setContentView(int)}.
* Use to obtain references to views. Connect/Disconnect button and the device name view are manager automatically.
*
* @param savedInstanceState contains the data it most recently supplied in {@link #onSaveInstanceState(Bundle)}.
* Note: <b>Otherwise it is null</b>.
*/
protected abstract void onCreateView(final Bundle savedInstanceState);
/**
* Called after the view has been created.
*
* @param savedInstanceState contains the data it most recently supplied in {@link #onSaveInstanceState(Bundle)}.
* Note: <b>Otherwise it is null</b>.
*/
protected void onViewCreated(final Bundle savedInstanceState) {
// empty default implementation
}
/**
* Called after the view and the toolbar has been created.
*/
protected final void setUpView() {
// set GUI
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mConnectButton = findViewById(R.id.action_connect);
mDeviceNameView = findViewById(R.id.device_name);
}
@Override
public void onBackPressed() {
mBleManager.disconnect().enqueue();
super.onBackPressed();
}
@Override
protected void onSaveInstanceState(final Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(SIS_CONNECTION_STATUS, mDeviceConnected);
outState.putString(SIS_DEVICE_NAME, mDeviceName);
}
@Override
protected void onRestoreInstanceState(final @NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mDeviceConnected = savedInstanceState.getBoolean(SIS_CONNECTION_STATUS);
mDeviceName = savedInstanceState.getString(SIS_DEVICE_NAME);
if (mDeviceConnected) {
mConnectButton.setText(R.string.action_disconnect);
} else {
mConnectButton.setText(R.string.action_connect);
}
}
/**
* Use this method to handle menu actions other than home and about.
*
* @param itemId the menu item id
* @return <code>true</code> if action has been handled
*/
protected boolean onOptionsItemSelected(final int itemId) {
// Overwrite when using menu other than R.menu.help
return false;
}
/**
* Called when user press CONNECT or DISCONNECT button. See layout files -> onClick attribute.
*/
public void onConnectClicked(final View view) {
if (isBLEEnabled()) {
if (!mDeviceConnected) {
setDefaultUI();
showDeviceScanningDialog(getFilterUUID());
} else {
mBleManager.disconnect().enqueue();
}
} else {
showBLEDialog();
}
}
/**
* Returns the title resource id that will be used to create logger session. If 0 is returned (default) logger will not be used.
*
* @return the title resource id
*/
protected int getLoggerProfileTitle() {
return 0;
}
/**
* This method may return the local log content provider authority if local log sessions are supported.
*
* @return local log session content provider URI
*/
protected Uri getLocalAuthorityLogger() {
return null;
}
/**
* This method returns whether autoConnect option should be used.
*
* @return true to use autoConnect feature, false (default) otherwise.
*/
protected boolean shouldAutoConnect() {
return false;
}
@Override
public void onDeviceSelected(final BluetoothDevice device, final String name) {
final int titleId = getLoggerProfileTitle();
if (titleId > 0) {
mLogSession = Logger.newSession(getApplicationContext(), getString(titleId), device.getAddress(), name);
// If nRF Logger is not installed we may want to use local logger
if (mLogSession == null && getLocalAuthorityLogger() != null) {
mLogSession = LocalLogSession.newSession(getApplicationContext(), getLocalAuthorityLogger(), device.getAddress(), name);
}
}
mDeviceName = name;
mBleManager.setLogger(mLogSession);
mBleManager.connect(device)
.useAutoConnect(shouldAutoConnect())
.retry(3, 100)
.enqueue();
}
@Override
public void onDialogCanceled() {
// do nothing
}
@Override
public void onDeviceConnecting(@NonNull final BluetoothDevice device) {
runOnUiThread(() -> {
mDeviceNameView.setText(mDeviceName != null ? mDeviceName : getString(R.string.not_available));
mConnectButton.setText(R.string.action_connecting);
});
}
@Override
public void onDeviceConnected(@NonNull final BluetoothDevice device) {
mDeviceConnected = true;
runOnUiThread(() -> mConnectButton.setText(R.string.action_disconnect));
}
@Override
public void onDeviceDisconnecting(@NonNull final BluetoothDevice device) {
runOnUiThread(() -> mConnectButton.setText(R.string.action_disconnecting));
}
@Override
public void onDeviceDisconnected(@NonNull final BluetoothDevice device) {
mDeviceConnected = false;
mBleManager.close();
runOnUiThread(() -> {
mConnectButton.setText(R.string.action_connect);
mDeviceNameView.setText(getDefaultDeviceName());
});
}
@Override
public void onLinkLossOccurred(@NonNull final BluetoothDevice device) {
mDeviceConnected = false;
}
@Override
public void onServicesDiscovered(@NonNull final BluetoothDevice device, boolean optionalServicesFound) {
// this may notify user or show some views
}
@Override
public void onDeviceReady(@NonNull final BluetoothDevice device) {
// empty default implementation
}
@Override
public void onBondingRequired(@NonNull final BluetoothDevice device) {
showToast(R.string.bonding);
}
@Override
public void onBonded(@NonNull final BluetoothDevice device) {
showToast(R.string.bonded);
}
@Override
public void onBondingFailed(@NonNull final BluetoothDevice device) {
showToast(R.string.bonding_failed);
}
@Override
public void onError(@NonNull final BluetoothDevice device, @NonNull final String message, final int errorCode) {
DebugLogger.e(TAG, "Error occurred: " + message + ", error code: " + errorCode);
showToast(message + " (" + errorCode + ")");
}
@Override
public void onDeviceNotSupported(@NonNull final BluetoothDevice device) {
showToast(R.string.not_supported);
}
/**
* Shows a message as a Toast notification. This method is thread safe, you can call it from any thread
*
* @param message a message to be shown
*/
protected void showToast(final String message) {
runOnUiThread(() -> Toast.makeText(BleProfileActivity.this, message, Toast.LENGTH_SHORT).show());
}
/**
* Shows a message as a Toast notification. This method is thread safe, you can call it from any thread
*
* @param messageResId an resource id of the message to be shown
*/
protected void showToast(final int messageResId) {
runOnUiThread(() -> Toast.makeText(BleProfileActivity.this, messageResId, Toast.LENGTH_SHORT).show());
}
/**
* Returns <code>true</code> if the device is connected. Services may not have been discovered yet.
*/
protected boolean isDeviceConnected() {
return mDeviceConnected;
}
/**
* Returns the name of the device that the phone is currently connected to or was connected last time
*/
protected String getDeviceName() {
return mDeviceName;
}
/**
* Initializes the Bluetooth Low Energy manager. A manager is used to communicate with profile's services.
*
* @return the manager that was created
*/
protected abstract LoggableBleManager<? extends BleManagerCallbacks> initializeManager();
/**
* Restores the default UI before reconnecting
*/
protected abstract void setDefaultUI();
/**
* Returns the default device name resource id. The real device name is obtained when connecting to the device. This one is used when device has
* disconnected.
*
* @return the default device name resource id
*/
protected abstract int getDefaultDeviceName();
/**
* Returns the string resource id that will be shown in About box
*
* @return the about resource id
*/
protected abstract int getAboutTextId();
/**
* The UUID filter is used to filter out available devices that does not have such UUID in their advertisement packet. See also:
* {@link #isChangingConfigurations()}.
*
* @return the required UUID or <code>null</code>
*/
protected abstract UUID getFilterUUID();
/**
* Shows the scanner fragment.
*
* @param filter the UUID filter used to filter out available devices. The fragment will always show all bonded devices as there is no information about their
* services
* @see #getFilterUUID()
*/
private void showDeviceScanningDialog(final UUID filter) {
runOnUiThread(() -> {
final ScannerFragment dialog = ScannerFragment.getInstance(filter);
dialog.show(getSupportFragmentManager(), "scan_fragment");
});
}
/**
* Returns the log session. Log session is created when the device was selected using the {@link ScannerFragment} and released when user press DISCONNECT.
*
* @return the logger session or <code>null</code>
*/
protected ILogSession getLogSession() {
return mLogSession;
}
private void ensureBLESupported() {
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.no_ble, Toast.LENGTH_LONG).show();
finish();
}
}
protected boolean isBLEEnabled() {
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
final BluetoothAdapter adapter = bluetoothManager.getAdapter();
return adapter != null && adapter.isEnabled();
}
protected void showBLEDialog() {
final Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
}
}

View File

@@ -0,0 +1,401 @@
package no.Reader.android.iisc.profile;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.util.UUID;
import no.nordicsemi.android.ble.BleManagerCallbacks;
import no.nordicsemi.android.log.ILogSession;
import no.nordicsemi.android.log.LocalLogSession;
import no.nordicsemi.android.log.Logger;
import no.Reader.android.iisc.R;
import no.Reader.android.iisc.app.ExpandableListActivity;
import no.Reader.android.iisc.scanner.ScannerFragment;
import no.Reader.android.iisc.DebugLogger;
@SuppressWarnings("unused")
public abstract class BleProfileExpandableListActivity extends ExpandableListActivity implements BleManagerCallbacks, ScannerFragment.OnDeviceSelectedListener {
private static final String TAG = "BaseProfileActivity";
private static final String SIS_CONNECTION_STATUS = "connection_status";
private static final String SIS_DEVICE_NAME = "device_name";
protected static final int REQUEST_ENABLE_BT = 2;
private LoggableBleManager<? extends BleManagerCallbacks> mBleManager;
private TextView mDeviceNameView;
private Button mConnectButton;
private ILogSession mLogSession;
private boolean mDeviceConnected = false;
private String mDeviceName;
@Override
protected final void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ensureBLESupported();
if (!isBLEEnabled()) {
showBLEDialog();
}
/*
* We use the managers using a singleton pattern. It's not recommended for the Android, because the singleton instance remains after Activity has been
* destroyed but it's simple and is used only for this demo purpose. In final application Managers should be created as a non-static objects in
* Services. The Service should implement ManagerCallbacks interface. The application Activity may communicate with such Service using binding,
* broadcast listeners, local broadcast listeners (see support.v4 library), or messages. See the Proximity profile for Service approach.
*/
mBleManager = initializeManager();
// In onInitialize method a final class may register local broadcast receivers that will listen for events from the service
onInitialize(savedInstanceState);
// The onCreateView class should... create the view
onCreateView(savedInstanceState);
final Toolbar toolbar = findViewById(R.id.toolbar_actionbar);
setSupportActionBar(toolbar);
// Common nRF Toolbox view references are obtained here
setUpView();
// View is ready to be used
onViewCreated(savedInstanceState);
}
/**
* You may do some initialization here. This method is called from {@link #onCreate(Bundle)} before the view was created.
*/
@SuppressWarnings("unused")
protected void onInitialize(final Bundle savedInstanceState) {
// empty default implementation
}
/**
* Called from {@link #onCreate(Bundle)}. This method should build the activity UI, i.e. using {@link #setContentView(int)}.
* Use to obtain references to views. Connect/Disconnect button and the device name view are manager automatically.
*
* @param savedInstanceState contains the data it most recently supplied in {@link #onSaveInstanceState(Bundle)}.
* Note: <b>Otherwise it is null</b>.
*/
protected abstract void onCreateView(final Bundle savedInstanceState);
/**
* Called after the view has been created.
*
* @param savedInstanceState contains the data it most recently supplied in {@link #onSaveInstanceState(Bundle)}.
* Note: <b>Otherwise it is null</b>.
*/
@SuppressWarnings("unused")
protected void onViewCreated(final Bundle savedInstanceState) {
// empty default implementation
}
/**
* Called after the view and the toolbar has been created.
*/
protected final void setUpView() {
// set GUI
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mConnectButton = findViewById(R.id.action_connect);
mDeviceNameView = findViewById(R.id.device_name);
}
@Override
public void onBackPressed() {
mBleManager.disconnect().enqueue();
super.onBackPressed();
}
@Override
protected void onSaveInstanceState(final Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(SIS_CONNECTION_STATUS, mDeviceConnected);
outState.putString(SIS_DEVICE_NAME, mDeviceName);
}
@Override
protected void onRestoreInstanceState(final @NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mDeviceConnected = savedInstanceState.getBoolean(SIS_CONNECTION_STATUS);
mDeviceName = savedInstanceState.getString(SIS_DEVICE_NAME);
if (mDeviceConnected) {
mConnectButton.setText(R.string.action_disconnect);
} else {
mConnectButton.setText(R.string.action_connect);
}
}
/**
* Use this method to handle menu actions other than home and about.
*
* @param itemId the menu item id
* @return <code>true</code> if action has been handled
*/
@SuppressWarnings("unused")
protected boolean onOptionsItemSelected(final int itemId) {
// Overwrite when using menu other than R.menu.help
return false;
}
/**
* Called when user press CONNECT or DISCONNECT button. See layout files -> onClick attribute.
*/
public void onConnectClicked(final View view) {
if (isBLEEnabled()) {
if (!mDeviceConnected) {
setDefaultUI();
showDeviceScanningDialog(getFilterUUID());
} else {
mBleManager.disconnect().enqueue();
}
} else {
showBLEDialog();
}
}
/**
* Returns the title resource id that will be used to create logger session. If 0 is returned (default) logger will not be used.
*
* @return the title resource id
*/
protected int getLoggerProfileTitle() {
return 0;
}
/**
* This method may return the local log content provider authority if local log sessions are supported.
*
* @return local log session content provider URI
*/
protected Uri getLocalAuthorityLogger() {
return null;
}
/**
* This method returns whether autoConnect option should be used.
*
* @return true to use autoConnect feature, false (default) otherwise.
*/
protected boolean shouldAutoConnect() {
return false;
}
@Override
public void onDeviceSelected(final BluetoothDevice device, final String name) {
final int titleId = getLoggerProfileTitle();
if (titleId > 0) {
mLogSession = Logger.newSession(getApplicationContext(), getString(titleId), device.getAddress(), name);
// If nRF Logger is not installed we may want to use local logger
if (mLogSession == null && getLocalAuthorityLogger() != null) {
mLogSession = LocalLogSession.newSession(getApplicationContext(), getLocalAuthorityLogger(), device.getAddress(), name);
}
}
mDeviceName = name;
mBleManager.setLogger(mLogSession);
mBleManager.connect(device)
.useAutoConnect(shouldAutoConnect())
.retry(3, 100)
.enqueue();
}
@Override
public void onDialogCanceled() {
// do nothing
}
@Override
public void onDeviceConnecting(@NonNull final BluetoothDevice device) {
runOnUiThread(() -> {
mDeviceNameView.setText(mDeviceName != null ? mDeviceName : getString(R.string.not_available));
mConnectButton.setText(R.string.action_connecting);
});
}
@Override
public void onDeviceConnected(@NonNull final BluetoothDevice device) {
mDeviceConnected = true;
runOnUiThread(() -> mConnectButton.setText(R.string.action_disconnect));
}
@Override
public void onDeviceDisconnecting(@NonNull final BluetoothDevice device) {
runOnUiThread(() -> mConnectButton.setText(R.string.action_disconnecting));
}
@Override
public void onDeviceDisconnected(@NonNull final BluetoothDevice device) {
mDeviceConnected = false;
mBleManager.close();
runOnUiThread(() -> {
mConnectButton.setText(R.string.action_connect);
mDeviceNameView.setText(getDefaultDeviceName());
});
}
@Override
public void onLinkLossOccurred(@NonNull final BluetoothDevice device) {
mDeviceConnected = false;
}
@Override
public void onServicesDiscovered(@NonNull final BluetoothDevice device, boolean optionalServicesFound) {
// this may notify user or show some views
}
@Override
public void onDeviceReady(@NonNull final BluetoothDevice device) {
// empty default implementation
}
@Override
public void onBondingRequired(@NonNull final BluetoothDevice device) {
showToast(R.string.bonding);
}
@Override
public void onBonded(@NonNull final BluetoothDevice device) {
showToast(R.string.bonded);
}
@Override
public void onBondingFailed(@NonNull final BluetoothDevice device) {
showToast(R.string.bonding_failed);
}
@Override
public void onError(@NonNull final BluetoothDevice device, @NonNull final String message, final int errorCode) {
DebugLogger.e(TAG, "Error occurred: " + message + ", error code: " + errorCode);
showToast(message + " (" + errorCode + ")");
}
@Override
public void onDeviceNotSupported(@NonNull final BluetoothDevice device) {
showToast(R.string.not_supported);
}
/**
* Shows a message as a Toast notification. This method is thread safe, you can call it from any thread
*
* @param message a message to be shown
*/
protected void showToast(final String message) {
runOnUiThread(() -> Toast.makeText(BleProfileExpandableListActivity.this, message, Toast.LENGTH_SHORT).show());
}
/**
* Shows a message as a Toast notification. This method is thread safe, you can call it from any thread
*
* @param messageResId an resource id of the message to be shown
*/
protected void showToast(final int messageResId) {
runOnUiThread(() -> Toast.makeText(BleProfileExpandableListActivity.this, messageResId, Toast.LENGTH_SHORT).show());
}
/**
* Returns <code>true</code> if the device is connected. Services may not have been discovered yet.
*/
protected boolean isDeviceConnected() {
return mDeviceConnected;
}
/**
* Returns the name of the device that the phone is currently connected to or was connected last time
*/
protected String getDeviceName() {
return mDeviceName;
}
/**
* Initializes the Bluetooth Low Energy manager. A manager is used to communicate with profile's services.
*
* @return the manager that was created
*/
protected abstract LoggableBleManager<? extends BleManagerCallbacks> initializeManager();
/**
* Restores the default UI before reconnecting
*/
protected abstract void setDefaultUI();
/**
* Returns the default device name resource id. The real device name is obtained when connecting to the device. This one is used when device has
* disconnected.
*
* @return the default device name resource id
*/
protected abstract int getDefaultDeviceName();
/**
* Returns the string resource id that will be shown in About box
*
* @return the about resource id
*/
protected abstract int getAboutTextId();
/**
* The UUID filter is used to filter out available devices that does not have such UUID in their advertisement packet. See also:
* {@link #isChangingConfigurations()}.
*
* @return the required UUID or <code>null</code>
*/
protected abstract UUID getFilterUUID();
/**
* Shows the scanner fragment.
*
* @param filter the UUID filter used to filter out available devices. The fragment will always show all bonded devices as there is no information about their
* services
* @see #getFilterUUID()
*/
private void showDeviceScanningDialog(final UUID filter) {
runOnUiThread(() -> {
final ScannerFragment dialog = ScannerFragment.getInstance(filter);
dialog.show(getSupportFragmentManager(), "scan_fragment");
});
}
/**
* Returns the log session. Log session is created when the device was selected using the {@link ScannerFragment} and released when user press DISCONNECT.
*
* @return the logger session or <code>null</code>
*/
protected ILogSession getLogSession() {
return mLogSession;
}
private void ensureBLESupported() {
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.no_ble, Toast.LENGTH_LONG).show();
finish();
}
}
protected boolean isBLEEnabled() {
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
final BluetoothAdapter adapter = bluetoothManager.getAdapter();
return adapter != null && adapter.isEnabled();
}
protected void showBLEDialog() {
final Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
}
}

View File

@@ -0,0 +1,582 @@
package no.Reader.android.iisc.profile;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.util.Log;
import android.widget.Toast;
import no.nordicsemi.android.ble.BleManager;
import no.nordicsemi.android.ble.BleManagerCallbacks;
import no.nordicsemi.android.ble.utils.ILogger;
import no.nordicsemi.android.log.ILogSession;
import no.nordicsemi.android.log.Logger;
@SuppressWarnings("unused")
public abstract class BleProfileService extends Service implements BleManagerCallbacks {
@SuppressWarnings("unused")
private static final String TAG = "BleProfileService";
public static final String BROADCAST_CONNECTION_STATE = "no.Reader.android.iisc.BROADCAST_CONNECTION_STATE";
public static final String BROADCAST_SERVICES_DISCOVERED = "no.Reader.android.iisc.BROADCAST_SERVICES_DISCOVERED";
public static final String BROADCAST_DEVICE_READY = "no.Reader.android.iisc.DEVICE_READY";
public static final String BROADCAST_BOND_STATE = "no.Reader.android.iisc.BROADCAST_BOND_STATE";
@Deprecated
public static final String BROADCAST_BATTERY_LEVEL = "no.Reader.android.iisc.BROADCAST_BATTERY_LEVEL";
public static final String BROADCAST_ERROR = "no.Reader.android.iisc.BROADCAST_ERROR";
/** The parameter passed when creating the service. Must contain the address of the sensor that we want to connect to */
public static final String EXTRA_DEVICE_ADDRESS = "no.Reader.android.iisc.EXTRA_DEVICE_ADDRESS";
/** The key for the device name that is returned in {@link #BROADCAST_CONNECTION_STATE} with state {@link #STATE_CONNECTED}. */
public static final String EXTRA_DEVICE_NAME = "no.Reader.android.iisc.EXTRA_DEVICE_NAME";
public static final String EXTRA_DEVICE = "no.Reader.android.iisc.EXTRA_DEVICE";
public static final String EXTRA_LOG_URI = "no.Reader.android.iisc.EXTRA_LOG_URI";
public static final String EXTRA_CONNECTION_STATE = "no.Reader.android.iisc.EXTRA_CONNECTION_STATE";
public static final String EXTRA_BOND_STATE = "no.Reader.android.iisc.EXTRA_BOND_STATE";
public static final String EXTRA_SERVICE_PRIMARY = "no.Reader.android.iisc.EXTRA_SERVICE_PRIMARY";
public static final String EXTRA_SERVICE_SECONDARY = "no.Reader.android.iisc.EXTRA_SERVICE_SECONDARY";
@Deprecated
public static final String EXTRA_BATTERY_LEVEL = "no.Reader.android.iisc.EXTRA_BATTERY_LEVEL";
public static final String EXTRA_ERROR_MESSAGE = "no.Reader.android.iisc.EXTRA_ERROR_MESSAGE";
public static final String EXTRA_ERROR_CODE = "no.Reader.android.iisc.EXTRA_ERROR_CODE";
public static final int STATE_LINK_LOSS = -1;
public static final int STATE_DISCONNECTED = 0;
public static final int STATE_CONNECTED = 1;
public static final int STATE_CONNECTING = 2;
public static final int STATE_DISCONNECTING = 3;
private LoggableBleManager<BleManagerCallbacks> mBleManager;
private Handler mHandler;
protected boolean mBound;
private boolean mActivityIsChangingConfiguration;
private BluetoothDevice mBluetoothDevice;
private String mDeviceName;
private ILogSession mLogSession;
private final BroadcastReceiver mBluetoothStateBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
final ILogger logger = getBinder();
final String stateString = "[Broadcast] Action received: " + BluetoothAdapter.ACTION_STATE_CHANGED + ", state changed to " + state2String(state);
logger.log(Log.DEBUG, stateString);
switch (state) {
case BluetoothAdapter.STATE_ON:
onBluetoothEnabled();
break;
case BluetoothAdapter.STATE_TURNING_OFF:
case BluetoothAdapter.STATE_OFF:
onBluetoothDisabled();
break;
}
}
private String state2String(final int state) {
switch (state) {
case BluetoothAdapter.STATE_TURNING_ON:
return "TURNING ON";
case BluetoothAdapter.STATE_ON:
return "ON";
case BluetoothAdapter.STATE_TURNING_OFF:
return "TURNING OFF";
case BluetoothAdapter.STATE_OFF:
return "OFF";
default:
return "UNKNOWN (" + state + ")";
}
}
};
public class LocalBinder extends Binder implements ILogger {
/**
* Disconnects from the sensor.
*/
public final void disconnect() {
final int state = mBleManager.getConnectionState();
if (state == BluetoothGatt.STATE_DISCONNECTED || state == BluetoothGatt.STATE_DISCONNECTING) {
mBleManager.close();
onDeviceDisconnected(mBluetoothDevice);
return;
}
mBleManager.disconnect().enqueue();
}
/**
* Sets whether the bound activity if changing configuration or not.
* If <code>false</code>, we will turn off battery level notifications in onUnbind(..) method below.
* @param changing true if the bound activity is finishing
*/
public void setActivityIsChangingConfiguration(final boolean changing) {
mActivityIsChangingConfiguration = changing;
}
/**
* Returns the device address
*
* @return device address
*/
public String getDeviceAddress() {
return mBluetoothDevice.getAddress();
}
/**
* Returns the device name
*
* @return the device name
*/
public String getDeviceName() {
return mDeviceName;
}
/**
* Returns the Bluetooth device
*
* @return the Bluetooth device
*/
public BluetoothDevice getBluetoothDevice() {
return mBluetoothDevice;
}
/**
* Returns <code>true</code> if the device is connected to the sensor.
*
* @return <code>true</code> if device is connected to the sensor, <code>false</code> otherwise
*/
public boolean isConnected() {
return mBleManager.isConnected();
}
/**
* Returns the connection state of given device.
* @return the connection state, as in {@link BleManager#getConnectionState()}.
*/
public int getConnectionState() {
return mBleManager.getConnectionState();
}
/**
* Returns the log session that can be used to append log entries.
* The log session is created when the service is being created.
* The method returns <code>null</code> if the nRF Logger app was not installed.
*
* @return the log session
*/
public ILogSession getLogSession() {
return mLogSession;
}
@Override
public void log(final int level, @NonNull final String message) {
Logger.log(mLogSession, level, message);
}
@Override
public void log(final int level, final @StringRes int messageRes, final Object... params) {
Logger.log(mLogSession, level, messageRes, params);
}
}
/**
* Returns a handler that is created in onCreate().
* The handler may be used to postpone execution of some operations or to run them in UI thread.
*/
protected Handler getHandler() {
return mHandler;
}
/**
* Returns the binder implementation. This must return class implementing the additional manager interface that may be used in the bound activity.
*
* @return the service binder
*/
protected LocalBinder getBinder() {
// default implementation returns the basic binder. You can overwrite the LocalBinder with your own, wider implementation
return new LocalBinder();
}
@Override
public IBinder onBind(final Intent intent) {
mBound = true;
return getBinder();
}
@Override
public final void onRebind(final Intent intent) {
mBound = true;
if (!mActivityIsChangingConfiguration)
onRebind();
}
/**
* Called when the activity has rebound to the service after being recreated.
* This method is not called when the activity was killed to be recreated when the phone orientation changed
* if prior to being killed called {@link BleProfileService.LocalBinder#setActivityIsChangingConfiguration(boolean)} with parameter true.
*/
protected void onRebind() {
// empty default implementation
}
@Override
public final boolean onUnbind(final Intent intent) {
mBound = false;
if (!mActivityIsChangingConfiguration)
onUnbind();
// We want the onRebind method be called if anything else binds to it again
return true;
}
/**
* Called when the activity has unbound from the service before being finished.
* This method is not called when the activity is killed to be recreated when the phone orientation changed.
*/
protected void onUnbind() {
// empty default implementation
}
@SuppressWarnings("unchecked")
@Override
public void onCreate() {
super.onCreate();
mHandler = new Handler();
// Initialize the manager
mBleManager = initializeManager();
mBleManager.setGattCallbacks(this);
// Register broadcast receivers
registerReceiver(mBluetoothStateBroadcastReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
// Service has now been created
onServiceCreated();
// Call onBluetoothEnabled if Bluetooth enabled
final BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter.isEnabled()) {
onBluetoothEnabled();
}
}
/**
* Called when the service has been created, before the {@link #onBluetoothEnabled()} is called.
*/
protected void onServiceCreated() {
// empty default implementation
}
/**
* Initializes the Ble Manager responsible for connecting to a single device.
* @return a new BleManager object
*/
@SuppressWarnings("rawtypes")
protected abstract LoggableBleManager initializeManager();
/**
* This method returns whether autoConnect option should be used.
*
* @return true to use autoConnect feature, false (default) otherwise.
*/
protected boolean shouldAutoConnect() {
return false;
}
@Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
if (intent == null || !intent.hasExtra(EXTRA_DEVICE_ADDRESS))
throw new UnsupportedOperationException("No device address at EXTRA_DEVICE_ADDRESS key");
final Uri logUri = intent.getParcelableExtra(EXTRA_LOG_URI);
mLogSession = Logger.openSession(getApplicationContext(), logUri);
mDeviceName = intent.getStringExtra(EXTRA_DEVICE_NAME);
Logger.i(mLogSession, "Service started");
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
final String deviceAddress = intent.getStringExtra(EXTRA_DEVICE_ADDRESS);
mBluetoothDevice = adapter.getRemoteDevice(deviceAddress);
mBleManager.setLogger(mLogSession);
onServiceStarted();
mBleManager.connect(mBluetoothDevice)
.useAutoConnect(shouldAutoConnect())
.retry(3, 100)
.enqueue();
return START_REDELIVER_INTENT;
}
/**
* Called when the service has been started. The device name and address are set.
* The BLE Manager will try to connect to the device after this method finishes.
*/
protected void onServiceStarted() {
// empty default implementation
}
@Override
public void onTaskRemoved(final Intent rootIntent) {
super.onTaskRemoved(rootIntent);
// This method is called when user removed the app from Recents.
// By default, the service will be killed and recreated immediately after that.
// However, all managed devices will be lost and devices will be disconnected.
stopSelf();
}
@Override
public void onDestroy() {
super.onDestroy();
// Unregister broadcast receivers
unregisterReceiver(mBluetoothStateBroadcastReceiver);
// shutdown the manager
mBleManager.close();
Logger.i(mLogSession, "Service destroyed");
mBleManager = null;
mBluetoothDevice = null;
mDeviceName = null;
mLogSession = null;
mHandler = null;
}
/**
* Method called when Bluetooth Adapter has been disabled.
*/
protected void onBluetoothDisabled() {
// empty default implementation
}
/**
* This method is called when Bluetooth Adapter has been enabled and
* after the service was created if Bluetooth Adapter was enabled at that moment.
* This method could initialize all Bluetooth related features, for example open the GATT server.
*/
protected void onBluetoothEnabled() {
// empty default implementation
}
@Override
public void onDeviceConnecting(@NonNull final BluetoothDevice device) {
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_CONNECTING);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
@Override
public void onDeviceConnected(@NonNull final BluetoothDevice device) {
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_CONNECTED);
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
broadcast.putExtra(EXTRA_DEVICE_NAME, mDeviceName);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
@Override
public void onDeviceDisconnecting(@NonNull final BluetoothDevice device) {
// Notify user about changing the state to DISCONNECTING
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_DISCONNECTING);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
/**
* This method should return false if the service needs to do some asynchronous work after if has disconnected from the device.
* In that case the {@link #stopService()} method must be called when done.
* @return true (default) to automatically stop the service when device is disconnected. False otherwise.
*/
protected boolean stopWhenDisconnected() {
return true;
}
@Override
public void onDeviceDisconnected(@NonNull final BluetoothDevice device) {
// Note 1: Do not use the device argument here unless you change calling onDeviceDisconnected from the binder above
// Note 2: if BleManager#shouldAutoConnect() for this device returned true, this callback will be
// invoked ONLY when user requested disconnection (using Disconnect button). If the device
// disconnects due to a link loss, the onLinkLossOccurred(BluetoothDevice) method will be called instead.
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_DISCONNECTED);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
if (stopWhenDisconnected())
stopService();
}
protected void stopService() {
// user requested disconnection. We must stop the service
Logger.v(mLogSession, "Stopping service...");
stopSelf();
}
@Override
public void onLinkLossOccurred(@NonNull final BluetoothDevice device) {
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_LINK_LOSS);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
@Override
public void onServicesDiscovered(@NonNull final BluetoothDevice device, final boolean optionalServicesFound) {
final Intent broadcast = new Intent(BROADCAST_SERVICES_DISCOVERED);
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
broadcast.putExtra(EXTRA_SERVICE_PRIMARY, true);
broadcast.putExtra(EXTRA_SERVICE_SECONDARY, optionalServicesFound);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
@Override
public void onDeviceReady(@NonNull final BluetoothDevice device) {
final Intent broadcast = new Intent(BROADCAST_DEVICE_READY);
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
@Override
public void onDeviceNotSupported(@NonNull final BluetoothDevice device) {
final Intent broadcast = new Intent(BROADCAST_SERVICES_DISCOVERED);
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
broadcast.putExtra(EXTRA_SERVICE_PRIMARY, false);
broadcast.putExtra(EXTRA_SERVICE_SECONDARY, false);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
// no need for disconnecting, it will be disconnected by the manager automatically
}
@Override
public void onBatteryValueReceived(@NonNull final BluetoothDevice device, final int value) {
final Intent broadcast = new Intent(BROADCAST_BATTERY_LEVEL);
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
broadcast.putExtra(EXTRA_BATTERY_LEVEL, value);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
@Override
public void onBondingRequired(@NonNull final BluetoothDevice device) {
showToast(no.Reader.android.iisc.R.string.bonding);
final Intent broadcast = new Intent(BROADCAST_BOND_STATE);
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
broadcast.putExtra(EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDING);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
@Override
public void onBonded(@NonNull final BluetoothDevice device) {
showToast(no.Reader.android.iisc.R.string.bonding);
final Intent broadcast = new Intent(BROADCAST_BOND_STATE);
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
broadcast.putExtra(EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDED);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
@Override
public void onBondingFailed(@NonNull final BluetoothDevice device) {
showToast(no.Reader.android.iisc.R.string.bonding_failed);
final Intent broadcast = new Intent(BROADCAST_BOND_STATE);
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
broadcast.putExtra(EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
@Override
public void onError(@NonNull final BluetoothDevice device, @NonNull final String message, final int errorCode) {
final Intent broadcast = new Intent(BROADCAST_ERROR);
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
broadcast.putExtra(EXTRA_ERROR_MESSAGE, message);
broadcast.putExtra(EXTRA_ERROR_CODE, errorCode);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
/**
* Shows a message as a Toast notification. This method is thread safe, you can call it from any thread
*
* @param messageResId
* an resource id of the message to be shown
*/
protected void showToast(final int messageResId) {
mHandler.post(() -> Toast.makeText(BleProfileService.this, messageResId, Toast.LENGTH_SHORT).show());
}
/**
* Shows a message as a Toast notification. This method is thread safe, you can call it from any thread
*
* @param message
* a message to be shown
*/
protected void showToast(final String message) {
mHandler.post(() -> Toast.makeText(BleProfileService.this, message, Toast.LENGTH_SHORT).show());
}
/**
* Returns the log session that can be used to append log entries. The method returns <code>null</code> if the nRF Logger app was not installed. It is safe to use logger when
* {@link #onServiceStarted()} has been called.
*
* @return the log session
*/
protected ILogSession getLogSession() {
return mLogSession;
}
/**
* Returns the device address
*
* @return device address
*/
protected String getDeviceAddress() {
return mBluetoothDevice.getAddress();
}
/**
* Returns the Bluetooth device object
*
* @return bluetooth device
*/
protected BluetoothDevice getBluetoothDevice() {
return mBluetoothDevice;
}
/**
* Returns the device name
*
* @return the device name
*/
protected String getDeviceName() {
return mDeviceName;
}
/**
* Returns <code>true</code> if the device is connected to the sensor.
*
* @return <code>true</code> if device is connected to the sensor, <code>false</code> otherwise
*/
protected boolean isConnected() {
return mBleManager != null && mBleManager.isConnected();
}
}

View File

@@ -0,0 +1,626 @@
package no.Reader.android.iisc.profile;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import androidx.annotation.NonNull;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.util.UUID;
import no.nordicsemi.android.ble.BleManagerCallbacks;
import no.nordicsemi.android.log.ILogSession;
import no.nordicsemi.android.log.LocalLogSession;
import no.nordicsemi.android.log.Logger;
import no.Reader.android.iisc.R;
import no.Reader.android.iisc.scanner.ScannerFragment;
import no.Reader.android.iisc.DebugLogger;
/**
* <p>
* The {@link BleProfileServiceReadyActivity} activity is designed to be the base class for profile activities that uses services in order to connect to the
* device. When user press CONNECT button a service is created and the activity binds to it. The service tries to connect to the service and notifies the
* activity using Local Broadcasts ({@link LocalBroadcastManager}). See {@link BleProfileService} for messages. If the device is not in range it will listen for
* it and connect when it become visible. The service exists until user will press DISCONNECT button.
* </p>
* <p>
* When user closes the activity (f.e. by pressing Back button) while being connected, the Service remains working. It's still connected to the device or still
* listens for it. When entering back to the activity, activity will to bind to the service and refresh UI.
* </p>
*/
@SuppressWarnings("unused")
public abstract class BleProfileServiceReadyActivity<E extends BleProfileService.LocalBinder> extends AppCompatActivity implements
ScannerFragment.OnDeviceSelectedListener, BleManagerCallbacks {
private static final String TAG = "BleProfileServiceReadyActivity";
private static final String SIS_DEVICE_NAME = "device_name";
private static final String SIS_DEVICE = "device";
private static final String LOG_URI = "log_uri";
protected static final int REQUEST_ENABLE_BT = 2;
private E mService;
private TextView mDeviceNameView;
private Button mConnectButton;
private ILogSession mLogSession;
private BluetoothDevice mBluetoothDevice;
private String mDeviceName;
private final BroadcastReceiver mCommonBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
// Check if the broadcast applies the connected device
if (!isBroadcastForThisDevice(intent))
return;
final BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BleProfileService.EXTRA_DEVICE);
final String action = intent.getAction();
switch (action) {
case BleProfileService.BROADCAST_CONNECTION_STATE: {
final int state = intent.getIntExtra(BleProfileService.EXTRA_CONNECTION_STATE, BleProfileService.STATE_DISCONNECTED);
switch (state) {
case BleProfileService.STATE_CONNECTED: {
mDeviceName = intent.getStringExtra(BleProfileService.EXTRA_DEVICE_NAME);
onDeviceConnected(bluetoothDevice);
break;
}
case BleProfileService.STATE_DISCONNECTED: {
onDeviceDisconnected(bluetoothDevice);
mDeviceName = null;
break;
}
case BleProfileService.STATE_LINK_LOSS: {
onLinkLossOccurred(bluetoothDevice);
break;
}
case BleProfileService.STATE_CONNECTING: {
onDeviceConnecting(bluetoothDevice);
break;
}
case BleProfileService.STATE_DISCONNECTING: {
onDeviceDisconnecting(bluetoothDevice);
break;
}
default:
// there should be no other actions
break;
}
break;
}
case BleProfileService.BROADCAST_SERVICES_DISCOVERED: {
final boolean primaryService = intent.getBooleanExtra(BleProfileService.EXTRA_SERVICE_PRIMARY, false);
final boolean secondaryService = intent.getBooleanExtra(BleProfileService.EXTRA_SERVICE_SECONDARY, false);
if (primaryService) {
onServicesDiscovered(bluetoothDevice, secondaryService);
} else {
onDeviceNotSupported(bluetoothDevice);
}
break;
}
case BleProfileService.BROADCAST_DEVICE_READY: {
onDeviceReady(bluetoothDevice);
break;
}
case BleProfileService.BROADCAST_BOND_STATE: {
final int state = intent.getIntExtra(BleProfileService.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE);
switch (state) {
case BluetoothDevice.BOND_BONDING:
onBondingRequired(bluetoothDevice);
break;
case BluetoothDevice.BOND_BONDED:
onBonded(bluetoothDevice);
break;
}
break;
}
case BleProfileService.BROADCAST_ERROR: {
final String message = intent.getStringExtra(BleProfileService.EXTRA_ERROR_MESSAGE);
final int errorCode = intent.getIntExtra(BleProfileService.EXTRA_ERROR_CODE, 0);
onError(bluetoothDevice, message, errorCode);
break;
}
}
}
};
private ServiceConnection mServiceConnection = new ServiceConnection() {
@SuppressWarnings("unchecked")
@Override
public void onServiceConnected(final ComponentName name, final IBinder service) {
final E bleService = mService = (E) service;
mBluetoothDevice = bleService.getBluetoothDevice();
mLogSession = mService.getLogSession();
Logger.d(mLogSession, "Activity bound to the service");
onServiceBound(bleService);
// Update UI
mDeviceName = bleService.getDeviceName();
mDeviceNameView.setText(mDeviceName);
mConnectButton.setText(R.string.action_disconnect);
// And notify user if device is connected
if (bleService.isConnected()) {
onDeviceConnected(mBluetoothDevice);
} else {
// If the device is not connected it means that either it is still connecting,
// or the link was lost and service is trying to connect to it (autoConnect=true).
onDeviceConnecting(mBluetoothDevice);
}
}
@Override
public void onServiceDisconnected(final ComponentName name) {
// Note: this method is called only when the service is killed by the system,
// not when it stops itself or is stopped by the activity.
// It will be called only when there is critically low memory, in practice never
// when the activity is in foreground.
Logger.d(mLogSession, "Activity disconnected from the service");
mDeviceNameView.setText(getDefaultDeviceName());
mConnectButton.setText(R.string.action_connect);
mService = null;
mDeviceName = null;
mBluetoothDevice = null;
mLogSession = null;
onServiceUnbound();
}
};
@Override
protected final void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ensureBLESupported();
if (!isBLEEnabled()) {
showBLEDialog();
}
// Restore the old log session
if (savedInstanceState != null) {
final Uri logUri = savedInstanceState.getParcelable(LOG_URI);
mLogSession = Logger.openSession(getApplicationContext(), logUri);
}
// In onInitialize method a final class may register local broadcast receivers that will listen for events from the service
onInitialize(savedInstanceState);
// The onCreateView class should... create the view
onCreateView(savedInstanceState);
/*final Toolbar toolbar = findViewById(R.id.toolbar_actionbar);
setSupportActionBar(toolbar);
*/
// Common nRF Toolbox view references are obtained here
setUpView();
// View is ready to be used
onViewCreated(savedInstanceState);
LocalBroadcastManager.getInstance(this).registerReceiver(mCommonBroadcastReceiver, makeIntentFilter());
}
@Override
protected void onStart() {
super.onStart();
/*
* If the service has not been started before, the following lines will not start it.
* However, if it's running, the Activity will bind to it and notified via mServiceConnection.
*/
final Intent service = new Intent(this, getServiceClass());
// We pass 0 as a flag so the service will not be created if not exists.
bindService(service, mServiceConnection, 0);
/*
* When user exited the UARTActivity while being connected, the log session is kept in
* the service. We may not get it before binding to it so in this case this event will
* not be logged (mLogSession is null until onServiceConnected(..) is called).
* It will, however, be logged after the orientation changes.
*/
}
@Override
protected void onStop() {
super.onStop();
try {
// We don't want to perform some operations (e.g. disable Battery Level notifications)
// in the service if we are just rotating the screen. However, when the activity will
// disappear, we may want to disable some device features to reduce the battery
// consumption.
if (mService != null)
mService.setActivityIsChangingConfiguration(isChangingConfigurations());
unbindService(mServiceConnection);
mService = null;
Logger.d(mLogSession, "Activity unbound from the service");
onServiceUnbound();
mDeviceName = null;
mBluetoothDevice = null;
mLogSession = null;
} catch (final IllegalArgumentException e) {
// do nothing, we were not connected to the sensor
}
}
@Override
protected void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mCommonBroadcastReceiver);
}
private static IntentFilter makeIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BleProfileService.BROADCAST_CONNECTION_STATE);
intentFilter.addAction(BleProfileService.BROADCAST_SERVICES_DISCOVERED);
intentFilter.addAction(BleProfileService.BROADCAST_DEVICE_READY);
intentFilter.addAction(BleProfileService.BROADCAST_BOND_STATE);
intentFilter.addAction(BleProfileService.BROADCAST_ERROR);
return intentFilter;
}
/**
* Called when activity binds to the service. The parameter is the object returned in {@link Service#onBind(Intent)} method in your service. The method is
* called when device gets connected or is created while sensor was connected before. You may use the binder as a sensor interface.
*/
protected abstract void onServiceBound(E binder);
/**
* Called when activity unbinds from the service. You may no longer use this binder because the sensor was disconnected. This method is also called when you
* leave the activity being connected to the sensor in the background.
*/
protected abstract void onServiceUnbound();
/**
* Returns the service class for sensor communication. The service class must derive from {@link BleProfileService} in order to operate with this class.
*
* @return the service class
*/
protected abstract Class<? extends BleProfileService> getServiceClass();
/**
* Returns the service interface that may be used to communicate with the sensor. This will return <code>null</code> if the device is disconnected from the
* sensor.
*
* @return the service binder or <code>null</code>
*/
protected E getService() {
return mService;
}
/**
* You may do some initialization here. This method is called from {@link #onCreate(Bundle)} before the view was created.
*/
protected void onInitialize(final Bundle savedInstanceState) {
// empty default implementation
}
/**
* Called from {@link #onCreate(Bundle)}. This method should build the activity UI, i.e. using {@link #setContentView(int)}.
* Use to obtain references to views. Connect/Disconnect button, the device name view are manager automatically.
*
* @param savedInstanceState contains the data it most recently supplied in {@link #onSaveInstanceState(Bundle)}.
* Note: <b>Otherwise it is null</b>.
*/
protected abstract void onCreateView(final Bundle savedInstanceState);
/**
* Called after the view has been created.
*
* @param savedInstanceState contains the data it most recently supplied in {@link #onSaveInstanceState(Bundle)}.
* Note: <b>Otherwise it is null</b>.
*/
protected void onViewCreated(final Bundle savedInstanceState) {
// empty default implementation
}
/**
* Called after the view and the toolbar has been created.
*/
protected final void setUpView() {
// set GUI
// getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mConnectButton = findViewById(R.id.action_connect);
mDeviceNameView = findViewById(R.id.device_name);
}
@Override
protected void onSaveInstanceState(final Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(SIS_DEVICE_NAME, mDeviceName);
outState.putParcelable(SIS_DEVICE, mBluetoothDevice);
if (mLogSession != null)
outState.putParcelable(LOG_URI, mLogSession.getSessionUri());
}
@Override
protected void onRestoreInstanceState(final @NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mDeviceName = savedInstanceState.getString(SIS_DEVICE_NAME);
mBluetoothDevice = savedInstanceState.getParcelable(SIS_DEVICE);
}
/**
* Use this method to handle menu actions other than home and about.
*
* @param itemId the menu item id
* @return <code>true</code> if action has been handled
*/
protected boolean onOptionsItemSelected(final int itemId) {
// Overwrite when using menu other than R.menu.help
return false;
}
/**
* Called when user press CONNECT or DISCONNECT button. See layout files -> onClick attribute.
*/
public void onConnectClicked(final View view) {
if (isBLEEnabled()) {
if (mService == null) {
setDefaultUI();
showDeviceScanningDialog(getFilterUUID());
} else {
mService.disconnect();
}
} else {
showBLEDialog();
}
}
/**
* Returns the title resource id that will be used to create logger session. If 0 is returned (default) logger will not be used.
*
* @return the title resource id
*/
protected int getLoggerProfileTitle() {
return 0;
}
/**
* This method may return the local log content provider authority if local log sessions are supported.
*
* @return local log session content provider URI
*/
protected Uri getLocalAuthorityLogger() {
return null;
}
@Override
public void onDeviceSelected(final BluetoothDevice device, final String name) {
final int titleId = getLoggerProfileTitle();
if (titleId > 0) {
mLogSession = Logger.newSession(getApplicationContext(), getString(titleId), device.getAddress(), name);
// If nRF Logger is not installed we may want to use local logger
if (mLogSession == null && getLocalAuthorityLogger() != null) {
mLogSession = LocalLogSession.newSession(getApplicationContext(), getLocalAuthorityLogger(), device.getAddress(), name);
}
}
mBluetoothDevice = device;
mDeviceName = name;
// The device may not be in the range but the service will try to connect to it if it reach it
Logger.d(mLogSession, "Creating service...");
final Intent service = new Intent(this, getServiceClass());
service.putExtra(BleProfileService.EXTRA_DEVICE_ADDRESS, device.getAddress());
service.putExtra(BleProfileService.EXTRA_DEVICE_NAME, name);
if (mLogSession != null)
service.putExtra(BleProfileService.EXTRA_LOG_URI, mLogSession.getSessionUri());
startService(service);
Logger.d(mLogSession, "Binding to the service...");
bindService(service, mServiceConnection, 0);
}
@Override
public void onDialogCanceled() {
// do nothing
}
@Override
public void onDeviceConnecting(final BluetoothDevice device) {
mDeviceNameView.setText(mDeviceName != null ? mDeviceName : getString(R.string.not_available));
mConnectButton.setText(R.string.action_connecting);
}
@Override
public void onDeviceConnected(final BluetoothDevice device) {
mDeviceNameView.setText(mDeviceName);
mConnectButton.setText(R.string.action_disconnect);
}
@Override
public void onDeviceDisconnecting(final BluetoothDevice device) {
mConnectButton.setText(R.string.action_disconnecting);
}
@Override
public void onDeviceDisconnected(final BluetoothDevice device) {
mConnectButton.setText(R.string.action_connect);
mDeviceNameView.setText(getDefaultDeviceName());
try {
Logger.d(mLogSession, "Unbinding from the service...");
unbindService(mServiceConnection);
mService = null;
Logger.d(mLogSession, "Activity unbound from the service");
onServiceUnbound();
mDeviceName = null;
mBluetoothDevice = null;
mLogSession = null;
} catch (final IllegalArgumentException e) {
// do nothing. This should never happen but does...
}
}
@Override
public void onLinkLossOccurred(final BluetoothDevice device) {
// empty default implementation
}
@Override
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
// empty default implementation
}
@Override
public void onDeviceReady(final BluetoothDevice device) {
// empty default implementation
}
@Override
public void onBondingRequired(final BluetoothDevice device) {
// empty default implementation
}
@Override
public void onBonded(final BluetoothDevice device) {
// empty default implementation
}
@Override
public void onBondingFailed(final BluetoothDevice device) {
// empty default implementation
}
@Override
public void onError(final BluetoothDevice device, final String message, final int errorCode) {
DebugLogger.e(TAG, "Error occurred: " + message + ", error code: " + errorCode);
showToast(message + " (" + errorCode + ")");
}
@Override
public void onDeviceNotSupported(final BluetoothDevice device) {
showToast(R.string.not_supported);
}
/**
* Shows a message as a Toast notification. This method is thread safe, you can call it from any thread
*
* @param message a message to be shown
*/
protected void showToast(final String message) {
runOnUiThread(() -> Toast.makeText(BleProfileServiceReadyActivity.this, message, Toast.LENGTH_LONG).show());
}
/**
* Shows a message as a Toast notification. This method is thread safe, you can call it from any thread
*
* @param messageResId an resource id of the message to be shown
*/
protected void showToast(final int messageResId) {
runOnUiThread(() -> Toast.makeText(BleProfileServiceReadyActivity.this, messageResId, Toast.LENGTH_SHORT).show());
}
/**
* Returns <code>true</code> if the device is connected. Services may not have been discovered yet.
*/
protected boolean isDeviceConnected() {
return mService != null && mService.isConnected();
}
/**
* Returns the name of the device that the phone is currently connected to or was connected last time
*/
protected String getDeviceName() {
return mDeviceName;
}
/**
* Restores the default UI before reconnecting
*/
protected abstract void setDefaultUI();
/**
* Returns the default device name resource id. The real device name is obtained when connecting to the device. This one is used when device has
* disconnected.
*
* @return the default device name resource id
*/
protected abstract int getDefaultDeviceName();
/**
* Returns the string resource id that will be shown in About box
*
* @return the about resource id
*/
/**
* The UUID filter is used to filter out available devices that does not have such UUID in their advertisement packet. See also:
* {@link #isChangingConfigurations()}.
*
* @return the required UUID or <code>null</code>
*/
protected abstract UUID getFilterUUID();
/**
* Checks the {@link BleProfileService#EXTRA_DEVICE} in the given intent and compares it with the connected BluetoothDevice object.
* @param intent intent received via a broadcast from the service
* @return true if the data in the intent apply to the connected device, false otherwise
*/
protected boolean isBroadcastForThisDevice(final Intent intent) {
final BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BleProfileService.EXTRA_DEVICE);
return mBluetoothDevice != null && mBluetoothDevice.equals(bluetoothDevice);
}
/**
* Shows the scanner fragment.
*
* @param filter the UUID filter used to filter out available devices. The fragment will always show all bonded devices as there is no information about their
* services
* @see #getFilterUUID()
*/
private void showDeviceScanningDialog(final UUID filter) {
final ScannerFragment dialog = ScannerFragment.getInstance(filter);
dialog.show(getSupportFragmentManager(), "scan_fragment");
}
/**
* Returns the log session. Log session is created when the device was selected using the {@link ScannerFragment} and released when user press DISCONNECT.
*
* @return the logger session or <code>null</code>
*/
protected ILogSession getLogSession() {
return mLogSession;
}
private void ensureBLESupported() {
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.no_ble, Toast.LENGTH_LONG).show();
finish();
}
}
protected boolean isBLEEnabled() {
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
final BluetoothAdapter adapter = bluetoothManager.getAdapter();
return adapter != null && adapter.isEnabled();
}
protected void showBLEDialog() {
final Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
}
}

View File

@@ -0,0 +1,48 @@
package no.Reader.android.iisc.profile;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.util.Log;
import no.nordicsemi.android.ble.BleManager;
import no.nordicsemi.android.ble.BleManagerCallbacks;
import no.nordicsemi.android.log.ILogSession;
import no.nordicsemi.android.log.LogContract;
import no.nordicsemi.android.log.Logger;
/**
* The manager that logs to nRF Logger. If nRF Logger is not installed, logs are ignored.
*
* @param <T> the callbacks class.
*/
public abstract class LoggableBleManager<T extends BleManagerCallbacks> extends BleManager<T> {
private ILogSession mLogSession;
/**
* The manager constructor.
* <p>
* After constructing the manager, the callbacks object must be set with
* {@link #setGattCallbacks(BleManagerCallbacks)}.
*
* @param context the context.
*/
public LoggableBleManager(@NonNull final Context context) {
super(context);
}
/**
* Sets the log session to log into.
*
* @param session nRF Logger log session to log inti, or null, if nRF Logger is not installed.
*/
public void setLogger(@Nullable final ILogSession session) {
mLogSession = session;
}
@Override
public void log(final int priority, @NonNull final String message) {
Logger.log(mLogSession, LogContract.Log.Level.fromPriority(priority), message);
Log.println(priority, "BleManager", message);
}
}

View File

@@ -0,0 +1,615 @@
package no.Reader.android.iisc.profile.multiconnect;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.util.Log;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import no.Reader.android.iisc.profile.LoggableBleManager;
import no.nordicsemi.android.ble.BleManager;
import no.nordicsemi.android.ble.BleManagerCallbacks;
import no.nordicsemi.android.ble.utils.ILogger;
import no.nordicsemi.android.log.ILogSession;
public abstract class BleMulticonnectProfileService extends Service implements BleManagerCallbacks {
@SuppressWarnings("unused")
private static final String TAG = "BleMultiProfileService";
public static final String BROADCAST_CONNECTION_STATE = "no.Reader.android.iisc.BROADCAST_CONNECTION_STATE";
public static final String BROADCAST_SERVICES_DISCOVERED = "no.Reader.android.iisc.BROADCAST_SERVICES_DISCOVERED";
public static final String BROADCAST_DEVICE_READY = "no.Reader.android.iisc.DEVICE_READY";
public static final String BROADCAST_BOND_STATE = "no.Reader.android.iisc.BROADCAST_BOND_STATE";
@Deprecated
public static final String BROADCAST_BATTERY_LEVEL = "no.Reader.android.iisc.BROADCAST_BATTERY_LEVEL";
public static final String BROADCAST_ERROR = "no.Reader.android.iisc.BROADCAST_ERROR";
public static final String EXTRA_DEVICE = "no.Reader.android.iisc.EXTRA_DEVICE";
public static final String EXTRA_CONNECTION_STATE = "no.Reader.android.iisc.EXTRA_CONNECTION_STATE";
public static final String EXTRA_BOND_STATE = "no.Reader.android.iisc.EXTRA_BOND_STATE";
public static final String EXTRA_SERVICE_PRIMARY = "no.Reader.android.iisc.EXTRA_SERVICE_PRIMARY";
public static final String EXTRA_SERVICE_SECONDARY = "no.Reader.android.iisc.EXTRA_SERVICE_SECONDARY";
@Deprecated
public static final String EXTRA_BATTERY_LEVEL = "no.Reader.android.iisc.EXTRA_BATTERY_LEVEL";
public static final String EXTRA_ERROR_MESSAGE = "no.Reader.android.iisc.EXTRA_ERROR_MESSAGE";
public static final String EXTRA_ERROR_CODE = "no.Reader.android.iisc.EXTRA_ERROR_CODE";
public static final int STATE_LINK_LOSS = -1;
public static final int STATE_DISCONNECTED = 0;
public static final int STATE_CONNECTED = 1;
public static final int STATE_CONNECTING = 2;
public static final int STATE_DISCONNECTING = 3;
private HashMap<BluetoothDevice, LoggableBleManager<BleManagerCallbacks>> bleManagers;
private List<BluetoothDevice> managedDevices;
private Handler handler;
protected boolean bound;
private boolean activityIsChangingConfiguration;
private final BroadcastReceiver bluetoothStateBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
final int previousState = intent.getIntExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, BluetoothAdapter.STATE_OFF);
switch (state) {
case BluetoothAdapter.STATE_ON:
// On older phones (tested on Nexus 4 with Android 5.0.1) the Bluetooth requires some time
// after it has been enabled before some operations can start. Starting the GATT server here
// without a delay is very likely to cause a DeadObjectException from BluetoothManager#openGattServer(...).
handler.postDelayed(() -> onBluetoothEnabled(), 600);
break;
case BluetoothAdapter.STATE_TURNING_OFF:
case BluetoothAdapter.STATE_OFF:
if (previousState != BluetoothAdapter.STATE_TURNING_OFF && previousState != BluetoothAdapter.STATE_OFF)
onBluetoothDisabled();
break;
}
}
};
public class LocalBinder extends Binder implements ILogger, IDeviceLogger {
/**
* Returns an unmodifiable list of devices managed by the service.
* The returned devices do not need to be connected at tha moment. Each of them was however created
* using {@link #connect(BluetoothDevice)} method so they might have been connected before and disconnected.
* @return unmodifiable list of devices managed by the service
*/
public final List<BluetoothDevice> getManagedDevices() {
return Collections.unmodifiableList(managedDevices);
}
/**
* Connects to the given device. If the device is already connected this method does nothing.
* @param device target Bluetooth device
*/
public void connect(final BluetoothDevice device) {
connect(device, null);
}
/**
* Adds the given device to managed and stars connecting to it. If the device is already connected this method does nothing.
* @param device target Bluetooth device
* @param session log session that has to be used by the device
*/
@SuppressWarnings("unchecked")
public void connect(final BluetoothDevice device, final ILogSession session) {
// If a device is in managed devices it means that it's already connected, or was connected
// using autoConnect and the link was lost but Android is already trying to connect to it.
if (managedDevices.contains(device))
return;
managedDevices.add(device);
LoggableBleManager<BleManagerCallbacks> manager = bleManagers.get(device);
if (manager == null) {
bleManagers.put(device, manager = initializeManager());
manager.setGattCallbacks(BleMulticonnectProfileService.this);
}
manager.setLogger(session);
manager.connect(device)
.retry(2, 100)
.useAutoConnect(shouldAutoConnect())
.timeout(10000)
.fail((d, status) -> {
managedDevices.remove(device);
bleManagers.remove(device);
})
.enqueue();
}
/**
* Disconnects the given device and removes the associated BleManager object.
* If the list of BleManagers is empty while the last activity unbinds from the service,
* the service will stop itself.
* @param device target device to disconnect and forget
*/
public void disconnect(final BluetoothDevice device) {
final BleManager manager = bleManagers.get(device);
if (manager != null && manager.isConnected()) {
manager.disconnect().enqueue();
}
managedDevices.remove(device);
}
/**
* Returns <code>true</code> if the device is connected to the sensor.
* @param device the target device
* @return <code>true</code> if device is connected to the sensor, <code>false</code> otherwise
*/
public final boolean isConnected(final BluetoothDevice device) {
final BleManager manager = bleManagers.get(device);
return manager != null && manager.isConnected();
}
/**
* Returns <code>true</code> if the device has finished initializing.
* @param device the target device
* @return <code>true</code> if device is connected to the sensor and has finished
* initializing. False otherwise.
*/
public final boolean isReady(final BluetoothDevice device) {
final BleManager manager = bleManagers.get(device);
return manager != null && manager.isReady();
}
/**
* Returns the connection state of given device.
* @param device the target device
* @return the connection state, as in {@link BleManager#getConnectionState()}.
*/
@SuppressWarnings("unused")
public final int getConnectionState(final BluetoothDevice device) {
final BleManager manager = bleManagers.get(device);
return manager != null ? manager.getConnectionState() : BluetoothGatt.STATE_DISCONNECTED;
}
/**
* Returns the last received battery level value.
* @param device the device of which battery level should be returned
* @return battery value or -1 if no value was received or Battery Level characteristic was not found
* @deprecated Keep battery value in your manager instead.
*/
@SuppressWarnings("deprecation")
@Deprecated
public int getBatteryValue(final BluetoothDevice device) {
final BleManager manager = bleManagers.get(device);
if (manager != null)
return manager.getBatteryValue();
return 0;
}
/**
* Sets whether the bound activity if changing configuration or not.
* If <code>false</code>, we will turn off battery level notifications in onUnbind(..) method below.
* @param changing true if the bound activity is finishing
*/
@SuppressWarnings("WeakerAccess")
public final void setActivityIsChangingConfiguration(final boolean changing) {
activityIsChangingConfiguration = changing;
}
@Override
public void log(@NonNull final BluetoothDevice device, final int level, final String message) {
final BleManager manager = bleManagers.get(device);
if (manager != null)
manager.log(level, message);
}
@Override
public void log(@NonNull final BluetoothDevice device, final int level, @StringRes final int messageRes, final Object... params) {
final BleManager manager = bleManagers.get(device);
if (manager != null)
manager.log(level, messageRes, params);
}
@Override
public void log(final int level, @NonNull final String message) {
for (final BleManager manager : bleManagers.values())
manager.log(level, message);
}
@Override
public void log(final int level, @StringRes final int messageRes, final Object... params) {
for (final BleManager manager : bleManagers.values())
manager.log(level, messageRes, params);
}
}
/**
* Returns a handler that is created in onCreate().
* The handler may be used to postpone execution of some operations or to run them in UI thread.
*/
protected Handler getHandler() {
return handler;
}
/**
* This method returns whether autoConnect option should be used.
*
* @return true to use autoConnect feature, false (default) otherwise.
*/
protected boolean shouldAutoConnect() {
return false;
}
/**
* Returns the binder implementation. This must return class implementing the additional manager interface that may be used in the bound activity.
*
* @return the service binder
*/
protected LocalBinder getBinder() {
// default implementation returns the basic binder. You can overwrite the LocalBinder with your own, wider implementation
return new LocalBinder();
}
@Override
public IBinder onBind(final Intent intent) {
bound = true;
return getBinder();
}
@Override
public final void onRebind(final Intent intent) {
bound = true;
if (!activityIsChangingConfiguration) {
onRebind();
}
}
/**
* Called when the activity has rebound to the service after being recreated.
* This method is not called when the activity was killed to be recreated when the phone orientation changed
* if prior to being killed called {@link LocalBinder#setActivityIsChangingConfiguration(boolean)} with parameter true.
*/
protected void onRebind() {
// empty default implementation
}
@Override
public final boolean onUnbind(final Intent intent) {
bound = false;
if (!activityIsChangingConfiguration) {
if (!managedDevices.isEmpty()) {
onUnbind();
} else {
// The last activity has disconnected from the service and there are no devices to manage. The service may be stopped.
stopSelf();
}
}
// We want the onRebind method be called if anything else binds to it again
return true;
}
/**
* Called when the activity has unbound from the service before being finished.
* This method is not called when the activity is killed to be recreated when the phone orientation changed.
*/
protected void onUnbind() {
// empty default implementation
}
@Override
public void onCreate() {
super.onCreate();
handler = new Handler();
// Initialize the map of BLE managers
bleManagers = new HashMap<>();
managedDevices = new ArrayList<>();
// Register broadcast receivers
registerReceiver(bluetoothStateBroadcastReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
// Service has now been created
onServiceCreated();
// Call onBluetoothEnabled if Bluetooth enabled
final BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter.isEnabled()) {
onBluetoothEnabled();
}
}
/**
* Called when the service has been created, before the {@link #onBluetoothEnabled()} is called.
*/
protected void onServiceCreated() {
// empty default implementation
}
/**
* Initializes the Ble Manager responsible for connecting to a single device.
* @return a new BleManager object
*/
@SuppressWarnings("rawtypes")
protected abstract LoggableBleManager initializeManager();
@Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
onServiceStarted();
// The service does not save addresses of managed devices.
// A bound activity will be required to add connections again.
return START_NOT_STICKY;
}
/**
* Called when the service has been started.
*/
protected void onServiceStarted() {
// empty default implementation
}
@Override
public void onTaskRemoved(final Intent rootIntent) {
super.onTaskRemoved(rootIntent);
// This method is called when user removed the app from Recents.
// By default, the service will be killed and recreated immediately after that.
// However, all managed devices will be lost and devices will be disconnected.
stopSelf();
}
@Override
public void onDestroy() {
super.onDestroy();
onServiceStopped();
handler = null;
}
/**
* Called when the service has been stopped.
*/
protected void onServiceStopped() {
// Unregister broadcast receivers
unregisterReceiver(bluetoothStateBroadcastReceiver);
// The managers map may not be empty if the service was killed by the system
for (final BleManager manager : bleManagers.values()) {
// Service is being destroyed, no need to disconnect manually.
manager.close();
manager.log(Log.INFO, "Service destroyed");
}
bleManagers.clear();
managedDevices.clear();
bleManagers = null;
managedDevices = null;
}
/**
* Method called when Bluetooth Adapter has been disabled.
*/
protected void onBluetoothDisabled() {
// do nothing, BleManagers have their own Bluetooth State broadcast received and will close themselves
}
/**
* This method is called when Bluetooth Adapter has been enabled. It is also called
* after the service was created if Bluetooth Adapter was enabled at that moment.
* This method could initialize all Bluetooth related features, for example open the GATT server.
* Make sure you call <code>super.onBluetoothEnabled()</code> at this methods reconnects to
* devices that were connected before the Bluetooth was turned off.
*/
protected void onBluetoothEnabled() {
for (final BluetoothDevice device : managedDevices) {
final BleManager manager = bleManagers.get(device);
if (manager != null && !manager.isConnected())
manager.connect(device).enqueue();
}
}
@Override
public void onDeviceConnecting(@NonNull final BluetoothDevice device) {
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
broadcast.putExtra(EXTRA_DEVICE, device);
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_CONNECTING);
LocalBroadcastManager.getInstance(BleMulticonnectProfileService.this).sendBroadcast(broadcast);
}
@Override
public void onDeviceConnected(@NonNull final BluetoothDevice device) {
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
broadcast.putExtra(EXTRA_DEVICE, device);
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_CONNECTED);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
@Override
public void onDeviceDisconnecting(@NonNull final BluetoothDevice device) {
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
broadcast.putExtra(EXTRA_DEVICE, device);
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_DISCONNECTING);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
@Override
public void onDeviceDisconnected(@NonNull final BluetoothDevice device) {
// Note: if BleManager#shouldAutoConnect() for this device returned true, this callback will be
// invoked ONLY when user requested disconnection (using Disconnect button). If the device
// disconnects due to a link loss, the onLinkLossOccurred(BluetoothDevice) method will be called instead.
// We no longer want to keep the device in the service
managedDevices.remove(device);
// The BleManager is not removed from the HashMap in order to keep the device's log session.
// bleManagers.remove(device);
// Do not use the device argument here unless you change calling onDeviceDisconnected from the binder above
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
broadcast.putExtra(EXTRA_DEVICE, device);
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_DISCONNECTED);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
// When user disconnected the last device while the activity was not bound the service can be stopped
if (!bound && managedDevices.isEmpty()) {
stopSelf();
}
}
@Override
public void onLinkLossOccurred(@NonNull final BluetoothDevice device) {
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
broadcast.putExtra(EXTRA_DEVICE, device);
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_LINK_LOSS);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
@Override
public void onServicesDiscovered(@NonNull final BluetoothDevice device, final boolean optionalServicesFound) {
final Intent broadcast = new Intent(BROADCAST_SERVICES_DISCOVERED);
broadcast.putExtra(EXTRA_DEVICE, device);
broadcast.putExtra(EXTRA_SERVICE_PRIMARY, true);
broadcast.putExtra(EXTRA_SERVICE_SECONDARY, optionalServicesFound);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
@Override
public void onDeviceReady(@NonNull final BluetoothDevice device) {
final Intent broadcast = new Intent(BROADCAST_DEVICE_READY);
broadcast.putExtra(EXTRA_DEVICE, device);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
@Override
public void onDeviceNotSupported(@NonNull final BluetoothDevice device) {
// We don't like this device, remove it from both collections
managedDevices.remove(device);
bleManagers.remove(device);
final Intent broadcast = new Intent(BROADCAST_SERVICES_DISCOVERED);
broadcast.putExtra(EXTRA_DEVICE, device);
broadcast.putExtra(EXTRA_SERVICE_PRIMARY, false);
broadcast.putExtra(EXTRA_SERVICE_SECONDARY, false);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
// no need for disconnecting, it will be disconnected by the manager automatically
}
@SuppressWarnings("deprecation")
@Override
public void onBatteryValueReceived(@NonNull final BluetoothDevice device, final int value) {
final Intent broadcast = new Intent(BROADCAST_BATTERY_LEVEL);
broadcast.putExtra(EXTRA_DEVICE, device);
broadcast.putExtra(EXTRA_BATTERY_LEVEL, value);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
@Override
public void onBondingRequired(@NonNull final BluetoothDevice device) {
showToast("bonding ");
final Intent broadcast = new Intent(BROADCAST_BOND_STATE);
broadcast.putExtra(EXTRA_DEVICE, device);
broadcast.putExtra(EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDING);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
@Override
public void onBonded(@NonNull final BluetoothDevice device) {
showToast(" bonded ");
final Intent broadcast = new Intent(BROADCAST_BOND_STATE);
broadcast.putExtra(EXTRA_DEVICE, device);
broadcast.putExtra(EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDED);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
@Override
public void onBondingFailed(@NonNull final BluetoothDevice device) {
showToast(" bonding_failed ");
final Intent broadcast = new Intent(BROADCAST_BOND_STATE);
broadcast.putExtra(EXTRA_DEVICE, device);
broadcast.putExtra(EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
@Override
public void onError(@NonNull final BluetoothDevice device, @NonNull final String message, final int errorCode) {
final Intent broadcast = new Intent(BROADCAST_ERROR);
broadcast.putExtra(EXTRA_DEVICE, device);
broadcast.putExtra(EXTRA_ERROR_MESSAGE, message);
broadcast.putExtra(EXTRA_ERROR_CODE, errorCode);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
/**
* Shows a message as a Toast notification. This method is thread safe, you can call it from any thread
*
* @param messageResId
* an resource id of the message to be shown
*/
protected void showToast(final int messageResId) {
handler.post(() -> Toast.makeText(BleMulticonnectProfileService.this, messageResId, Toast.LENGTH_SHORT).show());
}
/**
* Shows a message as a Toast notification. This method is thread safe, you can call it from any thread
*
* @param message
* a message to be shown
*/
protected void showToast(final String message) {
handler.post(() -> Toast.makeText(BleMulticonnectProfileService.this, message, Toast.LENGTH_SHORT).show());
}
/**
* Returns the {@link BleManager} object associated with given device, or null if such has not been created.
* To create a BleManager call the {@link LocalBinder#connect(BluetoothDevice)} method must be called.
* @param device the target device
* @return the BleManager or null
*/
protected BleManager getBleManager(final BluetoothDevice device) {
return bleManagers.get(device);
}
/**
* Returns unmodifiable list of all managed devices. They don't have to be connected at the moment.
* @return list of managed devices
*/
protected List<BluetoothDevice> getManagedDevices() {
return Collections.unmodifiableList(managedDevices);
}
/**
* Returns a list of those managed devices that are connected at the moment.
* @return list of connected devices
*/
protected List<BluetoothDevice> getConnectedDevices() {
final List<BluetoothDevice> list = new ArrayList<>();
for (BluetoothDevice device : managedDevices) {
final BleManager manager = bleManagers.get(device);
if (manager != null && manager.isConnected())
list.add(device);
}
return Collections.unmodifiableList(list);
}
/**
* Returns <code>true</code> if the device is connected to the sensor.
* @param device the target device
* @return <code>true</code> if device is connected to the sensor, <code>false</code> otherwise
*/
protected boolean isConnected(final BluetoothDevice device) {
final BleManager manager = bleManagers.get(device);
return manager != null && manager.isConnected();
}
}

View File

@@ -0,0 +1,502 @@
package no.Reader.android.iisc.profile.multiconnect;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import no.nordicsemi.android.ble.BleManagerCallbacks;
import no.nordicsemi.android.log.ILogSession;
import no.nordicsemi.android.log.LocalLogSession;
import no.nordicsemi.android.log.Logger;
import no.Reader.android.iisc.R;
import no.Reader.android.iisc.scanner.ScannerFragment;
import no.Reader.android.iisc.DebugLogger;
/**
* <p>
* The {@link BleMulticonnectProfileServiceReadyActivity} activity is designed to be the base class for profile activities that uses services in order to connect
* more than one device at the same time. A service extending {@link BleMulticonnectProfileService} is created when the activity is created, and the activity binds to it.
* The service returns a binder that may be used to connect, disconnect or manage devices, and notifies the
* activity using Local Broadcasts ({@link LocalBroadcastManager}). See {@link BleMulticonnectProfileService} for messages. If the device is not in range it will listen for
* it and connect when it become visible. The service exists until all managed devices have been disconnected and unmanaged and the last activity unbinds from it.
* </p>
* <p>
* When user closes the activity (e.g. by pressing Back button) while being connected, the Service remains working. It's remains connected to the devices or still
* listens for updates from them. When entering back to the activity, activity will to bind to the service and refresh UI.
* </p>
*/
public abstract class BleMulticonnectProfileServiceReadyActivity<E extends BleMulticonnectProfileService.LocalBinder> extends AppCompatActivity implements
ScannerFragment.OnDeviceSelectedListener, BleManagerCallbacks {
private static final String TAG = "BleMulticonnectProfileServiceReadyActivity";
protected static final int REQUEST_ENABLE_BT = 2;
private E mService;
private List<BluetoothDevice> mManagedDevices;
private final BroadcastReceiver mCommonBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
final BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BleMulticonnectProfileService.EXTRA_DEVICE);
final String action = intent.getAction();
switch (action) {
case BleMulticonnectProfileService.BROADCAST_CONNECTION_STATE: {
final int state = intent.getIntExtra(BleMulticonnectProfileService.EXTRA_CONNECTION_STATE, BleMulticonnectProfileService.STATE_DISCONNECTED);
switch (state) {
case BleMulticonnectProfileService.STATE_CONNECTED: {
onDeviceConnected(bluetoothDevice);
break;
}
case BleMulticonnectProfileService.STATE_DISCONNECTED: {
onDeviceDisconnected(bluetoothDevice);
break;
}
case BleMulticonnectProfileService.STATE_LINK_LOSS: {
onLinkLossOccurred(bluetoothDevice);
break;
}
case BleMulticonnectProfileService.STATE_CONNECTING: {
onDeviceConnecting(bluetoothDevice);
break;
}
case BleMulticonnectProfileService.STATE_DISCONNECTING: {
onDeviceDisconnecting(bluetoothDevice);
break;
}
default:
// there should be no other actions
break;
}
break;
}
case BleMulticonnectProfileService.BROADCAST_SERVICES_DISCOVERED: {
final boolean primaryService = intent.getBooleanExtra(BleMulticonnectProfileService.EXTRA_SERVICE_PRIMARY, false);
final boolean secondaryService = intent.getBooleanExtra(BleMulticonnectProfileService.EXTRA_SERVICE_SECONDARY, false);
if (primaryService) {
onServicesDiscovered(bluetoothDevice, secondaryService);
} else {
onDeviceNotSupported(bluetoothDevice);
}
break;
}
case BleMulticonnectProfileService.BROADCAST_DEVICE_READY: {
onDeviceReady(bluetoothDevice);
break;
}
case BleMulticonnectProfileService.BROADCAST_BOND_STATE: {
final int state = intent.getIntExtra(BleMulticonnectProfileService.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE);
switch (state) {
case BluetoothDevice.BOND_BONDING:
onBondingRequired(bluetoothDevice);
break;
case BluetoothDevice.BOND_BONDED:
onBonded(bluetoothDevice);
break;
}
break;
}
case BleMulticonnectProfileService.BROADCAST_BATTERY_LEVEL: {
final int value = intent.getIntExtra(BleMulticonnectProfileService.EXTRA_BATTERY_LEVEL, -1);
if (value > 0)
onBatteryValueReceived(bluetoothDevice, value);
break;
}
case BleMulticonnectProfileService.BROADCAST_ERROR: {
final String message = intent.getStringExtra(BleMulticonnectProfileService.EXTRA_ERROR_MESSAGE);
final int errorCode = intent.getIntExtra(BleMulticonnectProfileService.EXTRA_ERROR_CODE, 0);
onError(bluetoothDevice, message, errorCode);
break;
}
}
}
};
private ServiceConnection mServiceConnection = new ServiceConnection() {
@SuppressWarnings("unchecked")
@Override
public void onServiceConnected(final ComponentName name, final IBinder service) {
final E bleService = mService = (E) service;
bleService.log(Log.DEBUG, "Activity bound to the service");
mManagedDevices.addAll(bleService.getManagedDevices());
onServiceBound(bleService);
// and notify user if device is connected
for (final BluetoothDevice device : mManagedDevices) {
if (bleService.isConnected(device))
onDeviceConnected(device);
}
}
@Override
public void onServiceDisconnected(final ComponentName name) {
mService = null;
onServiceUnbound();
}
};
@Override
protected final void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mManagedDevices = new ArrayList<>();
ensureBLESupported();
if (!isBLEEnabled()) {
showBLEDialog();
}
// In onInitialize method a final class may register local broadcast receivers that will listen for events from the service
onInitialize(savedInstanceState);
// The onCreateView class should... create the view
onCreateView(savedInstanceState);
final Toolbar toolbar = findViewById(R.id.toolbar_actionbar);
setSupportActionBar(toolbar);
// Common nRF Toolbox view references are obtained here
setUpView();
// View is ready to be used
onViewCreated(savedInstanceState);
LocalBroadcastManager.getInstance(this).registerReceiver(mCommonBroadcastReceiver, makeIntentFilter());
}
@Override
protected void onStart() {
super.onStart();
/*
* In comparison to BleProfileServiceReadyActivity this activity always starts the service when started.
* Connecting to a device is done by calling mService.connect(BluetoothDevice) method, not startService(...) like there.
* The service will stop itself when all devices it manages were disconnected and unmanaged and the last activity unbinds from it.
*/
final Intent service = new Intent(this, getServiceClass());
startService(service);
bindService(service, mServiceConnection, 0);
}
@Override
protected void onStop() {
super.onStop();
if (mService != null) {
// We don't want to perform some operations (e.g. disable Battery Level notifications) in the service if we are just rotating the screen.
// However, when the activity will disappear, we may want to disable some device features to reduce the battery consumption.
mService.setActivityIsChangingConfiguration(isChangingConfigurations());
// Log it here as there is no callback when the service gets unbound
// and the mService will not be available later (the activity doesn't keep log sessions)
mService.log(Log.DEBUG, "Activity unbound from the service");
}
unbindService(mServiceConnection);
mService = null;
onServiceUnbound();
}
@Override
protected void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mCommonBroadcastReceiver);
}
private static IntentFilter makeIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BleMulticonnectProfileService.BROADCAST_CONNECTION_STATE);
intentFilter.addAction(BleMulticonnectProfileService.BROADCAST_SERVICES_DISCOVERED);
intentFilter.addAction(BleMulticonnectProfileService.BROADCAST_DEVICE_READY);
intentFilter.addAction(BleMulticonnectProfileService.BROADCAST_BOND_STATE);
intentFilter.addAction(BleMulticonnectProfileService.BROADCAST_BATTERY_LEVEL);
intentFilter.addAction(BleMulticonnectProfileService.BROADCAST_ERROR);
return intentFilter;
}
/**
* Called when activity binds to the service. The parameter is the object returned in {@link Service#onBind(Intent)} method in your service.
* It is safe to obtain managed devices now.
*/
protected abstract void onServiceBound(E binder);
/**
* Called when activity unbinds from the service. You may no longer use this binder methods.
*/
protected abstract void onServiceUnbound();
/**
* Returns the service class for sensor communication. The service class must derive from {@link BleMulticonnectProfileService} in order to operate with this class.
*
* @return the service class
*/
protected abstract Class<? extends BleMulticonnectProfileService> getServiceClass();
/**
* Returns the service interface that may be used to communicate with the sensor. This will return <code>null</code> if the device is disconnected from the
* sensor.
*
* @return the service binder or <code>null</code>
*/
protected E getService() {
return mService;
}
/**
* You may do some initialization here. This method is called from {@link #onCreate(Bundle)} before the view was created.
*/
protected void onInitialize(final Bundle savedInstanceState) {
// empty default implementation
}
/**
* Called from {@link #onCreate(Bundle)}. This method should build the activity UI, i.e. using {@link #setContentView(int)}.
* Use to obtain references to views. Connect/Disconnect button and the device name view are manager automatically.
*
* @param savedInstanceState contains the data it most recently supplied in {@link #onSaveInstanceState(Bundle)}.
* Note: <b>Otherwise it is null</b>.
*/
protected abstract void onCreateView(final Bundle savedInstanceState);
/**
* Called after the view has been created.
*
* @param savedInstanceState contains the data it most recently supplied in {@link #onSaveInstanceState(Bundle)}.
* Note: <b>Otherwise it is null</b>.
*/
protected void onViewCreated(final Bundle savedInstanceState) {
// empty default implementation
}
/**
* Called after the view and the toolbar has been created.
*/
protected final void setUpView() {
// set GUI
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
/**
* Use this method to handle menu actions other than home and about.
*
* @param itemId the menu item id
* @return <code>true</code> if action has been handled
*/
/**
* Called when user press ADD DEVICE button. See layout files -> onClick attribute.
*/
public void onAddDeviceClicked(final View view) {
if (isBLEEnabled()) {
showDeviceScanningDialog(getFilterUUID());
} else {
showBLEDialog();
}
}
/**
* Returns the title resource id that will be used to create logger session. If 0 is returned (default) logger will not be used.
*
* @return the title resource id
*/
protected int getLoggerProfileTitle() {
return 0;
}
/**
* This method may return the local log content provider authority if local log sessions are supported.
*
* @return local log session content provider URI
*/
protected Uri getLocalAuthorityLogger() {
return null;
}
@Override
public void onDeviceSelected(final BluetoothDevice device, final String name) {
final int titleId = getLoggerProfileTitle();
ILogSession logSession = null;
if (titleId > 0) {
logSession = Logger.newSession(getApplicationContext(), getString(titleId), device.getAddress(), name);
// If nRF Logger is not installed we may want to use local logger
if (logSession == null && getLocalAuthorityLogger() != null) {
logSession = LocalLogSession.newSession(getApplicationContext(), getLocalAuthorityLogger(), device.getAddress(), name);
}
}
mService.connect(device, logSession);
}
@Override
public void onDialogCanceled() {
// do nothing
}
@Override
public void onDeviceConnecting(final BluetoothDevice device) {
// empty default implementation
}
@Override
public void onDeviceDisconnecting(final BluetoothDevice device) {
// empty default implementation
}
@Override
public void onLinkLossOccurred(final BluetoothDevice device) {
// empty default implementation
}
@Override
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
// empty default implementation
}
@Override
public void onDeviceReady(final BluetoothDevice device) {
// empty default implementation
}
@Override
public void onBondingRequired(final BluetoothDevice device) {
// empty default implementation
}
@Override
public void onBonded(final BluetoothDevice device) {
// empty default implementation
}
@Override
public void onBondingFailed(final BluetoothDevice device) {
// empty default implementation
}
@Override
public void onDeviceNotSupported(final BluetoothDevice device) {
showToast(R.string.not_supported);
}
@Override
public final boolean shouldEnableBatteryLevelNotifications(final BluetoothDevice device) {
// This method will never be called.
// Please see BleMulticonnectProfileService#shouldEnableBatteryLevelNotifications(BluetoothDevice) instead.
throw new UnsupportedOperationException("This method should not be called");
}
@Override
public void onBatteryValueReceived(final BluetoothDevice device, final int value) {
// empty default implementation
}
@Override
public void onError(final BluetoothDevice device, final String message, final int errorCode) {
DebugLogger.e(TAG, "Error occurred: " + message + ", error code: " + errorCode);
showToast(message + " (" + errorCode + ")");
}
/**
* Shows a message as a Toast notification. This method is thread safe, you can call it from any thread
*
* @param message a message to be shown
*/
protected void showToast(final String message) {
runOnUiThread(() -> Toast.makeText(BleMulticonnectProfileServiceReadyActivity.this, message, Toast.LENGTH_LONG).show());
}
/**
* Shows a message as a Toast notification. This method is thread safe, you can call it from any thread
*
* @param messageResId an resource id of the message to be shown
*/
protected void showToast(final int messageResId) {
runOnUiThread(() -> Toast.makeText(BleMulticonnectProfileServiceReadyActivity.this, messageResId, Toast.LENGTH_SHORT).show());
}
/**
* Returns the string resource id that will be shown in About box
*
* @return the about resource id
*/
protected abstract int getAboutTextId();
/**
* The UUID filter is used to filter out available devices that does not have such UUID in their advertisement packet. See also:
* {@link #isChangingConfigurations()}.
*
* @return the required UUID or <code>null</code>
*/
protected abstract UUID getFilterUUID();
/**
* Returns unmodifiable list of managed devices. Managed device is a device the was selected on ScannerFragment until it's removed from the managed list.
* It does not have to be connected at that moment.
* @return unmodifiable list of managed devices
*/
protected List<BluetoothDevice> getManagedDevices() {
return Collections.unmodifiableList(mManagedDevices);
}
/**
* Returns <code>true</code> if the device is connected. Services may not have been discovered yet.
* @param device the device to check if it's connected
*/
protected boolean isDeviceConnected(final BluetoothDevice device) {
return mService != null && mService.isConnected(device);
}
/**
* Shows the scanner fragment.
*
* @param filter the UUID filter used to filter out available devices. The fragment will always show all bonded devices as there is no information about their
* services
* @see #getFilterUUID()
*/
private void showDeviceScanningDialog(final UUID filter) {
final ScannerFragment dialog = ScannerFragment.getInstance(filter);
dialog.show(getSupportFragmentManager(), "scan_fragment");
}
private void ensureBLESupported() {
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.no_ble, Toast.LENGTH_LONG).show();
finish();
}
}
protected boolean isBLEEnabled() {
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
final BluetoothAdapter adapter = bluetoothManager.getAdapter();
return adapter != null && adapter.isEnabled();
}
protected void showBLEDialog() {
final Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2016, Nordic Semiconductor
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package no.Reader.android.iisc.profile.multiconnect;
import android.bluetooth.BluetoothDevice;
import androidx.annotation.StringRes;
public interface IDeviceLogger {
/**
* Logs the given message with given log level into the device's log session.
* @param device the target device
* @param level the log level
* @param message the message to be logged
*/
void log(final BluetoothDevice device, final int level, final String message);
/**
* Logs the given message with given log level into the device's log session.
* @param device the target device
* @param level the log level
* @param messageRes string resource id
* @param params additional (optional) parameters used to fill the message
*/
void log(final BluetoothDevice device, final int level, @StringRes final int messageRes, final Object... params);
}

View File

@@ -0,0 +1,193 @@
package no.Reader.android.iisc.scanner;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import no.nordicsemi.android.support.v18.scanner.ScanResult;
import no.Reader.android.iisc.R;
/**
* DeviceListAdapter class is list adapter for showing scanned Devices name, address and RSSI image based on RSSI values.
*/
public class DeviceListAdapter extends BaseAdapter {
private static final int TYPE_TITLE = 0;
private static final int TYPE_ITEM = 1;
private static final int TYPE_EMPTY = 2;
private final ArrayList<ExtendedBluetoothDevice> mListBondedValues = new ArrayList<>();
private final ArrayList<ExtendedBluetoothDevice> mListValues = new ArrayList<>();
private final Context mContext;
public DeviceListAdapter(final Context context) {
mContext = context;
}
/**
* Sets a list of bonded devices.
* @param devices list of bonded devices.
*/
public void addBondedDevices(final Set<BluetoothDevice> devices) {
final List<ExtendedBluetoothDevice> bondedDevices = mListBondedValues;
for (BluetoothDevice device : devices) {
bondedDevices.add(new ExtendedBluetoothDevice(device));
}
notifyDataSetChanged();
}
/**
* Updates the list of not bonded devices.
* @param results list of results from the scanner
*/
public void update(final List<ScanResult> results) {
for (final ScanResult result : results) {
final ExtendedBluetoothDevice device = findDevice(result);
if (device == null) {
mListValues.add(new ExtendedBluetoothDevice(result));
} else {
device.name = result.getScanRecord() != null ? result.getScanRecord().getDeviceName() : null;
device.rssi = result.getRssi();
}
}
notifyDataSetChanged();
}
private ExtendedBluetoothDevice findDevice(final ScanResult result) {
for (final ExtendedBluetoothDevice device : mListBondedValues)
if (device.matches(result))
return device;
for (final ExtendedBluetoothDevice device : mListValues)
if (device.matches(result))
return device;
return null;
}
public void clearDevices() {
mListValues.clear();
notifyDataSetChanged();
}
@Override
public int getCount() {
final int bondedCount = mListBondedValues.size() + 1; // 1 for the title
final int availableCount = mListValues.isEmpty() ? 2 : mListValues.size() + 1; // 1 for title, 1 for empty text
if (bondedCount == 1)
return availableCount;
return bondedCount + availableCount;
}
@Override
public Object getItem(int position) {
final int bondedCount = mListBondedValues.size() + 1; // 1 for the title
if (mListBondedValues.isEmpty()) {
if (position == 0)
return R.string.scanner_subtitle_not_bonded;
else
return mListValues.get(position - 1);
} else {
if (position == 0)
return R.string.scanner_subtitle_bonded;
if (position < bondedCount)
return mListBondedValues.get(position - 1);
if (position == bondedCount)
return R.string.scanner_subtitle_not_bonded;
return mListValues.get(position - bondedCount - 1);
}
}
@Override
public int getViewTypeCount() {
return 3;
}
@Override
public boolean areAllItemsEnabled() {
return false;
}
@Override
public boolean isEnabled(int position) {
return getItemViewType(position) == TYPE_ITEM;
}
@Override
public int getItemViewType(int position) {
if (position == 0)
return TYPE_TITLE;
if (!mListBondedValues.isEmpty() && position == mListBondedValues.size() + 1)
return TYPE_TITLE;
if (position == getCount() - 1 && mListValues.isEmpty())
return TYPE_EMPTY;
return TYPE_ITEM;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View oldView, ViewGroup parent) {
final LayoutInflater inflater = LayoutInflater.from(mContext);
final int type = getItemViewType(position);
View view = oldView;
switch (type) {
case TYPE_EMPTY:
if (view == null) {
view = inflater.inflate(R.layout.device_list_empty, parent, false);
}
break;
case TYPE_TITLE:
if (view == null) {
view = inflater.inflate(R.layout.device_list_title, parent, false);
}
final TextView title = (TextView) view;
title.setText((Integer) getItem(position));
break;
default:
if (view == null) {
view = inflater.inflate(R.layout.device_list_row, parent, false);
final ViewHolder holder = new ViewHolder();
holder.name = view.findViewById(R.id.name);
holder.address = view.findViewById(R.id.address);
holder.rssi = view.findViewById(R.id.rssi);
view.setTag(holder);
}
final ExtendedBluetoothDevice device = (ExtendedBluetoothDevice) getItem(position);
final ViewHolder holder = (ViewHolder) view.getTag();
final String name = device.name;
holder.name.setText(name != null ? name : mContext.getString(R.string.not_available));
holder.address.setText(device.device.getAddress());
if (!device.isBonded || device.rssi != ExtendedBluetoothDevice.NO_RSSI) {
final int rssiPercent = (int) (100.0f * (127.0f + device.rssi) / (127.0f + 20.0f));
holder.rssi.setImageLevel(rssiPercent);
holder.rssi.setVisibility(View.VISIBLE);
} else {
holder.rssi.setVisibility(View.GONE);
}
break;
}
return view;
}
private class ViewHolder {
private TextView name;
private TextView address;
private ImageView rssi;
}
}

View File

@@ -0,0 +1,32 @@
package no.Reader.android.iisc.scanner;
import android.bluetooth.BluetoothDevice;
import no.nordicsemi.android.support.v18.scanner.ScanResult;
public class ExtendedBluetoothDevice {
/* package */ static final int NO_RSSI = -1000;
public final BluetoothDevice device;
/** The name is not parsed by some Android devices, f.e. Sony Xperia Z1 with Android 4.3 (C6903). It needs to be parsed manually. */
public String name;
public int rssi;
public boolean isBonded;
public ExtendedBluetoothDevice(final ScanResult scanResult) {
this.device = scanResult.getDevice();
this.name = scanResult.getScanRecord() != null ? scanResult.getScanRecord().getDeviceName() : null;
this.rssi = scanResult.getRssi();
this.isBonded = false;
}
public ExtendedBluetoothDevice(final BluetoothDevice device) {
this.device = device;
this.name = device.getName();
this.rssi = NO_RSSI;
this.isBonded = true;
}
public boolean matches(final ScanResult scanResult) {
return device.getAddress().equals(scanResult.getDevice().getAddress());
}
}

View File

@@ -0,0 +1,268 @@
package no.Reader.android.iisc.scanner;
import android.Manifest;
import android.app.Dialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.ParcelUuid;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.DialogFragment;
import androidx.core.content.ContextCompat;
import androidx.appcompat.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerCompat;
import no.nordicsemi.android.support.v18.scanner.ScanCallback;
import no.nordicsemi.android.support.v18.scanner.ScanFilter;
import no.nordicsemi.android.support.v18.scanner.ScanResult;
import no.nordicsemi.android.support.v18.scanner.ScanSettings;
import no.Reader.android.iisc.R;
/**
* ScannerFragment class scan required BLE devices and shows them in a list. This class scans and filter
* devices with standard BLE Service UUID and devices with custom BLE Service UUID. It contains a
* list and a button to scan/cancel. There is a interface {@link OnDeviceSelectedListener} which is
* implemented by activity in order to receive selected device. The scanning will continue to scan
* for 5 seconds and then stop.
*/
public class ScannerFragment extends DialogFragment {
private final static String TAG = "ScannerFragment";
private final static String PARAM_UUID = "param_uuid";
private final static long SCAN_DURATION = 5000;
private final static int REQUEST_PERMISSION_REQ_CODE = 34; // any 8-bit number
private BluetoothAdapter mBluetoothAdapter;
private OnDeviceSelectedListener mListener;
private DeviceListAdapter mAdapter;
private final Handler mHandler = new Handler();
private Button mScanButton;
private View mPermissionRationale;
private ParcelUuid mUuid;
private boolean mIsScanning = false;
public static ScannerFragment getInstance(final UUID uuid) {
final ScannerFragment fragment = new ScannerFragment();
final Bundle args = new Bundle();
if (uuid != null)
args.putParcelable(PARAM_UUID, new ParcelUuid(uuid));
fragment.setArguments(args);
return fragment;
}
/**
* Interface required to be implemented by activity.
*/
public interface OnDeviceSelectedListener {
/**
* Fired when user selected the device.
*
* @param device
* the device to connect to
* @param name
* the device name. Unfortunately on some devices {@link BluetoothDevice#getName()}
* always returns <code>null</code>, i.e. Sony Xperia Z1 (C6903) with Android 4.3.
* The name has to be parsed manually form the Advertisement packet.
*/
void onDeviceSelected(final BluetoothDevice device, final String name);
/**
* Fired when scanner dialog has been cancelled without selecting a device.
*/
void onDialogCanceled();
}
/**
* This will make sure that {@link OnDeviceSelectedListener} interface is implemented by activity.
*/
@Override
public void onAttach(final Context context) {
super.onAttach(context);
try {
this.mListener = (OnDeviceSelectedListener) context;
} catch (final ClassCastException e) {
throw new ClassCastException(context.toString() + " must implement OnDeviceSelectedListener");
}
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Bundle args = getArguments();
if (args != null && args.containsKey(PARAM_UUID)) {
mUuid = args.getParcelable(PARAM_UUID);
}
final BluetoothManager manager = (BluetoothManager) requireContext().getSystemService(Context.BLUETOOTH_SERVICE);
if (manager != null) {
mBluetoothAdapter = manager.getAdapter();
}
}
@Override
public void onDestroyView() {
stopScan();
super.onDestroyView();
}
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
final AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
final View dialogView = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_device_selection, null);
final ListView listview = dialogView.findViewById(android.R.id.list);
listview.setEmptyView(dialogView.findViewById(android.R.id.empty));
listview.setAdapter(mAdapter = new DeviceListAdapter(getActivity()));
builder.setTitle(R.string.scanner_title);
final AlertDialog dialog = builder.setView(dialogView).create();
listview.setOnItemClickListener((parent, view, position, id) -> {
stopScan();
dialog.dismiss();
final ExtendedBluetoothDevice d = (ExtendedBluetoothDevice) mAdapter.getItem(position);
mListener.onDeviceSelected(d.device, d.name);
});
mPermissionRationale = dialogView.findViewById(R.id.permission_rationale); // this is not null only on API23+
mScanButton = dialogView.findViewById(R.id.action_cancel);
mScanButton.setOnClickListener(v -> {
if (v.getId() == R.id.action_cancel) {
if (mIsScanning) {
dialog.cancel();
} else {
startScan();
}
}
});
addBoundDevices();
if (savedInstanceState == null)
startScan();
return dialog;
}
@Override
public void onCancel(DialogInterface dialog) {
super.onCancel(dialog);
mListener.onDialogCanceled();
}
@Override
public void onRequestPermissionsResult(final int requestCode, final @NonNull String[] permissions, final @NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_PERMISSION_REQ_CODE: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// We have been granted the Manifest.permission.ACCESS_COARSE_LOCATION permission. Now we may proceed with scanning.
startScan();
} else {
mPermissionRationale.setVisibility(View.VISIBLE);
Toast.makeText(getActivity(), R.string.no_required_permission, Toast.LENGTH_SHORT).show();
}
break;
}
}
}
/**
* Scan for 5 seconds and then stop scanning when a BluetoothLE device is found then mLEScanCallback
* is activated This will perform regular scan for custom BLE Service UUID and then filter out.
* using class ScannerServiceParser
*/
private void startScan() {
// Since Android 6.0 we need to obtain either Manifest.permission.ACCESS_COARSE_LOCATION or Manifest.permission.ACCESS_FINE_LOCATION to be able to scan for
// Bluetooth LE devices. This is related to beacons as proximity devices.
// On API older than Marshmallow the following code does nothing.
if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// When user pressed Deny and still wants to use this functionality, show the rationale
if (ActivityCompat.shouldShowRequestPermissionRationale(requireActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) && mPermissionRationale.getVisibility() == View.GONE) {
mPermissionRationale.setVisibility(View.VISIBLE);
return;
}
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSION_REQ_CODE);
return;
}
// Hide the rationale message, we don't need it anymore.
if (mPermissionRationale != null)
mPermissionRationale.setVisibility(View.GONE);
mAdapter.clearDevices();
mScanButton.setText(R.string.scanner_action_cancel);
final BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner();
final ScanSettings settings = new ScanSettings.Builder()
.setLegacy(false)
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).setReportDelay(1000).setUseHardwareBatchingIfSupported(false).build();
final List<ScanFilter> filters = new ArrayList<>();
filters.add(new ScanFilter.Builder().setServiceUuid(mUuid).build());
scanner.startScan(filters, settings, scanCallback);
mIsScanning = true;
mHandler.postDelayed(() -> {
if (mIsScanning) {
stopScan();
}
}, SCAN_DURATION);
}
/**
* Stop scan if user tap Cancel button
*/
private void stopScan() {
if (mIsScanning) {
mScanButton.setText(R.string.scanner_action_scan);
final BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner();
scanner.stopScan(scanCallback);
mIsScanning = false;
}
}
private ScanCallback scanCallback = new ScanCallback() {
@Override
public void onScanResult(final int callbackType, final ScanResult result) {
// do nothing
}
@Override
public void onBatchScanResults(final List<ScanResult> results) {
mAdapter.update(results);
}
@Override
public void onScanFailed(final int errorCode) {
// should never be called
}
};
private void addBoundDevices() {
final Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
mAdapter.addBondedDevices(devices);
}
}

View File

@@ -0,0 +1,149 @@
/*************************************************************************************************************************************************
* Copyright (c) 2015, Nordic Semiconductor
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************************************************************************************/
package no.Reader.android.iisc.widget;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.os.Build;
import androidx.annotation.NonNull;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
import no.Reader.android.iisc.R;
public class ForegroundRelativeLayout extends RelativeLayout {
private Drawable mForegroundSelector;
private Rect mRectPadding;
private boolean mUseBackgroundPadding = false;
public ForegroundRelativeLayout(Context context) {
super(context);
}
public ForegroundRelativeLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ForegroundRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ForegroundRelativeLayout,
defStyle, 0);
final Drawable d = a.getDrawable(R.styleable.ForegroundRelativeLayout_foreground);
if (d != null) {
setForeground(d);
}
a.recycle();
if (this.getBackground() instanceof NinePatchDrawable) {
final NinePatchDrawable npd = (NinePatchDrawable) this.getBackground();
mRectPadding = new Rect();
if (npd.getPadding(mRectPadding)) {
mUseBackgroundPadding = true;
}
}
}
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
if (mForegroundSelector != null && mForegroundSelector.isStateful()) {
mForegroundSelector.setState(getDrawableState());
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (mForegroundSelector != null) {
if (mUseBackgroundPadding) {
mForegroundSelector.setBounds(mRectPadding.left, mRectPadding.top, w - mRectPadding.right, h - mRectPadding.bottom);
} else {
mForegroundSelector.setBounds(0, 0, w, h);
}
}
}
@Override
protected void dispatchDraw(@NonNull Canvas canvas) {
super.dispatchDraw(canvas);
if (mForegroundSelector != null) {
mForegroundSelector.draw(canvas);
}
}
@Override
protected boolean verifyDrawable(Drawable who) {
return super.verifyDrawable(who) || (who == mForegroundSelector);
}
@Override
public void jumpDrawablesToCurrentState() {
super.jumpDrawablesToCurrentState();
if (mForegroundSelector != null) mForegroundSelector.jumpToCurrentState();
}
public void setForeground(Drawable drawable) {
if (mForegroundSelector != drawable) {
if (mForegroundSelector != null) {
mForegroundSelector.setCallback(null);
unscheduleDrawable(mForegroundSelector);
}
mForegroundSelector = drawable;
if (drawable != null) {
setWillNotDraw(false);
drawable.setCallback(this);
if (drawable.isStateful()) {
drawable.setState(getDrawableState());
}
} else {
setWillNotDraw(true);
}
requestLayout();
invalidate();
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void drawableHotspotChanged(float x, float y) {
super.drawableHotspotChanged(x, y);
if (mForegroundSelector != null) {
mForegroundSelector.setHotspot(x, y);
}
}
}

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="1500"
android:fromXDelta="0%"
android:fromYDelta="100%" />
<alpha
android:duration="1500"
android:fromAlpha="0.1"
android:toAlpha="1.0" />
</set>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="500" />
<translate
android:fromYDelta="-100%"
android:toYDelta="0%"
android:duration="700" />
</set>

View File

@@ -0,0 +1,10 @@
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="2000"
android:fromXDelta="0%"
android:fromYDelta="-50%" />
<alpha
android:duration="1500"
android:fromAlpha="0.1"
android:toAlpha="1.0" />
</set>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/nordicLake" android:state_enabled="true"/>
<item android:color="#c4cbcc"/>
</selector>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ Copyright (c) 2015, Nordic Semiconductor
~ All rights reserved.
~
~ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
~
~ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
~
~ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
~ documentation and/or other materials provided with the distribution.
~
~ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
~ software without specific prior written permission.
~
~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
~ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
~ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
~ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
~ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
~ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="@color/actionBarColorDark" />
<item android:color="#FF212121"/>
</selector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 546 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2015, Nordic Semiconductor
~ All rights reserved.
~
~ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
~
~ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
~
~ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
~ documentation and/or other materials provided with the distribution.
~
~ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
~ software without specific prior written permission.
~
~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
~ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
~ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
~ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
~ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
~ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/actionBarColor" >
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<corners android:radius="10dp" />
<solid android:color="#FF000000" />
</shape>
</item>
</ripple>

Some files were not shown because too many files have changed in this diff Show More