Skip to content

Commit

Permalink
Merge pull request #1 from cafebazaar/dev
Browse files Browse the repository at this point in the history
Initialize the project
  • Loading branch information
hbazargan authored Jan 3, 2022
2 parents 6464a63 + fb0e427 commit e07d92c
Show file tree
Hide file tree
Showing 49 changed files with 1,099 additions and 1 deletion.
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
3 changes: 3 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
# ServiceBase
# ServiceBase
This is a base library in order to use by other libraries which need to implement AIDL and BroadCast connection with Bazaar client.
1 change: 1 addition & 0 deletions ServiceBase/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
45 changes: 45 additions & 0 deletions ServiceBase/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
plugins {
id 'com.android.library'
id 'kotlin-android'
id 'maven-publish'
}

android {
compileSdk 30
buildToolsVersion '31.0.0'

defaultConfig {
minSdk 17
targetSdk 30
versionCode 1
versionName "1.0"

}

buildTypes {
release {
minifyEnabled false
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}

dependencies {
implementation "androidx.core:core-ktx:1.6.0"
}

afterEvaluate {
publishing {
publications {
release(MavenPublication) {
from components.release
}
}
}
}
2 changes: 2 additions & 0 deletions ServiceBase/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.cafebazaar.servicebase" />
165 changes: 165 additions & 0 deletions ServiceBase/src/main/java/com/cafebazaar/servicebase/Client.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package com.cafebazaar.servicebase

import android.content.Context
import android.os.Looper
import com.cafebazaar.servicebase.communicator.ClientConnectionCommunicator
import com.cafebazaar.servicebase.communicator.ClientReceiverCommunicator
import com.cafebazaar.servicebase.receiver.ClientReceiver
import com.cafebazaar.servicebase.state.ClientError
import com.cafebazaar.servicebase.state.ClientStateListener

abstract class Client(private val context: Context) {

private var clientStateListener: ClientStateListener? = null

protected abstract val supportedClientVersion: Long
protected abstract fun getServiceConnection(): ClientConnectionCommunicator?
protected abstract fun getBroadcastConnections(): ClientConnectionCommunicator?

@Volatile private var clientState = DISCONNECTED
@Volatile protected var clientConnection: ClientConnectionCommunicator? = null

private val isReady: Boolean
get() = (clientState == CONNECTED)
.and(clientConnection != null)

fun startConnection(clientStateListener: ClientStateListener) {
this.clientStateListener = clientStateListener
if (isNotBazaarInstalled(clientStateListener)) return
if (isNotBazaarCompatible(clientStateListener)) return
throwExceptionIfRunningOnMainThread()
startingConnection(clientStateListener)
}

private fun isNotBazaarCompatible(clientStateListener: ClientStateListener): Boolean {
if (getBazaarVersionCode(context) < supportedClientVersion) {
handleErrorOnBazaarIsNotCompatible(clientStateListener)
return true
}
return false
}

private fun isNotBazaarInstalled(clientStateListener: ClientStateListener): Boolean {
if (verifyBazaarIsInstalled(context).not()) {
handleErrorOnBazaarIsNotInstalled(clientStateListener)
return true
}
return false
}

private fun handleErrorOnBazaarIsNotCompatible(clientStateListener: ClientStateListener) {
clientState = DISCONNECTED
clientStateListener.onError(
ClientError.ERROR_BAZAAR_IS_NOT_COMPATIBLE
)
}

private fun handleErrorOnBazaarIsNotInstalled(clientStateListener: ClientStateListener) {
clientState = DISCONNECTED
clientStateListener.onError(
ClientError.ERROR_BAZAAR_IS_NOT_INSTALL
)
}

private fun startingConnection(clientStateListener: ClientStateListener) {
if (isReady.not()) {
if (clientState == CONNECTING) {
clientStateListener.onError(
ClientError.ERROR_SDK_IS_STARTED
)
return
}
tryToConnect(clientStateListener)
} else {
clientStateListener.onReady()
}
}

private fun tryToConnect(clientStateListener: ClientStateListener) {
clientState = CONNECTING
if (tryConnectingByService()) return
if (tryConnectingByBroadcast()) return
clientState = DISCONNECTED
clientStateListener.onError(
ClientError.ERROR_SDK_COULD_NOT_CONNECT
)
}

private fun tryConnectingByBroadcast(): Boolean {
getBroadcastConnections()?.let { connection ->
if (connection is ClientReceiverCommunicator) {
ClientReceiver.addObserver(connection)
}
if (connection.startConnection()) {
clientConnection = connection
updateClientStateToConnected()
return true
}
}
return false
}

private fun tryConnectingByService(): Boolean {
synchronized(this) {
getServiceConnection()?.let { connection ->
if (connection.startConnection()) {
clientConnection = connection
return true
}
}
return false
}
}

protected fun updateClientStateToConnected() {
synchronized(this) {
clientState = CONNECTED
clientStateListener?.onReady()
}
}

private fun throwExceptionIfRunningOnMainThread() {
if (Looper.myLooper() == Looper.getMainLooper()) {
throw IllegalThreadStateException(OFF_MAIN_THREAD_EXCEPTION)
}
}

fun endConnection() {
clientStateListener = null
clientConnection?.let { connection ->
if (connection is ClientReceiverCommunicator) {
ClientReceiver.removeObserver(connection)
}
connection.stopConnection()
}
clientState = DISCONNECTED
}

protected fun errorOccurred(clientError: ClientError) {
clientStateListener?.onError(clientError)
}

@Throws(IllegalStateException::class)
protected fun <T> runIfReady(block: () -> T?): T? {
if (isReady.not()) {
throw IllegalStateException(SERVICE_IS_NOT_STARTED_EXCEPTION)
} else {
return block.invoke()
}
}

private fun verifyBazaarIsInstalled(context: Context): Boolean {
return getBazaarPackageInfo(context) != null
}

companion object {
const val SERVICE_PACKAGE_NAME = "com.farsitel.bazaar"

private const val OFF_MAIN_THREAD_EXCEPTION = "This function has to call off the main thread."
private const val SERVICE_IS_NOT_STARTED_EXCEPTION =
"Service not connected. Please start a connection before using the service."
private const val DISCONNECTED = 0
private const val CONNECTING = 1
private const val CONNECTED = 2
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.cafebazaar.servicebase

import android.content.Context
import android.content.pm.PackageInfo
import android.os.Build

internal fun getBazaarPackageInfo(context: Context): PackageInfo? {
return try {
val packageManager = context.packageManager
packageManager.getPackageInfo(Client.SERVICE_PACKAGE_NAME, 0)
} catch (ignored: Exception) {
null
}
}

internal fun getBazaarVersionCode(context: Context) = getBazaarPackageInfo(context)?.let {
sdkAwareVersionCode(it)
} ?: 0L

internal fun sdkAwareVersionCode(packageInfo: PackageInfo): Long {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
packageInfo.longVersionCode
} else {
packageInfo.versionCode.toLong()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.cafebazaar.servicebase.communicator

interface ClientConnectionCommunicator {

fun startConnection(): Boolean

fun stopConnection()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.cafebazaar.servicebase.communicator

import android.content.Intent

interface ClientReceiverCommunicator {

fun onNewBroadcastReceived(intent: Intent?)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.cafebazaar.servicebase.receiver

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import com.cafebazaar.servicebase.communicator.ClientReceiverCommunicator

class ClientReceiver: BroadcastReceiver() {

override fun onReceive(context: Context?, intent: Intent?) {
intent?.let {
notifyObservers(it)
}
}

private fun notifyObservers(intent: Intent) {
synchronized(observerLock) {
for (observer in observers) {
observer.onNewBroadcastReceived(intent)
}
}
}

companion object {

private val observerLock = Any()
private val observers = mutableListOf<ClientReceiverCommunicator>()

fun addObserver(communicator: ClientReceiverCommunicator) {
synchronized(observerLock) {
observers.add(communicator)
}
}

fun removeObserver(communicator: ClientReceiverCommunicator) {
synchronized(observerLock) {
observers.remove(communicator)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.cafebazaar.servicebase.state

enum class ClientError(var message: String) {
ERROR_BAZAAR_IS_NOT_INSTALL("Bazaar Client Is Not Installed"),
ERROR_BAZAAR_IS_NOT_COMPATIBLE("Bazaar Client Is Not Compatible"),
ERROR_SDK_COULD_NOT_CONNECT("SDK Could Not Connect"),
ERROR_SDK_IS_STARTED("SDK Is Started"),
ERROR_DURING_GETTING_REFERRER_DETAILS("Error during getting referrer details"),
ERROR_DURING_CONSUMING_REFERRER("Error during consuming referrer")
}
Loading

0 comments on commit e07d92c

Please sign in to comment.