Search code examples
androidxamarin.androidandroid-permissions

android Build.GetSerial() throwing exception


I'm developing a Xamarin.Android project,where I need to get the Device Serial number.

I have implemented it the way it is shown below. Also added the permissions in the manifest file:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />

string serial;
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
     serial = Build.GetSerial();
}
else
{
     serial = Build.Serial;
}

I have tried it on two different devices(both android 9.0).Sadly i get the following exception when the GetSerial() function is called(huawei p10): Java.Lang.SecurityException: <Timeout exceeded getting exception details> .

On an other device(galaxy s8) I get this exception:

Java.Lang.SecurityException: getSerial requires READ_PHONE_STATE or READ_PRIVILEGED_PHONE_STATE permission

I really dont understand what the problem is,because I have added both permissions in the manifest,which the exception sais... Any idea what am I doing wrong?


Solution

  • You should faced a persmission issue. And since Android Marshmallow, you need to ask the user for the permissions. Besides adding the permission in android manifest file, you can also add runtime permissions like this:

    static readonly int REQUEST_PHONE_STATE = 1;
    
    public void checkPermission()
        {
            Log.Info(TAG, "Checking permission.");
    
            // Check if the  permission is already available.
            if (ActivityCompat.CheckSelfPermission(this, Manifest.Permission.ReadPhoneState) != (int)Permission.Granted)
            {
    
                //  permission has not been granted
                RequestPhoneStatePermission();
            }
            else
            {
                //  permissions is already available, show the camera preview.
                Log.Info(TAG, " permission has already been granted.");
                getInfo();
            }
        }
    

    Method RequestPhoneStatePermission

     private void RequestPhoneStatePermission()
        {
            Log.Info(TAG, "PhoneState permission has NOT been granted. Requesting permission.");
    
            if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.ReadPhoneState))
            {
                Log.Info(TAG, "Displaying PhoneState permission rationale to provide additional context.");
    
                Snackbar.Make(layout, Resource.String.permission_phonestate_rationale,
                    Snackbar.LengthIndefinite).SetAction(Resource.String.ok, new Action<View>(delegate (View obj) {
                        ActivityCompat.RequestPermissions(this, new String[] { Manifest.Permission.ReadPhoneState }, REQUEST_PHONE_STATE);
                    })).Show();
            }
            else
            {
                // PhoneState permission has not been granted yet. Request it directly.
                ActivityCompat.RequestPermissions(this, new String[] { Manifest.Permission.ReadPhoneState }, REQUEST_PHONE_STATE);
            }
        }
    

    Method OnRequestPermissionsResult

       public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
        {
            if (requestCode == REQUEST_PHONE_STATE)
            {
                // Received permission result for camera permission.
                Log.Info(TAG, "Received response for phone state permission request.");
    
                // Check if the only required permission has been granted
                if (grantResults.Length == 1 && grantResults[0] == Permission.Granted)
                {
                    // Camera permission has been granted, preview can be displayed
                    Log.Info(TAG, "phonestate permission has now been granted. Showing preview.");
                    Snackbar.Make(layout, Resource.String.permission_available_phonestate, Snackbar.LengthShort).Show();
    
                    getInfo();
    
                }
                else
                {
                    Log.Info(TAG, "phonestate permission was NOT granted.");
                    Snackbar.Make(layout, Resource.String.permissions_not_granted, Snackbar.LengthShort).Show();
                }
            }
            else
            {
                base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
            }
        }
    

    method getInfo

    private void getInfo() {
            string serial;
            if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
            {
                serial = Build.GetSerial();
            }
            else
            {
                serial = Build.Serial;
            }
    
            Log.Info(TAG, "serial = " + serial);
        }
    

    Here is a full demo, you can check it.

    After that, you can get the effect: enter image description here

    For more details,you can check: https://learn.microsoft.com/en-us/xamarin/android/app-fundamentals/permissions?tabs=windows

    https://devblogs.microsoft.com/xamarin/requesting-runtime-permissions-in-android-marshmallow/