diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..c7e83f7 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,80 @@ +version: 2 +jobs: + build: + docker: + - image: circleci/android:api-30 + steps: + - checkout + - run: + command: | + sdkmanager "system-images;android-29;default;x86" + name: Install system image "system-images;android-29;default;x86" + - run: + command: | + find . -name 'build.gradle' | sort | xargs cat | + shasum | awk '{print $1}' > ./tmp_gradle_cache_seed + name: Generate cache checksum + - restore_cache: + key: gradle-v1a-{{ arch }}-{{ checksum "./tmp_gradle_cache_seed" }} + name: Restore gradle cache + - run: + name: gradle.property + command: | + mkdir -p ~/.gradle + curl $GRADLE_PROPERTY_PATH --output ~/.gradle/gradle.properties + curl $SECRET_KEY_RING_PATH --output algorigoble/secret-keys.gpg + - run: + command: | + ./gradlew build + name: 'Run: ./gradlew build' + - save_cache: + key: gradle-v1a-{{ arch }}-{{ checksum "./tmp_gradle_cache_seed" }} + name: Save gradle cache + paths: + - ~/.gradle/caches + - ~/.gradle/wrapper + - save_cache: + key: gradle-properties-${CIRCLE_WORKFLOW_ID} + name: Save gradle properties + paths: + - ~/.gradle/gradle.properties + - store_artifacts: + path: algorigoble/build/reports + destination: reports + - store_test_results: + path: algorigoble/build/test-results + - persist_to_workspace: + root: . + paths: + - . + resource_class: medium + deploy: + docker: + - image: circleci/android:api-30 + working_directory: ~/code + steps: + - attach_workspace: + at: . + - restore_cache: + key: gradle-v1a-{{ arch }}-{{ checksum "./tmp_gradle_cache_seed" }} + name: Restore gradle cache + - restore_cache: + key: gradle-properties-${CIRCLE_WORKFLOW_ID} + name: Restore gradle properties + - run: + name: Upload Maven Central + command: ./gradlew uploadArchives + +workflows: + version: 2 + build_deploy: + jobs: + - build + - deploy: + requires: + - build + filters: + branches: + only: + - master + - /release\/.*/ diff --git a/algorigoble/build.gradle b/algorigoble/build.gradle index deaa79d..5fba981 100644 --- a/algorigoble/build.gradle +++ b/algorigoble/build.gradle @@ -2,72 +2,96 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' -apply plugin: 'maven-publish' -apply plugin: 'com.jfrog.bintray' - -version '1.2.0' -group 'com.algorigo.algorigoble' - -publishing { - publications { - AlgorigoBle(MavenPublication) { - artifact("$buildDir/outputs/aar/algorigoble-release.aar") - groupId this.group - artifactId 'AlgorigoBleLibrary' - version this.version - - pom.withXml { - def dependenciesNode = asNode().appendNode('dependencies') - - // Iterate over the implementation dependencies (we don't want the test ones), adding a node for each - configurations.implementation.allDependencies.each { - // Ensure dependencies such as fileTree are not included in the pom. - if (it.name != 'unspecified') { - def dependencyNode = dependenciesNode.appendNode('dependency') - dependencyNode.appendNode('groupId', it.group) - dependencyNode.appendNode('artifactId', it.name) - dependencyNode.appendNode('version', it.version) - } - } - } +def versionStr = '1.3.0' + +def getCurrentGitBranch() { + def gitBranch = "Unknown branch" + try { + def workingDir = new File("${project.projectDir}") + def result = 'git rev-parse --abbrev-ref HEAD'.execute(null, workingDir) + result.waitFor() + if (result.exitValue() == 0) { + gitBranch = result.text.trim() } + } catch (e) { + } + return gitBranch +} + +def getUserName() { + return System.properties['user.name'] +} + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.bmuschko:gradle-nexus-plugin:2.3.1' } } -bintray { - user = System.getenv('BINTRAY_USER') - key = System.getenv('BINTRAY_KEY') - publications = ['AlgorigoBle'] - configurations = ['archives'] - override = true - pkg { - repo = 'maven' - name = 'AlgorigoBle' - userOrg = 'chagilhwan' - description = "Algorigo Ble Library with rx" - publish = true - publicDownloadNumbers = true - licenses = ['Apache-2.0'] - websiteUrl = 'https://github.com/Algorigo/AlgorigoBleLibrary' - vcsUrl = '${websiteUrl}.git' - dryRun = false - version { - name = this.version - desc = 'minor update' - released = new Date() - vcsTag = this.version +apply plugin: 'com.bmuschko.nexus' + +group = "com.algorigo.rx" +archivesBaseName = "algorigoble" +if (getCurrentGitBranch().equals('master')) { + version = versionStr +} else { + version = "${versionStr}-${getUserName()}-SNAPSHOT" +} + +modifyPom { + project { + name 'AlgorigoBleLibrary' + description 'Ble Library for Android using ReactiveX' + url 'https://github.com/Algorigo/AlgorigoBleLibrary' + inceptionYear '2018' + + scm { + url 'https://github.com/Algorigo/AlgorigoBleLibrary' + connection 'scm:https://github.com/Algorigo/AlgorigoBleLibrary.git' + developerConnection 'scm:git:https://github.com/Algorigo/AlgorigoBleLibrary.git' + } + + licenses { + license { + name 'The Apache Software License, Version 2.0' + url 'http://www.apache.org/licenses/LICENSE-2.0.txt' + distribution 'repo' + } + } + + developers { + developer { + id 'rouddy' + name 'Rouddy' + email 'rouddy@naver.com' + } } } } +extraArchive { + sources = true + tests = true + javadoc = true +} + +nexus { + sign = true + repositoryUrl = NEXUS_REPOSITORY_URL + snapshotRepositoryUrl = NEXUS_SNAPSHOT_REPOSITORY_URL +} + android { - compileSdkVersion 29 + compileSdkVersion 30 defaultConfig { - minSdkVersion 18 - targetSdkVersion 29 + minSdkVersion 21 + targetSdkVersion 30 versionCode 1 - versionName this.version + versionName versionStr testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -85,23 +109,23 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test:runner:1.2.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test:runner:1.3.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' - implementation 'org.jetbrains.kotlin:kotlin-reflect:1.3.72' + implementation 'org.jetbrains.kotlin:kotlin-reflect:1.4.31' //RxAndroidBle - implementation "com.polidea.rxandroidble2:rxandroidble:1.10.1" + implementation "com.polidea.rxandroidble2:rxandroidble:1.11.1" //ReactiveX implementation 'io.reactivex.rxjava2:rxkotlin:2.4.0' implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' //ReactiveX Relay - implementation 'com.jakewharton.rxrelay2:rxrelay:2.1.0' + implementation 'com.jakewharton.rxrelay2:rxrelay:2.1.1' // gson - implementation 'com.google.code.gson:gson:2.8.5' + implementation 'com.google.code.gson:gson:2.8.6' } repositories { diff --git a/algorigoble/src/main/AndroidManifest.xml b/algorigoble/src/main/AndroidManifest.xml index bb0e232..81cc60d 100644 --- a/algorigoble/src/main/AndroidManifest.xml +++ b/algorigoble/src/main/AndroidManifest.xml @@ -10,5 +10,6 @@ + diff --git a/algorigoble/src/main/java/com/algorigo/algorigoble/impl/BleScanOptionsConverter.kt b/algorigoble/src/main/java/com/algorigo/algorigoble/impl/BleScanOptionsConverter.kt index d674f90..c61e845 100644 --- a/algorigoble/src/main/java/com/algorigo/algorigoble/impl/BleScanOptionsConverter.kt +++ b/algorigoble/src/main/java/com/algorigo/algorigoble/impl/BleScanOptionsConverter.kt @@ -36,7 +36,9 @@ object BleScanOptionsConverter { fun convertScanFilters(filters: Array): List { return filters.map { ScanFilter.Builder().apply { - setDeviceName(it.deviceName) + it.deviceName?.let { deviceName -> + setDeviceName(deviceName) + } it.deviceAddress?.let { deviceAddress -> setDeviceAddress(deviceAddress) } diff --git a/app/build.gradle b/app/build.gradle index 0644a03..c77d9a1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,19 +5,11 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' android { - signingConfigs { - release { - keyAlias 'Algorigo' - keyPassword project.property("keyPassword") - storeFile file(project.property("storeFile")) - storePassword project.property("storePassword") - } - } - compileSdkVersion 29 + compileSdkVersion 30 defaultConfig { applicationId "com.algorigo.algorigoblelibrary" - minSdkVersion 18 - targetSdkVersion 29 + minSdkVersion 21 + targetSdkVersion 30 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" @@ -26,7 +18,6 @@ android { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - signingConfig signingConfigs.release } } } @@ -34,11 +25,11 @@ android { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test:runner:1.2.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'androidx.constraintlayout:constraintlayout:2.0.4' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test:runner:1.3.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' implementation 'androidx.recyclerview:recyclerview:1.1.0' @@ -47,5 +38,5 @@ dependencies { //ReactiveX implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' //ReactiveX Relay - implementation 'com.jakewharton.rxrelay2:rxrelay:2.1.0' + implementation 'com.jakewharton.rxrelay2:rxrelay:2.1.1' } diff --git a/app/src/main/java/com/algorigo/algorigoblelibrary/MainActivity.kt b/app/src/main/java/com/algorigo/algorigoblelibrary/MainActivity.kt index 5067e41..1b810b2 100644 --- a/app/src/main/java/com/algorigo/algorigoblelibrary/MainActivity.kt +++ b/app/src/main/java/com/algorigo/algorigoblelibrary/MainActivity.kt @@ -87,7 +87,7 @@ class MainActivity : AppCompatActivity() { // 권한이 없음 -> 퍼미션을 요구 PermissionUtil.requestExternalPermissions( this, - Manifest.permission.ACCESS_COARSE_LOCATION, + arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), REQUEST_CODE ) } diff --git a/app/src/main/java/com/algorigo/algorigoblelibrary/SampleBleDevice.kt b/app/src/main/java/com/algorigo/algorigoblelibrary/SampleBleDevice.kt index 76c5f45..921464a 100644 --- a/app/src/main/java/com/algorigo/algorigoblelibrary/SampleBleDevice.kt +++ b/app/src/main/java/com/algorigo/algorigoblelibrary/SampleBleDevice.kt @@ -1,56 +1,22 @@ package com.algorigo.algorigoblelibrary +import com.algorigo.algorigoble.BleDevice import com.algorigo.algorigoble.InitializableBleDevice import io.reactivex.Completable import io.reactivex.Observable import io.reactivex.Single import java.util.* -class SampleBleDevice: InitializableBleDevice() { +class SampleBleDevice: BleDevice() { private var version = "" - override fun initializeCompletable(): Completable { - return getVersionSingle()!!.doOnSuccess { version = it }.ignoreElement() - } - override fun onDisconnected() { super.onDisconnected() version = "" } - fun sendDataOn(): Observable? { - return setupNotification(UUID.fromString(UUID_SEND_DATA_ON)) - ?.flatMap { it } - } - - fun setVersionSingle(value: String): Single? { - val byteArray = value.toByteArray(Charsets.UTF_8) - return writeCharacteristic(UUID.fromString(UUID_DATA_VERSION), byteArray) - ?.map { - version = it.contentToString() - version - } - } - - fun getVersionSingle(): Single? { - return readCharacteristic(UUID.fromString(UUID_DATA_VERSION)) - ?.map { - version = it.contentToString() - version - } - } - - fun getVersion(): String { - return version - } - companion object { private val TAG = SampleBleDevice::class.java.simpleName - - const val BLE_NAME = "SampleBle" - - private const val UUID_SEND_DATA_ON = "6e400003-b5a3-f393-e0a9-e50e24dcca9e" - private const val UUID_DATA_VERSION = "9fd42004-e46f-7c9a-57b1-2da365e18fa1" } } \ No newline at end of file diff --git a/app/src/main/java/com/algorigo/algorigoblelibrary/SampleBleDeviceActivity.kt b/app/src/main/java/com/algorigo/algorigoblelibrary/SampleBleDeviceActivity.kt index 799e61d..2ee31ff 100644 --- a/app/src/main/java/com/algorigo/algorigoblelibrary/SampleBleDeviceActivity.kt +++ b/app/src/main/java/com/algorigo/algorigoblelibrary/SampleBleDeviceActivity.kt @@ -18,39 +18,14 @@ class SampleBleDeviceActivity : AppCompatActivity() { setContentView(R.layout.activity_sample_ble_device) val macAddress = intent.getStringExtra(NAME_MAC_ADDRESS) - sampleBleDevice = BleManager.getInstance().getDevice(macAddress) as? SampleBleDevice - - periodEdit.setText(sampleBleDevice?.getVersion()?.toString()) - setPeriodBtn.setOnClickListener { - val value = periodEdit.text.toString() - sampleBleDevice?.setVersionSingle(value) - ?.observeOn(AndroidSchedulers.mainThread()) - ?.subscribe({ - periodEdit.setText(it.toString()) - }, { - Log.e(TAG, "", it) - }) - } - getPeriodBtn.setOnClickListener { - periodEdit.setText(sampleBleDevice?.getVersion()?.toString()) - } - sendOnBtn.setOnClickListener { - if (disposable == null) { - disposable = sampleBleDevice?.sendDataOn() - ?.observeOn(AndroidSchedulers.mainThread()) - ?.subscribe({ - dataText.setText(it.contentToString()) - }, { - Log.e(TAG, "", it) - }) - } - } - sendOffBtn.setOnClickListener { - disposable?.let { - it.dispose() - disposable = null - } + if (macAddress != null) { + sampleBleDevice = BleManager.getInstance().getDevice(macAddress) as? SampleBleDevice + } else { + finish() + return } + + dataText.setText("name:${sampleBleDevice?.name}\naddress:${sampleBleDevice?.macAddress}") } companion object { diff --git a/app/src/main/java/com/algorigo/algorigoblelibrary/SampleBleDeviceDelegate.kt b/app/src/main/java/com/algorigo/algorigoblelibrary/SampleBleDeviceDelegate.kt index d640ae5..b16ac30 100644 --- a/app/src/main/java/com/algorigo/algorigoblelibrary/SampleBleDeviceDelegate.kt +++ b/app/src/main/java/com/algorigo/algorigoblelibrary/SampleBleDeviceDelegate.kt @@ -1,6 +1,7 @@ package com.algorigo.algorigoblelibrary import android.bluetooth.BluetoothDevice +import android.util.Log import com.algorigo.algorigoble.BleDevice import com.algorigo.algorigoble.BleManager import com.algorigo.algorigoble.BleScanFilter @@ -9,8 +10,7 @@ import com.algorigo.algorigoble.BleScanSettings class SampleBleDeviceDelegate: BleManager.BleDeviceDelegate() { override fun createBleDevice(bluetoothDevice: BluetoothDevice): BleDevice? { return when (bluetoothDevice.name) { - SampleBleDevice.BLE_NAME -> SampleBleDevice() - else -> null + else -> SampleBleDevice() } } @@ -19,8 +19,6 @@ class SampleBleDeviceDelegate: BleManager.BleDeviceDelegate() { } override fun getBleScanFilters(): Array { - return arrayOf( - BleScanFilter.Builder().setDeviceName(SampleBleDevice.BLE_NAME).build() - ) + return arrayOf() } } \ No newline at end of file diff --git a/app/src/main/java/com/algorigo/algorigoblelibrary/util/PermissionUtil.java b/app/src/main/java/com/algorigo/algorigoblelibrary/util/PermissionUtil.java index daf0e10..66c688f 100644 --- a/app/src/main/java/com/algorigo/algorigoblelibrary/util/PermissionUtil.java +++ b/app/src/main/java/com/algorigo/algorigoblelibrary/util/PermissionUtil.java @@ -56,8 +56,8 @@ public void run() { } } - public static void requestExternalPermissions(Activity activity, String permission, final int requestCode) { - requestPermissions(activity, new String[] { permission }, requestCode); + public static void requestExternalPermissions(Activity activity, String[] permissions, final int requestCode) { + requestPermissions(activity, permissions, requestCode); } public static boolean verifyPermission(int[] grantresults) { diff --git a/app/src/main/res/layout/activity_sample_ble_device.xml b/app/src/main/res/layout/activity_sample_ble_device.xml index 9c12365..bdb675e 100644 --- a/app/src/main/res/layout/activity_sample_ble_device.xml +++ b/app/src/main/res/layout/activity_sample_ble_device.xml @@ -7,51 +7,6 @@ android:orientation="vertical" tools:context=".SampleBleDeviceActivity"> - - -