0

I created an Android app that works fine with OS v6.0/6.01 (Marshmallow). When I tried it with OS v7.1 (Nougat) it crashed because of the WRITE_SETTINGS requirement. With the addition of the added code the screen to modify the system settings shows up with v6.0 but is grayed out. The same thing happens with v7.1 only the app crashes first.

onCreate method

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 

    //***added code***
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (!Settings.System.canWrite(getApplicationContext())) {
            Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS);
            intent.setData(Uri.parse("package:" + getApplicationContext().getPackageName()));
            startActivity(intent);
        }
    }


     if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    != PackageManager.PERMISSION_GRANTED) {

        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                REQUEST_CODE_ASK_PERMISSIONS);
    }


    if (android.provider.Settings.System.getInt(getContentResolver(),
            Settings.System.ACCELEROMETER_ROTATION, 0) == 1) {

        android.provider.Settings.System.putInt(getContentResolver(),
                Settings.System.ACCELEROMETER_ROTATION, 0);
    }


    start = (Button) findViewById(R.id.button_start);
    start.setEnabled(true);

    stop = (Button) findViewById(R.id.button_stop);
    stop.setEnabled(true);

    confirm_ip = (Button) findViewById(R.id.button_confirm_ip);
    confirm_ip.setEnabled(true);
    confirm_ip.setOnClickListener(this);

    grab_device = (Button) findViewById(R.id.button_device);
    grab_device.setEnabled(true);
    grab_device.setOnClickListener(this);

    send = (Button) findViewById(R.id.button_send);
    send.setEnabled(false);
    send.setOnClickListener(this);

    clear_loc = (Button) findViewById(R.id.button_cl);
    clear_loc.setEnabled(true);
    clear_loc.setOnClickListener(this);

    device_name = (EditText) findViewById(R.id.et_device_name);
    device_name.setEnabled(true);

    location = (EditText) findViewById(R.id.et_location);
    location.setEnabled(true);

    scenario = (EditText) findViewById(R.id.et_scenario);
    scenario.setEnabled(true);

    distance = (EditText) findViewById(R.id.et_distance);
    distance.setEnabled(true);

    server_ip = (EditText) findViewById(R.id.et_server_ip);
    server_ip.setEnabled(true);
    server_ip.setText(R.string.server_ip);

    mAppStatus = (TextView) findViewById(R.id.tv_app_status);

    scenario_spinner = (Spinner) findViewById(R.id.spinner_scenario);
    scenario_spinner.setOnItemSelectedListener(this);

    ArrayAdapter<CharSequence> adp_scenario = ArrayAdapter.createFromResource(this, R.array.scenario_array,
            android.R.layout.simple_spinner_item);
    adp_scenario.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
    scenario_spinner.setAdapter(adp_scenario);


    distance_spinner = (Spinner) findViewById(R.id.spinner_distance);
    distance_spinner.setOnItemSelectedListener(this);

    ArrayAdapter<CharSequence> adp_distance = ArrayAdapter.createFromResource(this, R.array.distance_array,
            android.R.layout.simple_spinner_item);
    adp_distance.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
    distance_spinner.setAdapter(adp_distance);

    handler = new Handler(Looper.getMainLooper());

}

AndroidManifext.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.rssicollector">
<user-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

Here is the error it produces with v7.1

08-10 09:51:19.002 31732-31732/? E/AndroidRuntime: FATAL EXCEPTION: main
                                               Process: com.example.android.rssicollector, PID: 31732
                                               java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.rssicollector/com.example.android.rssicollector.MainActivity}: java.lang.SecurityException: com.example.android.rssicollector was not granted  this permission: android.permission.WRITE_SETTINGS.
                                                   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2666)
                                                   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2727)
                                                   at android.app.ActivityThread.-wrap12(ActivityThread.java)
                                                   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1478)
                                                   at android.os.Handler.dispatchMessage(Handler.java:102)
                                                   at android.os.Looper.loop(Looper.java:154)
                                                   at android.app.ActivityThread.main(ActivityThread.java:6121)
                                                   at java.lang.reflect.Method.invoke(Native Method)
                                                   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
                                                   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
                                                Caused by: java.lang.SecurityException: com.example.android.rssicollector was not granted  this permission: android.permission.WRITE_SETTINGS.
                                                   at android.os.Parcel.readException(Parcel.java:1684)
                                                   at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
                                                   at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
                                                   at android.content.ContentProviderProxy.call(ContentProviderNative.java:646)
                                                   at android.provider.Settings$NameValueCache.putStringForUser(Settings.java:1595)
                                                   at android.provider.Settings$System.putStringForUser(Settings.java:1965)
                                                   at android.provider.Settings$System.putIntForUser(Settings.java:2070)
                                                   at android.provider.Settings$System.putInt(Settings.java:2064)
                                                   at com.example.android.rssicollector.MainActivity.onCreate(MainActivity.java:132)
                                                   at android.app.Activity.performCreate(Activity.java:6682)
                                                   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
                                                   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2619)
                                                   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2727) 
                                                   at android.app.ActivityThread.-wrap12(ActivityThread.java) 
                                                   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1478) 
                                                   at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                   at android.os.Looper.loop(Looper.java:154) 
                                                   at android.app.ActivityThread.main(ActivityThread.java:6121) 
                                                   at java.lang.reflect.Method.invoke(Native Method) 
                                                   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) 
                                                   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) 

Any ideas as to what's going on/how to fix it? Any help would be greatly appreciated!

PattiK
  • 1
  • 2

1 Answers1

1
if (android.provider.Settings.System.getInt(getContentResolver(),
        Settings.System.ACCELEROMETER_ROTATION, 0) == 1) {

    android.provider.Settings.System.putInt(getContentResolver(),
            Settings.System.ACCELEROMETER_ROTATION, 0);
}

Only execute that code if Settings.System.canWrite(getApplicationContext()) returns true. Right now, you execute that code regardless of what canWrite() returns.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491