This Flutter app retrieves and displays detailed device information across multiple platforms, including Android, iOS, Linux, Windows, macOS, and Web.
- Device Identifier: Fetches a unique device identifier using platform-specific code through a
MethodChannel
. - Platform-Specific Information: Uses the
DeviceInfoPlugin
to gather detailed device data, such as OS version, model, manufacturer, memory, and other relevant specs. Each platform has its dedicated method for optimal data handling. - Dynamic UI: Automatically adapts the app title and displayed information based on the detected platform. Device details are shown in a scrollable list with clear labeling.
- Error Handling: Gracefully handles unsupported platforms by displaying an error message if information retrieval fails.
- Android
- iOS
- Linux
- Windows
- macOS
- Web
- Fuchsia (Displays an unsupported message for demonstration purposes)
The app initializes by detecting the platform and retrieving device-specific details using the DeviceInfoPlugin
. The information is then displayed in a user-friendly format in the UI. This app serves as a useful tool for developers needing device diagnostics or cross-platform device information.
Kotlin class for the MainActivity
of a Flutter app that interacts with Android's native layer to retrieve a device identifier. It uses a MethodChannel
to communicate between Flutter and Android, enabling the app to access platform-specific functionality, such as the device’s serial number or Android ID. Here’s a breakdown of each part:
class MainActivity: FlutterActivity() {
private val CHANNEL = "com.example.deviceInfo"
private val REQUEST_PHONE_STATE = 1
MainActivity
extendsFlutterActivity
, meaning it's the main entry point for the Android part of a Flutter app.CHANNEL
is the unique identifier for theMethodChannel
used to communicate with Flutter.REQUEST_PHONE_STATE
is a constant representing the request code for permission to read the phone state.
override fun configureFlutterEngine(flutterEngine: io.flutter.embedding.engine.FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
configureFlutterEngine
is overridden to set up theMethodChannel
with Flutter.MethodChannel(...).setMethodCallHandler
sets a listener for method calls from Flutter. Here, it listens for thegetDeviceIdentifier
method to retrieve the device ID.
if (call.method == "getDeviceIdentifier") {
if (Build.VERSION.SDK_INT in Build.VERSION_CODES.O..Build.VERSION_CODES.P) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
result.success(getDeviceIdentifier())
} else {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_PHONE_STATE), REQUEST_PHONE_STATE)
result.success("Permission required")
}
} else {
result.success(getDeviceIdentifier())
}
} else {
result.notImplemented()
}
-
If
getDeviceIdentifier
is called, the code checks the Android version:- Android 8-9 (Oreo to Pie): Requires
READ_PHONE_STATE
permission to access the device's serial number. If permission is granted, it retrieves the device identifier. Otherwise, it requests permission. - Other Versions: For Android 10 and later, it uses
ANDROID_ID
for the device identifier, which does not require permission.
- Android 8-9 (Oreo to Pie): Requires
-
If the method called is not
getDeviceIdentifier
, it responds withnotImplemented()
.
private fun getDeviceIdentifier(): String {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
} else {
try {
Build.getSerial()
} catch (e: SecurityException) {
"Permission denied"
}
}
}
- For Android 10 (API level 29) and above, it retrieves
ANDROID_ID
viaSettings.Secure.getString
. - For versions below Android 10, it attempts to retrieve
Build.getSerial()
. If the permission is denied, it catches theSecurityException
and returns “Permission denied.”
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
if (requestCode == REQUEST_PHONE_STATE) {
if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
flutterEngine?.dartExecutor?.binaryMessenger?.let { messenger ->
MethodChannel(messenger, CHANNEL).invokeMethod("getDeviceIdentifier", getDeviceIdentifier())
}
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
onRequestPermissionsResult
handles the result of the permission request.- If permission is granted, it re-invokes the
getDeviceIdentifier
method to retrieve and send the identifier back to Flutter.
This setup allows the Flutter app to retrieve a unique device identifier across various Android versions while handling permission requirements and potential exceptions.