When I try to write something to the COM port via the command line in the android, I just write in the shell: echo 123abc > /dev/ttyO0 and get it in the terminal. It's simple. If I try to do the same in android:

 final byte[] request = {0x0A, 0x10, 0, (byte)0x99, 0, 0x01, (byte)0xD0, (byte)0x9D}; final String comPortAddress = "/dev/ttyO0"; final OutputStream fileOutputStream = new FileOutputStream(comPortAddress); fileOutputStream.write(request); fileOutputStream.flush(); fileOutputStream.close(); 

That get an exception:

 W/System.err: java.io.FileNotFoundException: /dev/ttyO0: open failed: EACCES (Permission denied) W/System.err: at libcore.io.IoBridge.open(IoBridge.java:416) W/System.err: at java.io.FileOutputStream.<init>(FileOutputStream.java:88) W/System.err: at java.io.FileOutputStream.<init>(FileOutputStream.java:128) W/System.err: at java.io.FileOutputStream.<init>(FileOutputStream.java:117) W/System.err: at keppowertesting.com.modbustesterapp.TryStreams.go(TryStreams.java:15) W/System.err: at keppowertesting.com.modbustesterapp.MainActivity.button2Click(MainActivity.java:49) W/System.err: at java.lang.reflect.Method.invokeNative(Native Method) W/System.err: at java.lang.reflect.Method.invoke(Method.java:511) W/System.err: at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288) W/System.err: at android.view.View.performClick(View.java:4204) W/System.err: at android.view.View$PerformClick.run(View.java:17355) W/System.err: at android.os.Handler.handleCallback(Handler.java:725) W/System.err: at android.os.Handler.dispatchMessage(Handler.java:92) W/System.err: at android.os.Looper.loop(Looper.java:137) W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5041) W/System.err: at java.lang.reflect.Method.invokeNative(Native Method) W/System.err: at java.lang.reflect.Method.invoke(Method.java:511) W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) W/System.err: at dalvik.system.NativeStart.main(Native Method) W/System.err: **Caused by: libcore.io.ErrnoException: open failed: EACCES (Permission denied)** W/System.err: at libcore.io.Posix.open(Native Method) W/System.err: at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110) W/System.err: at libcore.io.IoBridge.open(IoBridge.java:400) W/System.err: ... 19 more 

I have a line in the manifest:

 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="25"/> 

But it is clearly not enough. Root access on the device is present.

    1 answer 1

    If you use methods that are accessible only to root, then in AndroidManifest.xml add the appropriate line:

     <uses-permission android:name="android.permission.ACCESS_SUPERUSER"> 

    WRITE_EXTERNAL_STORAGE belongs to dangerous permissions, therefore, to get this permission (with targetSdk 23 and higher), in addition to the corresponding line in AndroidManifest.xml you must also request this permission from the user in runtime .

    Here is a small example of a request for the permission you need:

     public class MainActivity extends AppCompatActivity { private final int MY_PERMISSIONS_WRITE_EXTERNAL_STORAGE = 1; private Button mButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mButton = (Button) findViewById(R.id.button); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != getPackageManager().PERMISSION_GRANTED) { ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSIONS_WRITE_EXTERNAL_STORAGE); } } }); } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case MY_PERMISSIONS_WRITE_EXTERNAL_STORAGE: { if (grantResults.length > 0 && grantResults[0] == getPackageManager().PERMISSION_GRANTED) { Toast.makeText(MainActivity.this, "Разрешение получено", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, "Разрешение отклонено", Toast.LENGTH_SHORT).show(); } return; } } } } 

    When you click on the button, permission is requested, after the user's reaction, Toast displayed with information about whether the requested permission has been received or not.

    • Thank you for your efforts, but this did not change anything. I have API17, and no query pops up. I also tried to simplify the task and work with a simple file /test.txt, but the same thing. And what is interesting, in the Supersu logs there is no my program, that is, there were no attempts to do something on behalf of root on the part of the program. - Eugene
    • @Eugene, targetSdk 17 ? or on the device api level 17 ? The fact that your program is not in the logs is quite logical, since it cannot access the files, as there is no access. You still try my advice. - post_zeew Nov.
    • And try to add in the manifest android.permission.ACCESS_SUPERUSER . - post_zeew Nov.
    • This is all wrong. This is what helped: 'if (! File.canRead () ||! File.canWrite ()) {try {Process su = Runtime.getRuntime (). Exec ("su"); if ((su.waitFor ()! = 0) ||! file.canRead () ||! file.canWrite ()) {System.out.println ("Still not!"); return; }} catch (Exception e) {}} ' - Eugene
    • API level 17. targetSDK 25. Only after calling 'Runtime.getRuntime (). Exec ("su")' a request for root access from Supersu appeared on the screen, I allowed, and then it worked. - Eugene