Penguin Map Integration & Permissions Fixes.
parent
53015422e5
commit
fb4cf08b89
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,51 @@
|
|||||||
|
package com.cloud.diplomaticquarterapp
|
||||||
|
import com.ejada.hmg.MainActivity
|
||||||
|
import android.os.Build
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
import com.cloud.diplomaticquarterapp.penguin.PenguinView
|
||||||
|
import io.flutter.embedding.engine.FlutterEngine
|
||||||
|
import io.flutter.plugin.common.MethodCall
|
||||||
|
import io.flutter.plugin.common.MethodChannel
|
||||||
|
|
||||||
|
class PenguinInPlatformBridge(
|
||||||
|
private var flutterEngine: FlutterEngine,
|
||||||
|
private var mainActivity: MainActivity
|
||||||
|
) {
|
||||||
|
|
||||||
|
private lateinit var channel: MethodChannel
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val CHANNEL = "launch_penguin_ui"
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
|
fun create() {
|
||||||
|
// openTok = OpenTok(mainActivity, flutterEngine)
|
||||||
|
channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
|
||||||
|
channel.setMethodCallHandler { call: MethodCall, result: MethodChannel.Result ->
|
||||||
|
when (call.method) {
|
||||||
|
"launchPenguin" -> {
|
||||||
|
print("the platform channel is being called")
|
||||||
|
val args = call.arguments as Map<String, Any>?
|
||||||
|
Log.d("TAG", "configureFlutterEngine: $args")
|
||||||
|
println("args")
|
||||||
|
args?.let {
|
||||||
|
PenguinView(
|
||||||
|
mainActivity,
|
||||||
|
100,
|
||||||
|
args,
|
||||||
|
flutterEngine.dartExecutor.binaryMessenger,
|
||||||
|
activity = mainActivity,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
result.notImplemented()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
package com.cloud.diplomaticquarterapp.PermissionManager
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
|
||||||
|
object PermissionHelper {
|
||||||
|
|
||||||
|
fun getRequiredPermissions(): Array<String> {
|
||||||
|
return arrayOf(
|
||||||
|
Manifest.permission.INTERNET,
|
||||||
|
Manifest.permission.ACCESS_FINE_LOCATION,
|
||||||
|
Manifest.permission.ACCESS_COARSE_LOCATION,
|
||||||
|
Manifest.permission.ACCESS_NETWORK_STATE,
|
||||||
|
Manifest.permission.BLUETOOTH,
|
||||||
|
Manifest.permission.BLUETOOTH_ADMIN,
|
||||||
|
Manifest.permission.BLUETOOTH_SCAN,
|
||||||
|
Manifest.permission.BLUETOOTH_CONNECT,
|
||||||
|
Manifest.permission.HIGH_SAMPLING_RATE_SENSORS,
|
||||||
|
// Manifest.permission.ACTIVITY_RECOGNITION
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
package com.cloud.diplomaticquarterapp.PermissionManager
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Build
|
||||||
|
import androidx.core.app.ActivityCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
|
||||||
|
class PermissionManager(
|
||||||
|
private val context: Context,
|
||||||
|
val listener: PermissionListener,
|
||||||
|
private val requestCode: Int,
|
||||||
|
vararg permissions: String
|
||||||
|
) {
|
||||||
|
|
||||||
|
private val permissionsArray = permissions
|
||||||
|
|
||||||
|
interface PermissionListener {
|
||||||
|
fun onPermissionGranted()
|
||||||
|
fun onPermissionDenied()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun arePermissionsGranted(): Boolean {
|
||||||
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
permissionsArray.all {
|
||||||
|
ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun requestPermissions(activity: Activity) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
ActivityCompat.requestPermissions(activity, permissionsArray, requestCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handlePermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||||
|
if (this.requestCode == requestCode) {
|
||||||
|
val allGranted = grantResults.all { it == PackageManager.PERMISSION_GRANTED }
|
||||||
|
if (allGranted) {
|
||||||
|
listener.onPermissionGranted()
|
||||||
|
} else {
|
||||||
|
listener.onPermissionDenied()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
package com.cloud.diplomaticquarterapp.PermissionManager
|
||||||
|
|
||||||
|
// PermissionResultReceiver.kt
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
|
||||||
|
class PermissionResultReceiver(
|
||||||
|
private val callback: (Boolean) -> Unit
|
||||||
|
) : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
|
val granted = intent?.getBooleanExtra("PERMISSION_GRANTED", false) ?: false
|
||||||
|
callback(granted)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,261 @@
|
|||||||
|
package com.cloud.diplomaticquarterapp.penguin
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Context.RECEIVER_EXPORTED
|
||||||
|
import android.content.IntentFilter
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.os.Build
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.RelativeLayout
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
import com.cloud.diplomaticquarterapp.PermissionManager.PermissionHelper
|
||||||
|
import com.cloud.diplomaticquarterapp.PermissionManager.PermissionManager
|
||||||
|
import com.cloud.diplomaticquarterapp.PermissionManager.PermissionResultReceiver
|
||||||
|
import com.ejada.hmg.MainActivity
|
||||||
|
import com.peng.pennavmap.PlugAndPlayConfiguration
|
||||||
|
import com.peng.pennavmap.PlugAndPlaySDK
|
||||||
|
import com.peng.pennavmap.enums.InitializationErrorType
|
||||||
|
import com.peng.pennavmap.interfaces.PenNavUIDelegate
|
||||||
|
import com.peng.pennavmap.utils.Languages
|
||||||
|
import io.flutter.plugin.common.BinaryMessenger
|
||||||
|
import io.flutter.plugin.common.MethodCall
|
||||||
|
import io.flutter.plugin.common.MethodChannel
|
||||||
|
import io.flutter.plugin.platform.PlatformView
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom PlatformView for displaying Penguin UI components within a Flutter app.
|
||||||
|
* Implements `PlatformView` for rendering the view, `MethodChannel.MethodCallHandler` for handling method calls,
|
||||||
|
* and `PenNavUIDelegate` for handling SDK events.
|
||||||
|
*/
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
|
internal class PenguinView(
|
||||||
|
context: Context,
|
||||||
|
id: Int,
|
||||||
|
val creationParams: Map<String, Any>,
|
||||||
|
messenger: BinaryMessenger,
|
||||||
|
activity: MainActivity
|
||||||
|
) : PlatformView, MethodChannel.MethodCallHandler, PenNavUIDelegate {
|
||||||
|
// The layout for displaying the Penguin UI
|
||||||
|
private val mapLayout: RelativeLayout = RelativeLayout(context)
|
||||||
|
private val _context: Context = context
|
||||||
|
|
||||||
|
private val permissionResultReceiver: PermissionResultReceiver
|
||||||
|
private val permissionIntentFilter = IntentFilter("PERMISSION_RESULT_ACTION")
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
const val PERMISSIONS_REQUEST_CODE = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
private lateinit var permissionManager: PermissionManager
|
||||||
|
|
||||||
|
// Reference to the main activity
|
||||||
|
private var _activity: Activity = activity
|
||||||
|
|
||||||
|
private lateinit var mContext: Context
|
||||||
|
|
||||||
|
init {
|
||||||
|
// Set layout parameters for the mapLayout
|
||||||
|
mapLayout.layoutParams = ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
)
|
||||||
|
|
||||||
|
mContext = context
|
||||||
|
|
||||||
|
|
||||||
|
permissionResultReceiver = PermissionResultReceiver { granted ->
|
||||||
|
if (granted) {
|
||||||
|
onPermissionsGranted()
|
||||||
|
} else {
|
||||||
|
onPermissionsDenied()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
mContext.registerReceiver(
|
||||||
|
permissionResultReceiver,
|
||||||
|
permissionIntentFilter,
|
||||||
|
RECEIVER_EXPORTED
|
||||||
|
)
|
||||||
|
}else{
|
||||||
|
mContext.registerReceiver(
|
||||||
|
permissionResultReceiver,
|
||||||
|
permissionIntentFilter,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the background color of the layout
|
||||||
|
mapLayout.setBackgroundColor(Color.RED)
|
||||||
|
|
||||||
|
permissionManager = PermissionManager(
|
||||||
|
context = mContext,
|
||||||
|
listener = object : PermissionManager.PermissionListener {
|
||||||
|
override fun onPermissionGranted() {
|
||||||
|
// Handle permissions granted
|
||||||
|
onPermissionsGranted()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPermissionDenied() {
|
||||||
|
// Handle permissions denied
|
||||||
|
onPermissionsDenied()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
requestCode = PERMISSIONS_REQUEST_CODE,
|
||||||
|
*PermissionHelper.getRequiredPermissions()
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!permissionManager.arePermissionsGranted()) {
|
||||||
|
permissionManager.requestPermissions(_activity)
|
||||||
|
} else {
|
||||||
|
// Permissions already granted
|
||||||
|
permissionManager.listener.onPermissionGranted()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onPermissionsGranted() {
|
||||||
|
// Handle the actions when permissions are granted
|
||||||
|
Log.d("PermissionsResult", "onPermissionsGranted")
|
||||||
|
// Register the platform view factory for creating custom views
|
||||||
|
|
||||||
|
// Initialize the Penguin SDK
|
||||||
|
initPenguin()
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onPermissionsDenied() {
|
||||||
|
// Handle the actions when permissions are denied
|
||||||
|
Log.d("PermissionsResult", "onPermissionsDenied")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the view associated with this PlatformView.
|
||||||
|
*
|
||||||
|
* @return The main view for this PlatformView.
|
||||||
|
*/
|
||||||
|
override fun getView(): View {
|
||||||
|
return mapLayout
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleans up resources associated with this PlatformView.
|
||||||
|
*/
|
||||||
|
override fun dispose() {
|
||||||
|
// Cleanup code if needed
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles method calls from Dart code.
|
||||||
|
*
|
||||||
|
* @param call The method call from Dart.
|
||||||
|
* @param result The result callback to send responses back to Dart.
|
||||||
|
*/
|
||||||
|
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
|
||||||
|
// Handle method calls from Dart code here
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the Penguin SDK with custom configuration and delegates.
|
||||||
|
*/
|
||||||
|
private fun initPenguin() {
|
||||||
|
// Configure the PlugAndPlaySDK
|
||||||
|
val language = when (creationParams["languageCode"] as String) {
|
||||||
|
"ar" -> Languages.ar
|
||||||
|
"en" -> Languages.en
|
||||||
|
else -> {
|
||||||
|
Languages.en
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.d(
|
||||||
|
"TAG",
|
||||||
|
"initPenguin: ${Languages.getLanguageEnum(creationParams["languageCode"] as String)}"
|
||||||
|
)
|
||||||
|
PlugAndPlaySDK.configuration = PlugAndPlayConfiguration.Builder()
|
||||||
|
.setBaseUrl(
|
||||||
|
creationParams["baseURL"] as String,
|
||||||
|
creationParams["positionURL"] as String
|
||||||
|
)
|
||||||
|
.setServiceName(
|
||||||
|
creationParams["dataServiceName"] as String,
|
||||||
|
creationParams["positionServiceName"] as String
|
||||||
|
)
|
||||||
|
.setClientData(
|
||||||
|
creationParams["clientID"] as String,
|
||||||
|
creationParams["clientKey"] as String
|
||||||
|
)
|
||||||
|
.setUserName(creationParams["username"] as String)
|
||||||
|
// .setLanguageID(Languages.en)
|
||||||
|
.setLanguageID(language)
|
||||||
|
.setSimulationModeEnabled(creationParams["isSimulationModeEnabled"] as Boolean)
|
||||||
|
.setEnableBackButton(true)
|
||||||
|
.setDeepLinkData("deeplink")
|
||||||
|
.setCustomizeColor("#2CA0AF")
|
||||||
|
.setDeepLinkSchema("")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
// Set location delegate to handle location updates
|
||||||
|
PlugAndPlaySDK.setPiLocationDelegate {
|
||||||
|
// Example code to handle location updates
|
||||||
|
// Uncomment and modify as needed
|
||||||
|
// if (location.size() > 0)
|
||||||
|
// Toast.makeText(_context, "Location Info Latitude: ${location[0]}, Longitude: ${location[1]}", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set events delegate for reporting issues
|
||||||
|
PlugAndPlaySDK.setPiEventsDelegate { }
|
||||||
|
|
||||||
|
// Start the Penguin SDK
|
||||||
|
PlugAndPlaySDK.start(mContext, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when Penguin UI setup is successful.
|
||||||
|
*
|
||||||
|
* @param warningCode Optional warning code received from the SDK.
|
||||||
|
*/
|
||||||
|
override fun onPenNavSuccess(warningCode: String?) {
|
||||||
|
// if (_context is Activity) {
|
||||||
|
// _context.runOnUiThread {
|
||||||
|
// Toast.makeText(_context, "Success Info: $warningCode", Toast.LENGTH_SHORT).show()
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// println("the warming is presented $$warningCode")
|
||||||
|
//// val handler = Handler(Looper.getMainLooper())
|
||||||
|
//// handler.post {
|
||||||
|
//// Toast.makeText(_context, "Success Info: $warningCode", Toast.LENGTH_SHORT).show()
|
||||||
|
//// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when there is an initialization error with Penguin UI.
|
||||||
|
*
|
||||||
|
* @param description Description of the error.
|
||||||
|
* @param errorType Type of initialization error.
|
||||||
|
*/
|
||||||
|
override fun onPenNavInitializationError(
|
||||||
|
description: String?,
|
||||||
|
errorType: InitializationErrorType?
|
||||||
|
) {
|
||||||
|
Toast.makeText(mContext, "Navigation Error: $description", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when Penguin UI is dismissed.
|
||||||
|
*/
|
||||||
|
override fun onPenNavUIDismiss() {
|
||||||
|
// Handle UI dismissal if needed
|
||||||
|
try {
|
||||||
|
mContext.unregisterReceiver(permissionResultReceiver)
|
||||||
|
dispose();
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
Log.e("PenguinView", "Receiver not registered: $e")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Reference in New Issue