Initial Commit
commit
d0709a4c54
@ -0,0 +1,2 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
@ -0,0 +1,43 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
**/ios/Flutter/.last_build_id
|
||||
.dart_tool/
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
.pub-cache/
|
||||
.pub/
|
||||
/build/
|
||||
|
||||
# Symbolication related
|
||||
app.*.symbols
|
||||
|
||||
# Obfuscation related
|
||||
app.*.map.json
|
||||
|
||||
# Android Studio will place build artifacts here
|
||||
/android/app/debug
|
||||
/android/app/profile
|
||||
/android/app/release
|
@ -0,0 +1,30 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: "5dcb86f68f239346676ceb1ed1ea385bd215fba1"
|
||||
channel: "stable"
|
||||
|
||||
project_type: app
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
|
||||
base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
|
||||
- platform: android
|
||||
create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
|
||||
base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:
|
||||
- 'lib/main.dart'
|
||||
- 'ios/Runner.xcodeproj/project.pbxproj'
|
@ -0,0 +1,28 @@
|
||||
# This file configures the analyzer, which statically analyzes Dart code to
|
||||
# check for errors, warnings, and lints.
|
||||
#
|
||||
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
||||
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
||||
# invoked from the command line by running `flutter analyze`.
|
||||
|
||||
# The following line activates a set of recommended lints for Flutter apps,
|
||||
# packages, and plugins designed to encourage good coding practices.
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
linter:
|
||||
# The lint rules applied to this project can be customized in the
|
||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||
# included above or to enable additional rules. A list of all available lints
|
||||
# and their documentation is published at https://dart.dev/lints.
|
||||
#
|
||||
# Instead of disabling a lint rule for the entire project in the
|
||||
# section below, it can also be suppressed for a single line of code
|
||||
# or a specific dart file by using the `// ignore: name_of_lint` and
|
||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||
# producing the lint.
|
||||
rules:
|
||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
@ -0,0 +1,13 @@
|
||||
gradle-wrapper.jar
|
||||
/.gradle
|
||||
/captures/
|
||||
/gradlew
|
||||
/gradlew.bat
|
||||
/local.properties
|
||||
GeneratedPluginRegistrant.java
|
||||
|
||||
# Remember to never publicly share your keystore.
|
||||
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
|
||||
key.properties
|
||||
**/*.keystore
|
||||
**/*.jks
|
@ -0,0 +1,133 @@
|
||||
plugins {
|
||||
id "com.android.application"
|
||||
id "kotlin-android"
|
||||
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||
id "dev.flutter.flutter-gradle-plugin"
|
||||
}
|
||||
|
||||
def localProperties = new Properties()
|
||||
def localPropertiesFile = rootProject.file("local.properties")
|
||||
if (localPropertiesFile.exists()) {
|
||||
localPropertiesFile.withReader("UTF-8") { reader ->
|
||||
localProperties.load(reader)
|
||||
}
|
||||
}
|
||||
|
||||
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
|
||||
if (flutterVersionCode == null) {
|
||||
flutterVersionCode = "1"
|
||||
}
|
||||
|
||||
def flutterVersionName = localProperties.getProperty("flutter.versionName")
|
||||
if (flutterVersionName == null) {
|
||||
flutterVersionName = "1.0"
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.eventtan.test.penguin_flutter_sample"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = flutter.ndkVersion
|
||||
|
||||
compileOptions {
|
||||
coreLibraryDesugaringEnabled true
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
dataBinding true
|
||||
buildConfig true
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = '17'
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId = "com.eventtan.test.penguin_flutter_sample"
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
|
||||
minSdk = 24
|
||||
targetSdk = flutter.targetSdkVersion
|
||||
versionCode = flutterVersionCode.toInteger()
|
||||
versionName = flutterVersionName
|
||||
}
|
||||
|
||||
|
||||
|
||||
signingConfigs {
|
||||
release {
|
||||
storeFile file("key.jks")
|
||||
storePassword "123456"
|
||||
keyAlias "key0"
|
||||
keyPassword "123456"
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
signingConfig signingConfigs.release
|
||||
|
||||
|
||||
}
|
||||
|
||||
debug {
|
||||
debuggable true
|
||||
minifyEnabled true
|
||||
signingConfig signingConfigs.release
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
flutter {
|
||||
source = "../.."
|
||||
}
|
||||
|
||||
dependencies {
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
|
||||
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.4.0'
|
||||
implementation 'com.google.android.material:material:1.9.0'
|
||||
|
||||
implementation"androidx.multidex:multidex:2.0.1"
|
||||
|
||||
|
||||
// Penguin Pre-libraries
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.3'
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
||||
implementation 'com.squareup.retrofit2:adapter-java8:2.4.0'
|
||||
implementation 'com.google.code.gson:gson:2.8.9'
|
||||
implementation 'com.google.android.gms:play-services-location:21.0.1'
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
|
||||
implementation 'androidx.test.ext:junit:1.1.5'
|
||||
implementation 'com.android.volley:volley:1.2.1'
|
||||
def room_version = "2.4.0-alpha04"
|
||||
implementation "androidx.room:room-runtime:$room_version"
|
||||
annotationProcessor "androidx.room:room-compiler:$room_version"
|
||||
implementation 'net.zetetic:android-database-sqlcipher:4.5.2'
|
||||
implementation 'com.intuit.ssp:ssp-android:1.1.0'
|
||||
implementation 'com.intuit.sdp:sdp-android:1.1.0'
|
||||
implementation 'com.github.bumptech.glide:glide:4.12.0'
|
||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
|
||||
implementation 'com.mapbox.maps:android:10.16.6'
|
||||
|
||||
|
||||
implementation files('libs/PenNavUI.aar')
|
||||
implementation files('libs/Penguin.aar')
|
||||
implementation files('libs/PenguinRenderer.aar')
|
||||
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,49 @@
|
||||
# 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
|
||||
|
||||
-dontwarn org.bouncycastle.jsse.BCSSLParameters
|
||||
-dontwarn org.bouncycastle.jsse.BCSSLSocket
|
||||
-dontwarn org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
|
||||
-dontwarn org.conscrypt.Conscrypt$Version
|
||||
-dontwarn org.conscrypt.Conscrypt
|
||||
-dontwarn org.conscrypt.ConscryptHostnameVerifier
|
||||
-dontwarn org.openjsse.javax.net.ssl.SSLParameters
|
||||
-dontwarn org.openjsse.javax.net.ssl.SSLSocket
|
||||
-dontwarn org.openjsse.net.ssl.OpenJSSE
|
||||
|
||||
-dontwarn penguin.com.pennav.Model.Navigation.NearLandmark
|
||||
|
||||
-keep,includedescriptorclasses class net.sqlcipher.** { *; }
|
||||
-keep,includedescriptorclasses interface net.sqlcipher.** { *; }
|
||||
|
||||
-keep class retrofit2.** { *; }
|
||||
-keep class okhttp3.** { *; }
|
||||
-dontwarn retrofit2.**
|
||||
|
||||
-keep class com.google.gson.** { *; }
|
||||
-dontwarn com.google.gson.**
|
||||
|
||||
# Penguin classes
|
||||
-keep class com.peng.pennavmap.models.** { *; }
|
||||
-keep class com.peng.pennavmap.db.** { *; }
|
||||
|
||||
|
@ -0,0 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
@ -0,0 +1,66 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<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.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS" />
|
||||
|
||||
|
||||
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
|
||||
|
||||
<application
|
||||
android:usesCleartextTraffic="true"
|
||||
android:label="penguin_flutter_sample"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:hardwareAccelerated="true"
|
||||
android:largeHeap="true"
|
||||
tools:replace="android:label">
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop"
|
||||
android:taskAffinity=""
|
||||
android:label="penguin_flutter_sample"
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||
the Android process has started. This theme is visible to the user
|
||||
while the Flutter UI initializes. After that, this theme continues
|
||||
to determine the Window background behind the Flutter UI. -->
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme"
|
||||
/>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<!-- Don't delete the meta-data below.
|
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
</application>
|
||||
<!-- Required to query activities that can process text, see:
|
||||
https://developer.android.com/training/package-visibility and
|
||||
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
||||
|
||||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
||||
<data android:mimeType="text/plain"/>
|
||||
</intent>
|
||||
</queries>
|
||||
</manifest>
|
@ -0,0 +1,66 @@
|
||||
package com.eventtan.test.penguin_flutter_sample
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.util.Log
|
||||
import com.eventtan.app.penguin_flutter_sample.penguin.PenguinViewFactory
|
||||
import com.eventtan.test.penguin_flutter_sample.PermissionManager.PermissionHelper
|
||||
import com.eventtan.test.penguin_flutter_sample.PermissionManager.PermissionManager
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
|
||||
|
||||
/**
|
||||
* The main activity for the Flutter application.
|
||||
* This activity is responsible for configuring the Flutter engine and registering platform view factories.
|
||||
*/
|
||||
class MainActivity : FlutterActivity() {
|
||||
|
||||
|
||||
|
||||
private lateinit var flutterEngine: FlutterEngine
|
||||
|
||||
/**
|
||||
* Configures the Flutter engine by registering platform view factories.
|
||||
*
|
||||
* @param flutterEngine The [FlutterEngine] instance associated with this activity.
|
||||
*/
|
||||
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
||||
super.configureFlutterEngine(flutterEngine)
|
||||
|
||||
flutterEngine.platformViewsController.registry.registerViewFactory(
|
||||
"penguin_lib", // Unique identifier for the view factory
|
||||
PenguinViewFactory(
|
||||
flutterEngine.dartExecutor.binaryMessenger, // Used for communication with Dart
|
||||
this // Reference to the current MainActivity
|
||||
)
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
permissions: Array<out String>,
|
||||
grantResults: IntArray
|
||||
) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
|
||||
val granted = grantResults.all { it == PackageManager.PERMISSION_GRANTED }
|
||||
|
||||
val intent = Intent("PERMISSION_RESULT_ACTION").apply {
|
||||
putExtra("PERMISSION_GRANTED", granted)
|
||||
}
|
||||
sendBroadcast(intent)
|
||||
|
||||
// Log the request code and permission results
|
||||
Log.d("PermissionsResult", "Request Code: $requestCode")
|
||||
Log.d("PermissionsResult", "Permissions: ${permissions.joinToString()}")
|
||||
Log.d("PermissionsResult", "Grant Results: ${grantResults.joinToString()}")
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
package com.eventtan.test.penguin_flutter_sample.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.eventtan.test.penguin_flutter_sample.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.eventtan.test.penguin_flutter_sample.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,230 @@
|
||||
package com.eventtan.app.penguin_flutter_sample.penguin
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.IntentFilter
|
||||
import android.graphics.Color
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.Toast
|
||||
import com.eventtan.test.penguin_flutter_sample.MainActivity
|
||||
import com.eventtan.test.penguin_flutter_sample.PermissionManager.PermissionHelper
|
||||
import com.eventtan.test.penguin_flutter_sample.PermissionManager.PermissionManager
|
||||
import com.eventtan.test.penguin_flutter_sample.PermissionManager.PermissionResultReceiver
|
||||
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.
|
||||
*/
|
||||
internal class PenguinView(
|
||||
context: Context,
|
||||
id: Int,
|
||||
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.applicationContext
|
||||
|
||||
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 = (_activity as MainActivity).context
|
||||
|
||||
|
||||
permissionResultReceiver = PermissionResultReceiver { granted ->
|
||||
if (granted) {
|
||||
onPermissionsGranted()
|
||||
} else {
|
||||
onPermissionsDenied()
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
PlugAndPlaySDK.configuration = PlugAndPlayConfiguration.Builder()
|
||||
.setBaseUrl("https://temp.penguinin.com", "https://temp.penguinin.com")
|
||||
.setServiceName("api", "pe")
|
||||
.setClientData("Client", "clientkey")
|
||||
.setUserName("client")
|
||||
.setLanguageID(Languages.en)
|
||||
.setSimulationModeEnabled(true)
|
||||
.setEnableBackButton(true)
|
||||
.setDeepLinkData("deeplink")
|
||||
.setCustomizeColor("#2CA0AF")
|
||||
.setDeepLinkSchema("")
|
||||
.setDeepLinkData(null)
|
||||
.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 {
|
||||
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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
package com.eventtan.app.penguin_flutter_sample.penguin
|
||||
|
||||
import android.content.Context
|
||||
import com.eventtan.test.penguin_flutter_sample.MainActivity
|
||||
import io.flutter.plugin.common.BinaryMessenger
|
||||
import io.flutter.plugin.common.StandardMessageCodec
|
||||
import io.flutter.plugin.platform.PlatformView
|
||||
import io.flutter.plugin.platform.PlatformViewFactory
|
||||
|
||||
// PenguinViewFactory.kt
|
||||
|
||||
/**
|
||||
* A factory class for creating instances of [PenguinView].
|
||||
*
|
||||
* @property messenger The [BinaryMessenger] used for communication.
|
||||
* @property mainActivity The [MainActivity] instance associated with this view.
|
||||
*/
|
||||
class PenguinViewFactory(
|
||||
private val messenger: BinaryMessenger,
|
||||
private val mainActivity: MainActivity
|
||||
) : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
|
||||
|
||||
/**
|
||||
* Creates a new [PenguinView] instance.
|
||||
*
|
||||
* @param context The [Context] in which the view is running.
|
||||
* @param viewId The unique ID of the view to be created.
|
||||
* @param args Optional arguments passed for creating the view, expected to be a [Map].
|
||||
* @return A new instance of [PenguinView].
|
||||
*/
|
||||
override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
|
||||
// Cast the arguments to a Map if they are provided
|
||||
val creationParams = args as Map<String?, Any?>?
|
||||
|
||||
// Instantiate and return the PenguinView with the provided parameters
|
||||
return PenguinView(context, viewId, creationParams, messenger, mainActivity)
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="?android:colorBackground" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
</layer-list>
|
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@android:color/white" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
</layer-list>
|
Binary file not shown.
After Width: | Height: | Size: 544 B |
Binary file not shown.
After Width: | Height: | Size: 442 B |
Binary file not shown.
After Width: | Height: | Size: 721 B |
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="teal_700">#FF018786</color>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
<color name="btnLanguage">#EFEFEF</color>
|
||||
<color name="mainPengColor">#2CA0AF</color>
|
||||
<color name="red">#d32f2f</color>
|
||||
<color name="com_penguin_nav_demo_transparent">#00000000</color>
|
||||
<color name="com_penguin_nav_demo_amber">#FFC107</color>
|
||||
<color name="com_penguin_nav_demo_pen_blue">#3392E2</color>
|
||||
<color name="com_penguin_nav_demo_green">#53973B</color>
|
||||
<color name="com_penguin_nav_demo_pen_line_dark_red">#DC0000</color>
|
||||
<color name="com_penguin_nav_demo_pen_gray_line">#E5E4E4</color>
|
||||
</resources>
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="com_penguin_nav_demo_10dp">10.00dp</dimen>
|
||||
<dimen name="com_penguin_nav_demo_15dp">15.00dp</dimen>
|
||||
<dimen name="com_penguin_nav_demo_16dp">16.00dp</dimen>
|
||||
<dimen name="com_penguin_nav_demo_25dp">25.00dp</dimen>
|
||||
<dimen name="com_penguin_nav_demo_40dp">40.00dp</dimen>
|
||||
<dimen name="com_penguin_nav_demo_60dp">60.00dp</dimen>
|
||||
</resources>
|
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Penguin_flutter_Sample</string>
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
<!--setupConfiguration-->
|
||||
<string name="data_url" translatable="false">https://temp.nav.penguinin.com</string>
|
||||
<string name="data_service_name" translatable="false">api</string>
|
||||
<string name="position_url" translatable="false">https://temp.nav.penguinin.com</string>
|
||||
<string name="position_service_name" translatable="false">pe</string>
|
||||
<string name="client_id" translatable="false">PIF</string>
|
||||
<string name="client_key" translatable="false">UGVuZ3VpbklOX1Blbk5hdl9QSUY=</string>
|
||||
<string name="deep_link_schema" translatable="false"></string>
|
||||
<string name="deep_link_domain" translatable="false"></string>
|
||||
<string name="mapbox_access_token" translatable="false">mapbox_token</string>
|
||||
////////////////////////////////////////////
|
||||
</resources>
|
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
|
||||
|
||||
<style name="LaunchTheme.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="LaunchTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
|
||||
<style name="LaunchTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||
</resources>
|
@ -0,0 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
@ -0,0 +1,57 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
maven { url 'https://plugins.gradle.org/m2' }
|
||||
// maven { url 'https://jitpack.io' }
|
||||
maven {
|
||||
url 'https://api.mapbox.com/downloads/v2/releases/maven'
|
||||
authentication {
|
||||
basic(BasicAuthentication)
|
||||
}
|
||||
credentials {
|
||||
username = 'mapbox'
|
||||
password = "sk.eyJ1IjoidmlyYWwtbW9ibWF4aW1lIiwiYSI6ImNseWZ0MzByYTAzZ2MyeHMxMXp3NWRscWYifQ.Dq-SRE-hyED1ojrJcq3JKA"
|
||||
if (password == null || password == "") {
|
||||
throw new GradleException("MAPBOX_DOWNLOADS_TOKEN isn't set. Set it to the project properties or to the enviroment variables.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath "com.mapbox.gradle.plugins:access-token:0.4.0"
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
maven { url 'https://plugins.gradle.org/m2' }
|
||||
maven {
|
||||
url 'https://api.mapbox.com/downloads/v2/releases/maven'
|
||||
authentication {
|
||||
basic(BasicAuthentication)
|
||||
}
|
||||
credentials {
|
||||
username = 'mapbox'
|
||||
password = "sk.eyJ1IjoidmlyYWwtbW9ibWF4aW1lIiwiYSI6ImNseWZ0MzByYTAzZ2MyeHMxMXp3NWRscWYifQ.Dq-SRE-hyED1ojrJcq3JKA"
|
||||
if (password == null || password == "") {
|
||||
throw new GradleException("MAPBOX_DOWNLOADS_TOKEN isn't set. Set it to the project properties or to the enviroment variables.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.layout.buildDirectory = file('../build')
|
||||
subprojects {
|
||||
project.layout.buildDirectory = file("${rootProject.layout.buildDirectory.get().asFile}/${project.name}")
|
||||
}
|
||||
subprojects {
|
||||
project.evaluationDependsOn(':app')
|
||||
}
|
||||
|
||||
tasks.register("clean", Delete) {
|
||||
delete rootProject.layout.buildDirectory
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
android.nonTransitiveRClass=false
|
||||
android.nonFinalResIds=false
|
||||
MAPBOX_USER_NAME = "mapbox"
|
||||
MAPBOX_DOWNLOADS_TOKEN="sk.eyJ1IjoidmlyYWwtbW9ibWF4aW1lIiwiYSI6ImNseWZ0MzByYTAzZ2MyeHMxMXp3NWRscWYifQ.Dq-SRE-hyED1ojrJcq3JKA"
|
||||
|
@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip
|
@ -0,0 +1,44 @@
|
||||
pluginManagement {
|
||||
def flutterSdkPath = {
|
||||
def properties = new Properties()
|
||||
file("local.properties").withInputStream { properties.load(it) }
|
||||
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
||||
return flutterSdkPath
|
||||
}()
|
||||
|
||||
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
maven { url 'https://plugins.gradle.org/m2' }
|
||||
maven { url 'https://jitpack.io' }
|
||||
maven {
|
||||
url 'https://api.mapbox.com/downloads/v2/releases/maven'
|
||||
credentials {
|
||||
username = 'mapbox'
|
||||
password = 'sk.eyJ1IjoidmlyYWwtbW9ibWF4aW1lIiwiYSI6ImNseWZ0MzByYTAzZ2MyeHMxMXp3NWRscWYifQ.Dq-SRE-hyED1ojrJcq3JKA'
|
||||
if (password == null || password == "") {
|
||||
throw new GradleException("MAPBOX_DOWNLOADS_TOKEN isn't set. Set it to the project properties or to the enviroment variables.")
|
||||
}
|
||||
}
|
||||
authentication {
|
||||
basic(BasicAuthentication)
|
||||
}
|
||||
}
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||
id "com.android.application" version "8.1.4" apply false
|
||||
id "org.jetbrains.kotlin.android" version "1.8.22" apply false
|
||||
}
|
||||
|
||||
include ":app"
|
||||
//include ':pennavui'
|
||||
//include ':penguin_sdk'
|
||||
//include ':renderer'
|
@ -0,0 +1,3 @@
|
||||
description: This file stores settings for Dart & Flutter DevTools.
|
||||
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
|
||||
extensions:
|
@ -0,0 +1,419 @@
|
||||
|
||||
[< Home](../readme.md)
|
||||
|
||||
|
||||
# Integration Guide for `PenNav P&P` Native Android Libraries in Flutter
|
||||
|
||||
#### Requirements
|
||||
|
||||
- The device must be running Android 7.0 or later.
|
||||
- The minimum supported Android version is 24.
|
||||
|
||||
## Prerequisites
|
||||
- Flutter SDK installed.
|
||||
- Basic knowledge of Flutter and Android development.
|
||||
- PenNav native Android libraries (`Penguin.aar`, `PenguinRenderer.aar`, `PenNavUI.aar`) ready.
|
||||
- Mapbox Account: Register for a Mapbox account to obtain an access token for Mapbox services.
|
||||
|
||||
## Steps
|
||||
|
||||
|
||||
|
||||
### Step 1: Install Mapbox Maps SDK v10.16.6 for Android
|
||||
|
||||
To integrate the Mapbox Maps SDK for Android and obtain authorization, follow these steps:
|
||||
|
||||
1. **Register and Obtain Authorization**
|
||||
- **Create a Mapbox Account**:
|
||||
- Visit the [Mapbox Sign Up page](https://www.mapbox.com/signup/) and register for a free account.
|
||||
- **Get Your Access Token**:
|
||||
- Log in to your Mapbox account and access your dashboard.
|
||||
- Navigate to the "Access Tokens" section.
|
||||
- Copy your default access token or create a new token with the required permissions.
|
||||
|
||||
2. **Configure Your Access Token**
|
||||
- For detailed instructions on setting up your access token in your Android project, refer to the [Mapbox Android Maps Installation guide](https://docs.mapbox.com/android/maps/guides/install/).
|
||||
|
||||
3. **Configure your public token**
|
||||
|
||||
One way to provide your public token to Mapbox SDK is by adding it as an Android string resource.
|
||||
|
||||
To add the `<string>` entry to your `strings.xml` :
|
||||
```xml
|
||||
<string name="mapbox_access_token" translatable="false" tools:ignore="UnusedResources">[Your-token-key]</string>
|
||||
```
|
||||
|
||||
|
||||
4. **Add Mapbox Repository**
|
||||
|
||||
**1- Open your `settings.gradle.kts` file (top-level file) and add the Mapbox Maven repository to the `dependencyResolutionManagement.repositories` block:**
|
||||
|
||||
```kotlin
|
||||
dependencyResolutionManagement {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
// Add the Mapbox Maven repository
|
||||
maven {
|
||||
url = uri("https://api.mapbox.com/downloads/v2/releases/maven")
|
||||
credentials {
|
||||
username = "mapbox" // The username field should always be "mapbox"
|
||||
password = project.findProperty("mapbox_access_token") as String?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
**2- Configure Credentials**
|
||||
|
||||
Ensure you have a valid Mapbox username and password. You should configure the credentials in your `gradle.properties` file, which is typically located in the root of your project or the `~/.gradle/` directory. Add the following properties to your `gradle.properties` file:
|
||||
|
||||
```properties
|
||||
mapbox_access_token= [Enter-your-token]
|
||||
```
|
||||
|
||||
**3- Add Mapbox SDK Dependency**
|
||||
|
||||
Open your `build.gradle.kts` file (module-level) and add the Mapbox Maps SDK dependency. You will need to include this in the `dependencies` block:
|
||||
|
||||
```kotlin
|
||||
dependencies {
|
||||
implementation("com.mapbox.maps:android:10.16.6")
|
||||
}
|
||||
```
|
||||
|
||||
**4- Sync Gradle:**
|
||||
Click on "Sync Now" in Android Studio or run `./gradlew sync` from the command line to update your project with these dependencies.
|
||||
|
||||
---
|
||||
|
||||
### Step 2: Add Native Libraries to Your Flutter Project
|
||||
|
||||
1. **Copy Libraries:**
|
||||
- Create a `libs` directory if it does not already exist: `android/app/libs`.
|
||||
- Copy your `.aar` files (`Penguin.aar`, `PenguinRenderer.aar`, `PenNavUI.aar`) into this `libs` directory.
|
||||
|
||||
2. **Update Gradle Files:**
|
||||
|
||||
- **In `android/build.gradle`:**
|
||||
Add the following to the `allprojects` section to include the `libs` directory as a repository:
|
||||
```gradle
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
flatDir {
|
||||
dirs 'libs'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **In `android/app/build.gradle`:**
|
||||
|
||||
Add the dependencies for your `.aar` files:
|
||||
```gradle
|
||||
|
||||
dependencies {
|
||||
|
||||
// Embeding the aar files (Penguin libraires)
|
||||
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
|
||||
|
||||
|
||||
// Pre-request Libraries - Important!
|
||||
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.3'
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
||||
implementation 'com.squareup.retrofit2:adapter-java8:2.4.0'
|
||||
implementation 'com.google.code.gson:gson:2.8.9'
|
||||
implementation 'com.google.android.gms:play-services-location:21.3.0'
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
|
||||
implementation 'androidx.test.ext:junit:1.1.5'
|
||||
implementation 'com.android.volley:volley:1.2.1'
|
||||
def room_version = "2.4.0-alpha04"
|
||||
implementation "androidx.room:room-runtime:$room_version"
|
||||
annotationProcessor "androidx.room:room-compiler:$room_version"
|
||||
implementation 'net.zetetic:android-database-sqlcipher:4.5.2'
|
||||
implementation 'com.intuit.ssp:ssp-android:1.1.0'
|
||||
implementation 'com.intuit.sdp:sdp-android:1.1.0'
|
||||
implementation 'com.github.bumptech.glide:glide:4.12.0'
|
||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
|
||||
|
||||
implementation 'com.mapbox.maps:android:10.16.6' // Added before
|
||||
|
||||
// Add other dependencies if needed
|
||||
}
|
||||
```
|
||||
|
||||
- **Enabling View Binding**
|
||||
To enable View Binding in your Android project, follow these steps:
|
||||
|
||||
Open your project's build.gradle file.
|
||||
|
||||
Inside the android block, add the following buildFeatures configuration:
|
||||
```java
|
||||
android {
|
||||
// Other configurations...
|
||||
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **ProGuard Configuration**
|
||||
- it's crucial to configure ProGuard to ensure that the library's classes and interfaces are not obfuscated or removed during the optimization process. Follow these steps to add the necessary ProGuard rules:
|
||||
|
||||
- Open your ProGuard configuration file (proguard-rules.pro) in your Android project.
|
||||
|
||||
- Add the following lines to the file:
|
||||
```java
|
||||
|
||||
-dontwarn penguin.com.pennav.Model.Navigation.NearLandmark
|
||||
|
||||
-keep,includedescriptorclasses class net.sqlcipher.** { *; }
|
||||
-keep,includedescriptorclasses interface net.sqlcipher.** { *; }
|
||||
|
||||
-keep class retrofit2.** { *; }
|
||||
-keep class okhttp3.** { *; }
|
||||
-dontwarn retrofit2.**
|
||||
|
||||
-keep class com.google.gson.** { *; }
|
||||
-dontwarn com.google.gson.**
|
||||
|
||||
# Penguin classes
|
||||
-keep class com.peng.pennavmap.models.** { *; }
|
||||
-keep class com.peng.pennavmap.db.** { *; }
|
||||
```
|
||||
|
||||
- **Sync Gradle:**
|
||||
Click on "Sync Now" in Android Studio or run `./gradlew sync` from the command line to update your project with these dependencies.
|
||||
|
||||
|
||||
## 4. add permissions
|
||||
|
||||
To ensure the smooth operation of the Plug & Play (P&P) module, a list of permissions must be
|
||||
granted. These permissions allow the P&P module to access certain resources and functions on the
|
||||
device, and are necessary for the P&P module to function properly.
|
||||
|
||||
Following is the permissions that must be added to <u>**AndroidManifest.xml**</u>
|
||||
|
||||
```xml
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<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.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS" />
|
||||
```
|
||||
|
||||
The request permission the purpose of requesting each one of the outlined in the table below
|
||||
| Permission | Why | What if dismissed |
|
||||
| ----------- | ----------- | ----------- |
|
||||
| INTERNET| To access the internet and connect to remote servers| is required in order to access remote servers and provide a seamless and reliable experience for our users. By granting this permission, you'll be able to fully utilize the features and functionality of our app |
|
||||
|ACCESS_NETWORK_STATE| To check the status of the device's network connection| is necessary for checking the status of the device's network connection. This helps ensure that our app is able to function properly, even when the network connection is unstable or unavailable. By granting this permission, you'll be able to use our app with confidence, knowing that it will work even under challenging network conditions|
|
||||
|<p>ACCESS_FINE_LOCATION</p><p>ACCESS_COARSE_LOCATION</p>|<p>To access the device's precise location (GPS and network-based) and it used for calculate turn-by-turn directions and show location on map </p><p>To access the device's approximate location (network-based)</p> | permissions are essential for providing location-based services and features. By granting these permissions, you'll be able to take full advantage of our app's ability to provide turn-by-turn directions, show your location on a map, and more. We take the privacy of your location data very seriously, and will always handle it with the utmost care and respect|
|
||||
|<p>BLUETOOTH</p><p>BLUETOOTH_ADMIN</p><p>BLUETOOTH_CONNECT</p><p>BLUETOOTH_SCAN</p>|<p>To access the device's Bluetooth functionality and improve wayfinding inside buildings</p><p>To configure the device's Bluetooth settings</p> <p>To connect to Bluetooth devices</p> <p>To scan for nearby Bluetooth devices</p>| permissions are needed to access and utilize the device's Bluetooth functionality. This allows our app to connect to Bluetooth devices, configure Bluetooth settings, and scan for nearby devices. you'll be able to more easily find your way around and make the most of our app's indoor navigation capabilities |
|
||||
|HIGH_SAMPLING_RATE_SENSORS|To access high-sampling rate sensors, such as the device's accelerometer and gyroscope, at a higher frequency rate| is needed to access high-sampling rate sensors, such as the device's accelerometer and gyroscope, at a higher frequency rate. This is necessary for certain features and functionality of our app, such as tracking motion and providing precise measurements. By granting this permission, you'll be able to fully utilize the capabilities of our app|
|
||||
|
||||
Overall, by granting these permissions, you'll be able to fully take advantage of the features and functionality of our app. We appreciate your trust in our app and will always handle your data with the at most care and respect.
|
||||
|
||||
|
||||
|
||||
---
|
||||
#### Native Android configuration steps
|
||||
|
||||
- **For detailed instructions on how to configure and initialize the PenNav libraries, please start by checking out the [Configuration Steps](p&p-android.md#configuration-steps). It is important to begin here to ensure a proper setup.**
|
||||
|
||||
|
||||
---
|
||||
|
||||
### Step 3: Create the Flutter Platform View Factory View
|
||||
|
||||
#### 2.1 Implement the View Factory
|
||||
|
||||
- **Create a new Kotlin or Java file** in `android/app/src/main/kotlin/com/yourcompany/yourapp/`.
|
||||
|
||||
- **Kotlin (PenguinViewFactory.kt):**
|
||||
|
||||
```kotlin
|
||||
class PenguinViewFactory(
|
||||
private val messenger: BinaryMessenger,
|
||||
private val mainActivity: MainActivity
|
||||
) : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
|
||||
override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
|
||||
val creationParams = args as Map<String?, Any?>?
|
||||
|
||||
return PenguinView(context, viewId, creationParams, messenger,mainActivity)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **Java (PenguinViewFactory.java):**
|
||||
|
||||
```java
|
||||
public class PenguinViewFactory extends PlatformViewFactory {
|
||||
|
||||
private final BinaryMessenger messenger;
|
||||
private final MainActivity mainActivity;
|
||||
|
||||
public PenguinViewFactory(BinaryMessenger messenger, MainActivity mainActivity) {
|
||||
super(StandardMessageCodec.INSTANCE);
|
||||
this.messenger = messenger;
|
||||
this.mainActivity = mainActivity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformView create(Context context, int viewId, Object args) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> creationParams = (Map<String, Object>) args;
|
||||
return new PenguinView(context, viewId, creationParams, messenger, mainActivity);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### 2.2 Implement the Custom View
|
||||
|
||||
- **Create a new Kotlin or Java file** in `android/app/src/main/kotlin/com/yourcompany/yourapp/`.
|
||||
|
||||
- **Kotlin (PenguinView.kt):**
|
||||
```kotlin
|
||||
|
||||
internal class PenguinView(
|
||||
context: Context,
|
||||
id: Int,
|
||||
creationParams: Map<String?, Any?>?,
|
||||
messenger: BinaryMessenger,
|
||||
activity: MainActivity
|
||||
) : PlatformView, MethodChannel.MethodCallHandler, PenNavUIDelegate {
|
||||
|
||||
// Review the sample app for full implemntation ...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
- **Java (PenguinView.java):**
|
||||
```java
|
||||
public class PenguinView implements PlatformView, MethodChannel.MethodCallHandler, PenNavUIDelegate {
|
||||
|
||||
public PenguinView(Context context
|
||||
, int id
|
||||
, Map<String?, Object?> creationParams
|
||||
, BinaryMessenger messenger
|
||||
, MainActivity activity) {
|
||||
//....
|
||||
}
|
||||
// Review the sample app for full implemntation ...
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### 2.3 Register the Platform View in `MainActivity`
|
||||
|
||||
- **Update `MainActivity`** to register the platform view factory.
|
||||
|
||||
- **Kotlin:**
|
||||
```kotlin
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
|
||||
class MainActivity : FlutterActivity() {
|
||||
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
||||
super.configureFlutterEngine(flutterEngine)
|
||||
|
||||
flutterEngine.platformViewsController.registry.registerViewFactory(
|
||||
"penguin_lib",
|
||||
PenguinViewFactory(flutterEngine.dartExecutor.binaryMessenger, this)
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **Java:**
|
||||
```java
|
||||
import io.flutter.embedding.android.FlutterActivity;
|
||||
import io.flutter.embedding.engine.FlutterEngine;
|
||||
|
||||
public class MainActivity extends FlutterActivity {
|
||||
@Override
|
||||
public void configureFlutterEngine(FlutterEngine flutterEngine) {
|
||||
super.configureFlutterEngine(flutterEngine);
|
||||
|
||||
flutterEngine.getPlatformViewsController().getRegistry().registerViewFactory(
|
||||
"penguin_lib",
|
||||
new PenguinViewFactory(flutterEngine.getDartExecutor().getBinaryMessenger(), this)
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
---
|
||||
|
||||
### Step 4: Use the Platform View in Flutter
|
||||
|
||||
- **Modify your Dart code** to use the custom platform view.
|
||||
|
||||
```dart
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
void main() {
|
||||
runApp(MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
const viewType = 'penguin_lib';
|
||||
|
||||
final creationParams = <String, dynamic>{};
|
||||
|
||||
return Container(
|
||||
child: Platform.isIOS
|
||||
? UiKitView( // Display the Penguin Map for iOS
|
||||
viewType: viewType,
|
||||
layoutDirection: TextDirection.ltr,
|
||||
creationParams: creationParams,
|
||||
onPlatformViewCreated: onPlatformViewCreated,
|
||||
creationParamsCodec: const StandardMessageCodec(),
|
||||
)
|
||||
: AndroidView( // Display the Penguin Map for Android
|
||||
viewType: viewType,
|
||||
layoutDirection: TextDirection.ltr,
|
||||
creationParams: creationParams,
|
||||
onPlatformViewCreated: onPlatformViewCreated,
|
||||
creationParamsCodec: const StandardMessageCodec(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> onPlatformViewCreated(int id) async {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5. Test Your Integration
|
||||
|
||||
1. **Build and Run Your App:**
|
||||
- Compile and run your Flutter app on an Android device or emulator.
|
||||
|
||||
2. **Verify the Custom View:**
|
||||
- Ensure the custom native view is displayed correctly and interacts as expected.
|
||||
|
||||
---
|
||||
|
||||
[< Home](../readme.md)
|
@ -0,0 +1,210 @@
|
||||
[< Back](android.md)
|
||||
|
||||
## Integrating and Configuring PenNavUI
|
||||
|
||||
## 5. Run the Plug & Play (P&P) Module
|
||||
|
||||
To implement the PenNavUIDelegate interface in your Java project and begin calling the P&P
|
||||
functions, follow this steps:
|
||||
|
||||
1. From your project implement the PenNavUIDelegate to start calling the P&P functions
|
||||
|
||||
```java
|
||||
public class MyClass implements PenNavUIDelegate {}
|
||||
```
|
||||
|
||||
2. In the class where you implement the PenNavUIDelegate interface, you need to call three
|
||||
functions :
|
||||
|
||||
a. **onPenNavSuccess** : The triggering of this callback signifies the successful initialization of
|
||||
the P&P module.
|
||||
```java
|
||||
@Override
|
||||
public void onPenNavSuccess(String warning) {}
|
||||
```
|
||||
b. **onPenNavInitializationError** : callback is triggered upon the failure of the P&P module
|
||||
initialization process.
|
||||
```java
|
||||
@Override
|
||||
public void onPenNavInitializationError(String description, InitializationErrorType errorType) {}
|
||||
```
|
||||
c. **onPenNavUIDismiss** : callback is triggered upon the successful closure of the P&P module, which
|
||||
is initiated by the clicking of the back button.
|
||||
```java
|
||||
@Override
|
||||
public void onPenNavUIDismiss() {}
|
||||
```
|
||||
3. Setup the P&P configuration using **PlugAndPlayConfiguration.Builder**
|
||||
```java
|
||||
private PlugAndPlayConfiguration.Builder builder=new PlugAndPlayConfiguration.Builder();
|
||||
```
|
||||
|
||||
4. From the class that used to start the P&P module,setup the P&P configurations
|
||||
|
||||
There are two types of configurations (mandatory and optional).
|
||||
|
||||
a. Mandatory configuration : if these configurations are not setup , the P&P module
|
||||
initialization will fail
|
||||
|
||||
```java
|
||||
PlugAndPlaySDK.configuration = builder
|
||||
.setBaseUrl(dataServerUrl, positionServerUrl)
|
||||
.setServiceName(dataServiceName,positionServiceName)
|
||||
.setClientData(clientID, clientKey)
|
||||
.setUserName(name)
|
||||
```
|
||||
|
||||
| Config | Link |
|
||||
|----------------|----------------------------------------------------|
|
||||
| setBaseUrl | [description](./readmeresources/setBaseUrl.md) |
|
||||
| setServiceName | [description](./readmeresources/setServiceName.md) |
|
||||
| setClientData | [description](./readmeresources/setClientData.md) |
|
||||
| setUserName | [description](./readmeresources/setUserName.md) |
|
||||
|
||||
b. And other optional configurations, you have the option to add them or ignore them and it will not affect the app performance
|
||||
|
||||
|
||||
```java
|
||||
builder.setSimulationModeEnabled(isSimulation)
|
||||
.setLanguageID(languageCode)
|
||||
.setCustomizeColor(hexCode)
|
||||
.setDeepLinkSchema(deepLinkSchema)
|
||||
.setDeepLinkData(deepLinkReceivedData)
|
||||
```
|
||||
| Config | Link |
|
||||
|--------------------------|-------------------------------------------------------|
|
||||
| setSimulationModeEnabled | [description](./readmeresources/setSimulationMode.md) |
|
||||
| setLanguageID | [description](./readmeresources/setLanguage.md) |
|
||||
| setCustomizeColor | [description](./readmeresources/setCustomizeColor.md) |
|
||||
| setDeepLinkData | [description](./readmeresources/setDeepLinkData.md) |
|
||||
| setDeepLinkSchema | [description](./readmeresources/setDeepLinkSchema.md) |
|
||||
|
||||
**After Setting configuration**
|
||||
|
||||
You need to build the configuration
|
||||
|
||||
```java
|
||||
builder.build()
|
||||
```
|
||||
|
||||
**Start initializing our SDK**
|
||||
|
||||
Call the initialize(Context, PenNavUIDelegate) method providing an object that implements PenNavUIDelegate.
|
||||
```java
|
||||
PlugAndPlaySDK.start(Context,PenNavUIDelegate);
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 6. Possibly another implementation is needed
|
||||
|
||||
### 1. Implementing the Off Location Campus Delegate
|
||||
|
||||
In this callBack if the user is offCampus you can get the location as (Latitude and Longitude)
|
||||
|
||||
Take the following steps to get notified if the user location is off-campus:
|
||||
|
||||
1. From your project Implement the `PILocationDelegate` interface and
|
||||
its `onLocationOffCampus(ArrayList<Double> location)` method that gets called back when the user
|
||||
location is off-campus with an array of floating-point numbers as a parameter that represents
|
||||
off-campus latitude and longitude.
|
||||
```java
|
||||
public class MyClass extends AppCompatActivity implements PILocationDelegate
|
||||
```
|
||||
|
||||
2. In the class where you implement the PILocationDelegate interface, you can call one method
|
||||
```java
|
||||
public class MyClass extends AppCompatActivity implements PILocationDelegate {
|
||||
@Override
|
||||
public void onLocationOffCampus(ArrayList<Double> location) {}
|
||||
}
|
||||
```
|
||||
You will receive an arrayList of double points of Latitude and longitude
|
||||
|
||||
Example of how you can use the data :
|
||||
```java
|
||||
if (location.size() > 0)
|
||||
Toast.makeText(mContext , "Location Info Latitude : " + location.get(0) + " longitude : " + location.get(1) , Toast.LENGTH_SHORT).show();
|
||||
```
|
||||
And the data will shown as :
|
||||
|
||||
Location Info Latitude : 31.656546 longitude : 35.46146
|
||||
|
||||
3. During the map initializing step, set the `PILocationDelegate` in the `setPiLocationDelegate`
|
||||
method to an object that implements the `PILocationDelegate` interface and
|
||||
its `ArrayList<Double> location)` method.
|
||||
|
||||
```java
|
||||
PlugAndPlaySDK.setPiLocationDelegate(PILocationDelegate);
|
||||
```
|
||||
|
||||
### 2. Navigating to Places on the Map
|
||||
|
||||
**Using Reference IDs**
|
||||
|
||||
You can use this method From PlugAndPlaySDK class and use it if you want to show the Poi on the map
|
||||
and navigate to it
|
||||
|
||||
Call the `navigateTo(Context mContext, String referenceID, Completion completion)` method to
|
||||
navigate to a place given its reference ID.
|
||||
|
||||
```java
|
||||
PlugAndPlaySDK.navigateTo(Context,String,Completion)
|
||||
```
|
||||
|
||||
**Using shared Links**
|
||||
|
||||
1. Provide a shared link for plug-and-play to share user or Poi location on the map using
|
||||
the `setDeepLinkSchema(String)` method
|
||||
```java
|
||||
PlugAndPlayConfiguration.Builder().setDeepLinkSchema(String)
|
||||
```
|
||||
2. Provide data from a deep link to display places on the map using the `setDeepLinkData(String)`
|
||||
method
|
||||
```java
|
||||
PlugAndPlayConfiguration.Builder().setDeepLinkData(String)
|
||||
```
|
||||
|
||||
### 3. Reporting an Issue
|
||||
|
||||
|
||||
|
||||
The PlugAndPlaySDK provides a flexible way to capture and report issues within your application. By using a delegate, you can seamlessly integrate third-party tools
|
||||
or your end point to streamline the process of issue reporting and debugging.
|
||||
|
||||
#### Setting Up the Delegate
|
||||
|
||||
To enable issue reporting with PlugAndPlaySDK, you need to set up a delegate by calling the `setPiEventsDelegate` method. The delegate is responsible for handling issue reports. Here's the basic setup:
|
||||
|
||||
```java
|
||||
PlugAndPlaySDK.setPiEventsDelegate(new PIEventsDelegate() {
|
||||
@Override
|
||||
public void onReportIssue(PIReportIssue issue) {
|
||||
// Implement issue reporting logic here
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
In this code snippet, we define an anonymous inner class that implements the `PIEventsDelegate` interface. The `onReportIssue` method is where you will place the logic for reporting issues to your chosen tool.
|
||||
|
||||
#### Controlling Report Issue Buttons in PlugAndPlaySDK
|
||||
|
||||
You can easily enable or disable report issue buttons in PlugAndPlaySDK based on your application's needs.
|
||||
|
||||
#### Usage
|
||||
|
||||
- **Enable Report Issue Buttons**:
|
||||
```java
|
||||
PlugAndPlaySDK.setReportingIssuesEnabled(true);
|
||||
```
|
||||
Use this when you want users to report issues.
|
||||
|
||||
- **Disable Report Issue Buttons**:
|
||||
```java
|
||||
PlugAndPlaySDK.setReportingIssuesEnabled(false);
|
||||
```
|
||||
Use this to prevent users from reporting issues.
|
||||
|
||||
|
||||
|
||||
[< Back](android.md)
|
@ -0,0 +1,229 @@
|
||||
|
||||
[< Back](ios.md)
|
||||
|
||||
## Integrating and Configuring PenNavUI
|
||||
|
||||
### Importing PenNavUI
|
||||
|
||||
Start by importing the PenNavUI framework into your project:
|
||||
|
||||
```swift
|
||||
import PenNavUI
|
||||
```
|
||||
|
||||
### Conforming to `PenNavInitializationDelegate`
|
||||
|
||||
Implement the `PenNavInitializationDelegate` protocol in your view controller to handle initialization events:
|
||||
|
||||
```swift
|
||||
extension ViewController: PenNavInitializationDelegate {
|
||||
func onPenNavSuccess() {
|
||||
// Handle successful initialization
|
||||
}
|
||||
|
||||
func onPenNavInitializationError(errorType: PenNavUIError, errorDescription: String) {
|
||||
// Handle initialization error
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Configuring `PenNavUIManager`
|
||||
|
||||
Set up `PenNavUIManager` with the configuration values provided by our Customer Success Team:
|
||||
|
||||
|
||||
```swift
|
||||
PenNavUIManager.shared
|
||||
.setClientKey("Your Client Key")
|
||||
.setClientID("Your Client ID")
|
||||
.setBaseURL(dataURL: "Your Data URL", positionURL: "Your Position URL")
|
||||
.setServiceName(dataServiceName: "Your Data Service Name", positionServiceName: "Your Position Service Name")
|
||||
.build()
|
||||
```
|
||||
|
||||
- Example with more configuration :
|
||||
```swift
|
||||
PenNavUIManager.shared
|
||||
.setClientKey("UGVuZ3VpbklOX1Blb")
|
||||
.setClientID("ClientA")
|
||||
.setUsername("UserA")
|
||||
.setSimulationModeEnabled(isEnable: true)
|
||||
.setBaseURL(dataURL: "https://temp.client.penguinin.com", positionURL: "https://temp.client.penguinin.com")
|
||||
.setServiceName(dataServiceName: "api", positionServiceName: "pe")
|
||||
.setIsShowUserName(false)
|
||||
.setEnableReportIssue(enable: false)
|
||||
.setLanguage("en")
|
||||
.build()
|
||||
```
|
||||
|
||||
### Presenting the Map
|
||||
|
||||
After successful initialization, present the map by calling:
|
||||
|
||||
```swift
|
||||
PenNavUIManager.shared.present(root: self, view: view)
|
||||
```
|
||||
|
||||
Ensure the `onPenNavSuccess` method includes this call:
|
||||
|
||||
```swift
|
||||
extension ViewController: PenNavInitializationDelegate {
|
||||
func onPenNavSuccess() {
|
||||
PenNavUIManager.shared.present(root: self, view: view)
|
||||
}
|
||||
|
||||
func onPenNavInitializationError(errorType: PenNavUIError, errorDescription: String) {
|
||||
// Handle initialization error
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Configuring the Location Delegate
|
||||
|
||||
To get notified when the user is off campus, conform to the `PILocationDelegate` protocol:
|
||||
|
||||
```swift
|
||||
extension ViewController: PILocationDelegate {
|
||||
func onLocationOffCampus(location: CLLocationCoordinate2D) {
|
||||
// Handle user location being off campus
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Set the `locationDelegate` of `PenNavUIManager`:
|
||||
|
||||
```swift
|
||||
PenNavUIManager.shared.locationDelegate = self
|
||||
```
|
||||
|
||||
### Configuring the Events Delegate
|
||||
|
||||
To handle map dismissal events, conform to the `PIEventsDelegate` protocol:
|
||||
|
||||
```swift
|
||||
extension ViewController: PIEventsDelegate {
|
||||
func onPenNavUIDismiss() {
|
||||
// Handle map dismissal
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Set the `eventsDelegate` of `PenNavUIManager`:
|
||||
|
||||
```swift
|
||||
PenNavUIManager.shared.eventsDelegate = self
|
||||
```
|
||||
|
||||
### Reporting Issues
|
||||
|
||||
Enable issue reporting and handle it using the `PIEventsDelegate` protocol:
|
||||
|
||||
```swift
|
||||
PenNavUIManager.shared.setEnableReportIssue(enable: true)
|
||||
|
||||
extension ViewController: PIEventsDelegate {
|
||||
func onReportIssue(_ issue: PenNavUI.IssueType) {
|
||||
// Handle issue reporting
|
||||
Instabug.show()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Set the `eventsDelegate` of `PenNavUIManager`:
|
||||
|
||||
```swift
|
||||
PenNavUIManager.shared.eventsDelegate = self
|
||||
```
|
||||
|
||||
### Navigating to Places
|
||||
|
||||
- **Using Reference IDs:**
|
||||
|
||||
Navigate to a place using its reference ID:
|
||||
|
||||
```swift
|
||||
PenNavUIManager.shared.navigate(to: "referenceID", completion: { success, error in
|
||||
// Handle navigation result
|
||||
})
|
||||
```
|
||||
|
||||
- **Using Deep Links:**
|
||||
|
||||
Configure deep linking to share places:
|
||||
|
||||
```swift
|
||||
PenNavUIManager.shared.setDeepLinkScheme("app://", deepLinkDomain: "www.penguinin.com")
|
||||
PenNavUIManager.shared.setDeepLinkData(data: "YourDeepLinkData")
|
||||
```
|
||||
|
||||
### Simulating User Location
|
||||
|
||||
Enable simulation mode for testing purposes:
|
||||
|
||||
```swift
|
||||
PenNavUIManager.shared
|
||||
.setClientKey("Your Client Key")
|
||||
.setClientID("Your Client ID")
|
||||
.setBaseURL(dataURL: "Your Data URL", positionURL: "Your Position URL")
|
||||
.setServiceName(dataServiceName: "Your Data Service Name", positionServiceName: "Your Position Service Name")
|
||||
.setSimulationModeEnabled(isEnable: true)
|
||||
.setUsername("Your Username")
|
||||
.build()
|
||||
```
|
||||
|
||||
### Dismissing the PenNav SDK
|
||||
|
||||
When the PenNav SDK is no longer needed, dismiss it to free up resources:
|
||||
|
||||
```swift
|
||||
PenNavUIManager.shared.dismiss()
|
||||
```
|
||||
|
||||
### Deprecated Methods
|
||||
|
||||
Avoid using the following deprecated methods:
|
||||
|
||||
- `setOutdoorEnable(isEnable:)`
|
||||
- `setStepDetectionEnable(isEnable:)`
|
||||
- `setTransitionEnable(isEnable:)`
|
||||
|
||||
### Handling Map Initialization Errors
|
||||
|
||||
Here are common errors and their descriptions:
|
||||
|
||||
| **Error** | **Description** |
|
||||
|----------------------------------|------------------------------------------------------------------------|
|
||||
| Missing Base URL | Specify a valid base URL. |
|
||||
| Missing Data Service Name | Provide the required data service name. |
|
||||
| Missing Position Service Name | Provide the required position service name. |
|
||||
| Missing Client ID | Ensure a valid client ID is provided. |
|
||||
| Invalid Client Key | Verify and provide a valid client key. |
|
||||
| Missing Root Controller | Ensure a valid root controller is provided. |
|
||||
| Missing View Container | Provide a valid view container. |
|
||||
| Unauthorized | Check your authorization for the requested action. |
|
||||
| Loading Data Error | Retry loading data. |
|
||||
| OS Not Supported | Ensure the operating system is supported. |
|
||||
| No Internet Connection | Verify your internet connection. |
|
||||
| Sensors Initialization Error | Check sensor settings and retry. |
|
||||
| Permissions Not Granted | Grant all necessary permissions. |
|
||||
| Location Permission Not Granted | Grant location permission. |
|
||||
| Bluetooth Permission Not Granted | Grant Bluetooth permission. |
|
||||
| Location Services Turned Off | Enable location services. |
|
||||
| Bluetooth Turned Off | Enable Bluetooth. |
|
||||
|
||||
### User Guide for the Demo App
|
||||
|
||||
Before installing and running the Demo App, configure `PenNavConfigurations.plist` with the values provided by our Customer Success Team:
|
||||
|
||||
| **Key** | **Value** |
|
||||
|----------------------------|-----------------------------------|
|
||||
| ClientKey | Provided by the Customer Success Team |
|
||||
| ClientId | Provided by the Customer Success Team |
|
||||
| DataUrl | Provided by the Customer Success Team |
|
||||
| PositionUrl | Provided by the Customer Success Team |
|
||||
| DataServiceName | Provided by the Customer Success Team |
|
||||
| PositionServiceName | Provided by the Customer Success Team |
|
||||
|
||||
---
|
||||
|
||||
[< Back](README-ios.md)
|
@ -0,0 +1,77 @@
|
||||
|
||||
|
||||
|
||||
# Errors
|
||||
|
||||
* [Missing SDK Configuration](#missing-sdk-configuration)
|
||||
* [Invalid SDK Configuration](#invalid-sdk-configuration)
|
||||
* [OS not supported](#os-not-supported)
|
||||
* [Signal Lost](#signal-lost)
|
||||
* [Sensors Initial Error](#sensors-initial-error)
|
||||
* [Loading Data Error](#loading-data-error)
|
||||
* [Default Venue Not Found](#default-venue-not-found)
|
||||
* [Default Floor Not Found](#default-floor-not-found)
|
||||
* [SDK Response Interface is null value](#sdk-response-interface-is-null-value)
|
||||
* [SDK Configuration is null value](#sdk-configuration-is-null-value)
|
||||
* [SDK Configuration Error](#sdk-configuration-error)
|
||||
* [Bluetooth Permissions Not Granted](#bluetooth-permissions-not-granted)
|
||||
* [Bluetooth Turned Off](#bluetooth-turned-off)
|
||||
* [Location Turned Off](#location-turned-off)
|
||||
|
||||
|
||||
## Missing SDK Configuration
|
||||
|
||||
Check if you set `Client Key`, `Client ID`, `Data URL`, `Position URL`, `Data Service Name`, and `Position Service Name`
|
||||
|
||||
## Invalid SDK Configuration
|
||||
Check if `Client Key`, `Client ID`, `Data URL`, `Position URL`, `Data Service Name`, and `Position Service Name` values match the values provided by our Customer Success Team
|
||||
|
||||
## OS not supported
|
||||
|
||||
Check if the software version on your device is Android 6.0 or later
|
||||
|
||||
minimum os supported is 23
|
||||
|
||||
## Signal Lost
|
||||
|
||||
Disconnected from server
|
||||
|
||||
## Sensors Initial Error
|
||||
|
||||
One or more of your device's sensors is failing to communicate
|
||||
Error while registering and starting sensors (Accelerometer, Magnetometer, Gyro, Orientation, Barometer, Pedometer)
|
||||
|
||||
## Loading Data Error
|
||||
Error while loading data (Venues, Floors, Edges and Settings)
|
||||
|
||||
## Default Venue Not Found
|
||||
Error while preparing outdoor data
|
||||
|
||||
## Default Floor Not Found
|
||||
Error while preparing outdoor data
|
||||
|
||||
## SDK Response Interface is null value
|
||||
|
||||
Check if you implemented the `PenNavUIDelegate` interface
|
||||
|
||||
## SDK Configuration is null value
|
||||
|
||||
you have to setup the configuration
|
||||
|
||||
[more about configuration ](configration.md)
|
||||
|
||||
## SDK Configuration Error
|
||||
|
||||
Wrong data provided by configuration
|
||||
|
||||
may one of the data is null or empty string
|
||||
|
||||
|
||||
## Bluetooth Permissions Not Granted
|
||||
Ensure that Bluetooth access has been granted
|
||||
|
||||
## Bluetooth Turned Off
|
||||
Check if Bluetooth is turned on
|
||||
|
||||
## Location Turned Off
|
||||
Check if Location is turned on
|
@ -0,0 +1,26 @@
|
||||
|
||||
# setBaseUrl(dataServerUrl, positionServerUrl)
|
||||
|
||||
This function is used to set the server IP or URL for the services required by the P&P module.
|
||||
|
||||
usually you will receive the following :
|
||||
|
||||
API : https://dev.penguinin.com:9090/api
|
||||
|
||||
PE : https://dev.penguinin.com:9090/pe
|
||||
|
||||
The URL consists of two parts: the base URL and the service name. The base URL is the first part of the URL, and it specifies the server or hostname. The service name is the second part of the URL, and it specifies the specific service that is being accessed."
|
||||
|
||||
For example, in the following URL:
|
||||
|
||||
https://dev.penguinin.com:9090/api
|
||||
|
||||
The base URL is https://dev.penguinin.com:9090
|
||||
|
||||
The service name is api
|
||||
|
||||
In this configuration you will pass the first part of the URL which is the server IP
|
||||
|
||||
```java
|
||||
setBaseUrl(https://dev.penguinin.com:9090, https://dev.penguinin.com:9090)
|
||||
```
|
@ -0,0 +1,15 @@
|
||||
|
||||
# setClientData(clientID, clientKey)
|
||||
|
||||
The client identifiers are unique identifiers that are provided by the PenguinIN team. It is used to access the P&P module functionality. With these credentials, clients are able to utilize the features and capabilities of the P&P module.
|
||||
|
||||
You will receive
|
||||
|
||||
1. clientID
|
||||
2. clientKey
|
||||
|
||||
The clientID and clientKey should be kept confidential and should not be shared with unauthorized parties.
|
||||
|
||||
```java
|
||||
setClientData(clientID, clientKey)
|
||||
```
|
@ -0,0 +1,11 @@
|
||||
# setCustomizeColor
|
||||
|
||||
The P&P module offers the ability to customize the colors of certain internal components through a configuration option. This allows users to alter the appearance of the UI to suit their preferences or match their organization's branding.
|
||||
|
||||
It is important to note that the default color for the P&P module is #2DA0B0.
|
||||
|
||||
> You need to pass the color in hex code
|
||||
|
||||
```java
|
||||
setCustomizeColor(hexCode)
|
||||
```
|
@ -0,0 +1,20 @@
|
||||
|
||||
# setDeepLinkData
|
||||
|
||||
The setDeepLinkData() method allows the passing of deep link data to be displayed on the map. This data is typically in the form of a hashed base64 string. When this method is called with the appropriate deep link data, it will be displayed on the map when it is initialized or already open.
|
||||
|
||||
**Parameters**
|
||||
|
||||
deepLinkData: A string containing the hashed base64 data to be passed to the map for display. This could include shared locations or points of interest.
|
||||
|
||||
- An example deep link including data for display on the map could be: "app://www.demo.com/MiwxLDEwCw5MTEuNDMyNTYsMzUuODY1NjUyMTA3NDQzMTI1LDMxLjk4MjU3MDM3MjQ1"
|
||||
|
||||
The data to be displayed on the map would be the last segment of the deep link:
|
||||
|
||||
"MiwxLDEwCw5MTEuNDMyNTYsMzUuODY1NjUyMTA3NDQzMTI1LDMxLjk4MjU3MDM3MjQ1"
|
||||
|
||||
Example :
|
||||
|
||||
```java
|
||||
setDeepLinkData("MiwxLDEwCw5MTEuNDMyNTYsMzUuODY1NjUyMTA3NDQzMTI1LDMxLjk4MjU3MDM3MjQ1");
|
||||
```
|
@ -0,0 +1,39 @@
|
||||
# setDeepLinkSchema
|
||||
|
||||
The setDeepLinkSchema() method allows the specification of a deep link schema for shared locations and points of interest. This is an optional method, and if not provided, the shared location or POI will not be active.
|
||||
|
||||
**Parameters**
|
||||
|
||||
deepLinkSchema: A string containing the desired deep link schema, such as app://www.demo.com.
|
||||
|
||||
## Update AndroidManifest.xml
|
||||
|
||||
The \<data> element in the intent-filter specifies the host and scheme for the deep link.
|
||||
|
||||
The **android:host** attribute is set to **@string/deeplinkHost**, which refers to the deep link host saved in the <u>**strings.xml**</u> file.
|
||||
|
||||
The **android:scheme** attribute is set to **@string/deeplinkSchema**, which refers to the deep link schema saved in the <u>**strings.xml**</u> file.
|
||||
|
||||
This allows the app to respond to deep links with the specified host and schema and handle them with the DeepLinkActivity.
|
||||
|
||||
It is important to ensure that the host and schema are saved correctly in the strings.xml file and that the correct references are used in the \<data> element of the intent-filter.
|
||||
|
||||
```java
|
||||
<activity
|
||||
android:name=".Activity">
|
||||
<intent-filter android:label="@string/app_name">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<data
|
||||
android:host="@string/deeplinkHost"
|
||||
android:scheme="@string/deeplinkSchema" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
```
|
||||
>Note
|
||||
>- It is recommended to save the deep link host and schema in the strings.xml file for future reference.
|
||||
>- The deep link schema should be provided in the correct format and adhere to the proper syntax for deep links.
|
||||
>- The use of this method is optional and may not be necessary in all cases. if not provided, the shared location or Shared POI will not be actived.
|
||||
|
||||
```java
|
||||
setDeepLinkSchema("app://www.demo.com")
|
||||
```
|
@ -0,0 +1,20 @@
|
||||
# setLanguageID
|
||||
|
||||
TThis function allows you to select a language code using the predefined 'Languages' enum.
|
||||
|
||||
The default language is English ('Languages.en'), but the function also supports Arabic ('Languages.ar').
|
||||
|
||||
Example usage:
|
||||
|
||||
```java
|
||||
setLanguageID(Languages.ar); // sets the language to Arabic
|
||||
```
|
||||
|
||||
```java
|
||||
setLanguageID(Languages.en); // sets the language to English
|
||||
```
|
||||
|
||||
```java
|
||||
setLanguageID(languageCode)
|
||||
```
|
||||
The default language of the P&P module is English.
|
@ -0,0 +1,23 @@
|
||||
# setServiceName(dataServiceName,positionServiceName)
|
||||
|
||||
This used to configure the server IP or URL for the services needed by the P&P module
|
||||
|
||||
Usually you will receive the following :
|
||||
|
||||
API : https://dev.penguinin.com:9090/api
|
||||
|
||||
PE : https://dev.penguinin.com:9090/pe
|
||||
|
||||
The URL consists of two parts: the base URL and the service name. The base URL is the first part of the URL, and it specifies the server or hostname. The service name is the second part of the URL, and it specifies the specific service that is being accessed.
|
||||
|
||||
For example, in the following URL:
|
||||
|
||||
https://dev.penguinin.com:9090/api
|
||||
|
||||
The base URL is https://dev.penguinin.com:9090
|
||||
|
||||
The service name is api
|
||||
|
||||
```java
|
||||
setServiceName(api, pe)
|
||||
```
|
@ -0,0 +1,12 @@
|
||||
# setSimulationModeEnabled
|
||||
|
||||
If the developer is not on the site and would like to test the P&P module, we have implemented a simulation mode that allows them to open the app with a predefined scenario. This feature is intended to ease the development process and enable the developer to test the app without being on the site.
|
||||
|
||||
> Important note :
|
||||
>
|
||||
> You will recieve a list of the predefined scenarios , when simulation mode enabled the
|
||||
> scenario name must be passed into username configration
|
||||
|
||||
```java
|
||||
setSimulationModeEnabled(isSimulation)
|
||||
```
|
@ -0,0 +1,14 @@
|
||||
|
||||
# setUserName
|
||||
|
||||
In this configuration, the app user identifier is the required parameter. This identifier is used to identify the user of the app and is necessary for the proper functioning of the app.
|
||||
|
||||
> Important notes :
|
||||
>
|
||||
> 1. This identifier must be unique mean that it's not allowed > for two devices to login tp P&P using same username
|
||||
>
|
||||
> >Violating this instruction will affect the positioning experience.
|
||||
|
||||
```java
|
||||
setUserName(name)
|
||||
```
|
Binary file not shown.
After Width: | Height: | Size: 564 B |
@ -0,0 +1,34 @@
|
||||
**/dgph
|
||||
*.mode1v3
|
||||
*.mode2v3
|
||||
*.moved-aside
|
||||
*.pbxuser
|
||||
*.perspectivev3
|
||||
**/*sync/
|
||||
.sconsign.dblite
|
||||
.tags*
|
||||
**/.vagrant/
|
||||
**/DerivedData/
|
||||
Icon?
|
||||
**/Pods/
|
||||
**/.symlinks/
|
||||
profile
|
||||
xcuserdata
|
||||
**/.generated/
|
||||
Flutter/App.framework
|
||||
Flutter/Flutter.framework
|
||||
Flutter/Flutter.podspec
|
||||
Flutter/Generated.xcconfig
|
||||
Flutter/ephemeral/
|
||||
Flutter/app.flx
|
||||
Flutter/app.zip
|
||||
Flutter/flutter_assets/
|
||||
Flutter/flutter_export_environment.sh
|
||||
ServiceDefinitions.json
|
||||
Runner/GeneratedPluginRegistrant.*
|
||||
|
||||
# Exceptions to above rules.
|
||||
!default.mode1v3
|
||||
!default.mode2v3
|
||||
!default.pbxuser
|
||||
!default.perspectivev3
|
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>App</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>io.flutter.flutter.app</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>App</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>12.0</string>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,2 @@
|
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||
#include "Generated.xcconfig"
|
@ -0,0 +1,2 @@
|
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||
#include "Generated.xcconfig"
|
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>AvailableLibraries</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>BinaryPath</key>
|
||||
<string>PenNavUI.framework/PenNavUI</string>
|
||||
<key>LibraryIdentifier</key>
|
||||
<string>ios-arm64_x86_64-simulator</string>
|
||||
<key>LibraryPath</key>
|
||||
<string>PenNavUI.framework</string>
|
||||
<key>SupportedArchitectures</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
<string>x86_64</string>
|
||||
</array>
|
||||
<key>SupportedPlatform</key>
|
||||
<string>ios</string>
|
||||
<key>SupportedPlatformVariant</key>
|
||||
<string>simulator</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>BinaryPath</key>
|
||||
<string>PenNavUI.framework/PenNavUI</string>
|
||||
<key>LibraryIdentifier</key>
|
||||
<string>ios-arm64</string>
|
||||
<key>LibraryPath</key>
|
||||
<string>PenNavUI.framework</string>
|
||||
<key>SupportedArchitectures</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>SupportedPlatform</key>
|
||||
<string>ios</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XFWK</string>
|
||||
<key>XCFrameworkFormatVersion</key>
|
||||
<string>1.0</string>
|
||||
</dict>
|
||||
</plist>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue