diff --git a/.gitignore b/.gitignore index be7a8b3..e4cd4e0 100644 --- a/.gitignore +++ b/.gitignore @@ -17,12 +17,15 @@ local.properties .idea/libraries/ .idea/workspace.xml .idea/tasks.xml +.idea/caches/ .idea/.name .idea/compiler.xml +.idea/gradle.xml .idea/copyright/profiles_settings.xml .idea/encodings.xml .idea/misc.xml .idea/modules.xml +.idea/runConfigurations.xml .idea/scopes/scope_settings.xml .idea/vcs.xml *.iml diff --git a/build.gradle b/build.gradle index ee2a4a9..c7ee934 100755 --- a/build.gradle +++ b/build.gradle @@ -1,41 +1,19 @@ -apply plugin: 'com.android.library' +buildscript { + ext.kotlin_version = '1.2.71' -android { - compileSdkVersion 25 - buildToolsVersion "25.0.2" - defaultConfig { - minSdkVersion 14 - targetSdkVersion 25 - versionCode 3 - versionName '0.3' - version 0.3 - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - productFlavors { - } -} - -buildscript { repositories { jcenter() + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.2.0' - } + classpath 'com.android.tools.build:gradle:3.2.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } -repositories { - jcenter() - mavenCentral() -} - -dependencies { - compile 'com.android.support:support-annotations:25.3.1' - compile 'com.arasthel:asyncjob-library:1.0.3' - compile 'com.bluelinelabs:logansquare:1.0.6' +allprojects { + repositories { + jcenter() + mavenCentral() + google() + } } diff --git a/demo/.gitignore b/demo/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/demo/.gitignore @@ -0,0 +1 @@ +/build diff --git a/demo/build.gradle b/demo/build.gradle new file mode 100644 index 0000000..3ff0496 --- /dev/null +++ b/demo/build.gradle @@ -0,0 +1,44 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' +android { + compileSdkVersion 28 + + + + defaultConfig { + applicationId "com.peak.salut.demo" + minSdkVersion 14 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation project(':library') + + annotationProcessor 'com.bluelinelabs:logansquare-compiler:1.3.7' + implementation 'com.bluelinelabs:logansquare:1.3.7' + + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + implementation 'com.android.support:recyclerview-v7:28.0.0' + implementation 'com.pascalwelsch.arrayadapter:arrayadapter:1.3.0' +} diff --git a/demo/proguard-rules.pro b/demo/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/demo/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/demo/src/main/AndroidManifest.xml b/demo/src/main/AndroidManifest.xml new file mode 100644 index 0000000..1df0c72 --- /dev/null +++ b/demo/src/main/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/src/main/java/com/peak/salut/demo/MainActivity.kt b/demo/src/main/java/com/peak/salut/demo/MainActivity.kt new file mode 100644 index 0000000..b563b9e --- /dev/null +++ b/demo/src/main/java/com/peak/salut/demo/MainActivity.kt @@ -0,0 +1,175 @@ +package com.peak.salut.demo + +import android.app.PendingIntent.getActivity +import android.os.Bundle +import android.support.v7.app.AppCompatActivity +import android.support.v7.widget.LinearLayoutManager +import android.support.v7.widget.RecyclerView +import android.util.Log +import android.view.* +import android.widget.Button +import android.widget.TextView +import android.widget.Toast +import com.bluelinelabs.logansquare.LoganSquare +import com.pascalwelsch.arrayadapter.ArrayAdapter +import com.peak.salut.Callbacks.SalutCallback +import com.peak.salut.Callbacks.SalutDataCallback +import com.peak.salut.Callbacks.SalutDeviceCallback +import com.peak.salut.Salut +import com.peak.salut.SalutDataReceiver +import com.peak.salut.SalutDevice +import com.peak.salut.SalutServiceData +import kotlinx.android.synthetic.main.activity_main.* +import java.util.* + +class MainActivity : AppCompatActivity() { + + enum class UiState { + DEFAULT, + HOST_MODE, + CLIENT_MODE + } + + class MySalut(dataReceiver: SalutDataReceiver?, salutServiceData: SalutServiceData?, deviceNotSupported: SalutCallback?) : Salut(dataReceiver, salutServiceData, deviceNotSupported) { + override fun serialize(o: Any?): String { + return LoganSquare.serialize(o) + } + } + + private lateinit var salut: Salut + private var uiState = UiState.DEFAULT + + private lateinit var connectedDevicesAdapter: SimpleAdapter + + companion object { + const val TAG = "SalutDemo" + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + val dataReceiver = SalutDataReceiver(this, SalutDataCallback { + + }) + + val instanceName = "Demo ID ${Random().nextInt(200)}" + + instanceNameLabel.text = "My Instance Name: $instanceName" + + val serviceData = SalutServiceData("sas", 50489, instanceName) + + salut = MySalut(dataReceiver, serviceData, SalutCallback { + Log.e(TAG, "Device does not support WiFi P2P") + }) + + list.layoutManager = LinearLayoutManager(this) + connectedDevicesAdapter = SimpleAdapter() + list.adapter = connectedDevicesAdapter + + startService.setOnClickListener { _ -> + updateUiState(UiState.HOST_MODE) + + salut.startNetworkService({ + connectedDevicesAdapter.add(it) + Toast.makeText(this.baseContext, it.readableName + " connected.", Toast.LENGTH_SHORT).show(); + }, { + Log.d(TAG, "Network service started") + }, { + Log.e(TAG, "Can not start network service") + }) + } + + connectService.setOnClickListener { _ -> + updateUiState(UiState.CLIENT_MODE) + + connectedDevicesAdapter.setAction("Connect") { position -> + val salutDevice = connectedDevicesAdapter.getItem(position) + salut.registerWithHost(salutDevice, { + Log.d(TAG, "Successfully registered") + Toast.makeText(this.baseContext, "Successfully connected to " + this.salut.registeredHost.readableName, Toast.LENGTH_SHORT).show(); + }, { + Log.e(TAG, "Error registering") + }) + } + + salut.discoverNetworkServices(SalutDeviceCallback { + connectedDevicesAdapter.add(it) + + + }, true) + } + } + + override fun onCreateOptionsMenu(menu: Menu?): Boolean { + MenuInflater(this).inflate(R.menu.menu_demo, menu) + + if (uiState == UiState.DEFAULT) { + menu?.removeItem(R.id.stop) + } + + return true + } + + override fun onOptionsItemSelected(item: MenuItem?): Boolean { + if (item?.itemId == R.id.stop) { + if (uiState == UiState.HOST_MODE) { + salut.stopNetworkService(false) + updateUiState(UiState.DEFAULT) + } else if (uiState == UiState.CLIENT_MODE) { + salut.stopServiceDiscovery(true) + updateUiState(UiState.DEFAULT) + } + return true + } + + return false + } + + private fun updateUiState(mode: UiState) { + this.uiState = mode + startService.visibility = if (mode == UiState.HOST_MODE) View.VISIBLE else View.GONE + connectService.visibility = if (mode == UiState.CLIENT_MODE) View.VISIBLE else View.GONE + + invalidateOptionsMenu() + } + + class SimpleAdapter : ArrayAdapter() { + + private var actionTitle: String? = null + private var action: ((index: Int) -> Unit)? = null + + fun setAction(title: String, action: ((index: Int) -> Unit)) { + actionTitle = title + this.action = action + + notifyDataSetChanged() + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SimpleViewHolder { + val view = LayoutInflater.from(parent.context) + return SimpleViewHolder(view.inflate(R.layout.list_item_device, parent, false)) + } + + override fun getItemId(item: SalutDevice): Any? { + return item.macAddress + } + + override fun onBindViewHolder(viewHolder: SimpleViewHolder, position: Int) { + viewHolder.titleView.text = getItem(position)?.instanceName + + viewHolder.action.visibility = if (action != null) View.VISIBLE else View.GONE + if (action != null) { + viewHolder.action.text = actionTitle + viewHolder.action.setOnClickListener { _ -> + action?.let { it -> it(position) } + } + } + } + } + + class SimpleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val titleView: TextView = itemView.findViewById(R.id.title) + val action: Button = itemView.findViewById(R.id.action) + } +} diff --git a/demo/src/main/res/drawable-hdpi/ic_action_cancel.png b/demo/src/main/res/drawable-hdpi/ic_action_cancel.png new file mode 100644 index 0000000..d26711c Binary files /dev/null and b/demo/src/main/res/drawable-hdpi/ic_action_cancel.png differ diff --git a/demo/src/main/res/drawable-mdpi/ic_action_cancel.png b/demo/src/main/res/drawable-mdpi/ic_action_cancel.png new file mode 100644 index 0000000..bc27fd1 Binary files /dev/null and b/demo/src/main/res/drawable-mdpi/ic_action_cancel.png differ diff --git a/demo/src/main/res/drawable-v24/ic_launcher_foreground.xml b/demo/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..1f6bb29 --- /dev/null +++ b/demo/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/demo/src/main/res/drawable-xhdpi/ic_action_cancel.png b/demo/src/main/res/drawable-xhdpi/ic_action_cancel.png new file mode 100644 index 0000000..8f037dc Binary files /dev/null and b/demo/src/main/res/drawable-xhdpi/ic_action_cancel.png differ diff --git a/demo/src/main/res/drawable-xxhdpi/ic_action_cancel.png b/demo/src/main/res/drawable-xxhdpi/ic_action_cancel.png new file mode 100644 index 0000000..c3ad30b Binary files /dev/null and b/demo/src/main/res/drawable-xxhdpi/ic_action_cancel.png differ diff --git a/demo/src/main/res/drawable-xxxhdpi/ic_action_cancel.png b/demo/src/main/res/drawable-xxxhdpi/ic_action_cancel.png new file mode 100644 index 0000000..a25191a Binary files /dev/null and b/demo/src/main/res/drawable-xxxhdpi/ic_action_cancel.png differ diff --git a/demo/src/main/res/drawable/ic_launcher_background.xml b/demo/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..0d025f9 --- /dev/null +++ b/demo/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/src/main/res/layout/activity_main.xml b/demo/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..b1f108d --- /dev/null +++ b/demo/src/main/res/layout/activity_main.xml @@ -0,0 +1,68 @@ + + + +