sdcard2 not writable on Tablet

Support for Android version of Total Commander

Moderators: white, Hacker, petermad, Stefan2

User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 48021
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) »

Copying a folder from internal flash (/mnt/sdcard) does not work.
Thanks for the hint, I will add that.
Copying files from the lan (SMB) does not work.
Currently this isn't supported in plugins, but I will try to add it to the next version if possible.

For anyone who wants to do this too, here is a class which you can use to write to the SD-Card. Feel free to use it in your own programs.

Code: Select all

package com.ghisler.android.TotalCommander;

import java.io.OutputStream;

import android.annotation.SuppressLint;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;

public class MediaFileFunctions {
	@SuppressLint({ "NewApi", "NewApi" })
	private static Uri getFileUri(Context context,String fullname) {
		// Note: check outside this class whether the OS version is >= 11
		Uri uri=null;
		Cursor cursor=null;
		ContentResolver contentResolver=null;
		try{
			contentResolver=context.getContentResolver();
			if (contentResolver==null)
				return null;
			uri=MediaStore.Files.getContentUri("external");
			String[] projection=new String[2];
			projection[0]="_id";
			projection[1]="_data";
			String selection="_data = ? ";    // this avoids SQL injection
			String[] selectionParams=new String[1];
			selectionParams[0]=fullname;
			String sortOrder="_id";
			cursor=contentResolver.query(uri, projection, selection, selectionParams, sortOrder);
			if (cursor!=null) {
				try {
					if (cursor.getCount()>0) {  // file present!
						cursor.moveToFirst();
						int dataColumn=cursor.getColumnIndex("_data");
						String s=cursor.getString(dataColumn);
						if (!s.equals(fullname))
							return null;
						int idColumn=cursor.getColumnIndex("_id");
						long id=cursor.getLong(idColumn);
						uri=MediaStore.Files.getContentUri("external",id);
					} else {  // file isn't in the media database!
						ContentValues contentValues=new ContentValues();
						contentValues.put("_data",fullname);
						uri=MediaStore.Files.getContentUri("external");
						uri=contentResolver.insert(uri,contentValues);
					}
				} catch (Throwable e) {
					uri=null;
				}
				cursor.close();
			}
		} catch (Throwable e) {
			uri=null;
		}
		return uri;
	}
	
	public static OutputStream getOutputStreamViaContentProvider(Context context,String fullname) {
		Uri uri=getFileUri(context,fullname);
		if (uri==null)
			return null;
		try {
			ContentResolver resolver=context.getContentResolver();
			return resolver.openOutputStream(uri);
		} catch (Throwable e) {
			return null;
		}
	}
	
	public static boolean deleteViaContentProvider(Context context,String fullname) {
		Uri uri=getFileUri(context,fullname);
		if (uri==null)
			return false;
		try {
			ContentResolver resolver=context.getContentResolver();
			// change type to image, otherwise nothing will be deleted
			ContentValues contentValues=new ContentValues();
			int media_type=1;
			contentValues.put("media_type", media_type);
			resolver.update(uri,contentValues,null,null);
			return resolver.delete(uri,null,null)>0;
		} catch (Throwable e) {
			return false;
		}
	}

	public static boolean mkDirViaContentProvider(Context context,String fullname) {
		String fileName;
		Uri uri;
		ContentResolver resolver;
		try {
			resolver=context.getContentResolver();
			fileName = strcatslash(fullname)+"ghisler_temp.jpg";
			ContentValues contentValues=new ContentValues();
			contentValues.put("_data", fileName);
			uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues);
		} catch (Throwable e) {
			return false;
		}
		if (uri!=null) {
			try {
				resolver.delete(uri,null,null);
			} catch (Throwable e) {
			}
			return true;
		} else
			return false;
	}

	public static String strcatslash(String dir) {
	if (dir.length()>0 && !dir.endsWith("/"))
		return dir+"/";
	else
		return dir;
    }

}
To create a file on the card, just call:

Code: Select all

boolean ok=true;
OutputStream g = null;
try {
	g = new FileOutputStream(fulltrg);
} catch (Exception e1) {
	ok = false;
}
if (!ok && getOsVersion()>=11 && fulltrg.startsWith("/mnt")) {
g=MediaFileFunctions.getOutputStreamViaContentProvider(this,fulltrg);
It's very important to check the OS version first, otherwise the class will crash your app on the first call! getOsVersion is defined like this:

Code: Select all

	public static int getOsVersion() {
		try {
			java.lang.reflect.Field osField = android.os.Build.VERSION.class.getDeclaredField("SDK_INT");
			osField.setAccessible(true);
			int myBuild = osField.getInt(android.os.Build.VERSION.class);
			return myBuild;
		} catch (Exception e) {
			return 3;
		}
	}
The reason why this works, and the normal File() object doesn't, is the following: We call to the multimedia database for images, music etc. This is part of a different process, which is part of the operating system. Since only operating system processes are allowed to write to the card, this method works. The File() object is part of our own program, therefore it's not allowed to write.
Author of Total Commander
https://www.ghisler.com
t_arn
Junior Member
Junior Member
Posts: 42
Joined: 2006-12-28, 07:52 UTC

Post by *t_arn »

Hello Christian

Will the MediaFileFunctions class also let me write to my external sdcard on KitKat again? The upgrade of my Samsung S4 to KitKat crippled my external sdcard to a mere media storage while I used it to store all my data before - this *really* made me angry!

Is MediaFileFunctions built into TC 2.04 ?
If yes, then it does not work on my device :(

I have also tested 2.05b3
There, I can write to /storage/extSdCard/Android/data/com.ghisler.android.TotalCommander/files, but not anywhere else on /storage/extSdCard/

Tom
User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 48021
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) »

Unfortunately it does not work any more on newer versions of Kitkat, it has all been locked down.
Author of Total Commander
https://www.ghisler.com
User avatar
DrShark
Power Member
Power Member
Posts: 1872
Joined: 2006-11-03, 22:26 UTC
Location: Kyiv, 68/262
Contact:

Post by *DrShark »

When I had the Android 4.0.4 on the device, AFAIR (unfortunately I didn't save a screenshot) TC detected 3 media storages: Internal Storage, SDCard (it is internal fake sd), and SDcard2 (extsd one).
After I updated the Android 4.3.1 TC detects "Internal Storage" which is indeed a mentioned above internal fake SD, and TC shows SD card logo for it. Also it detects the SDCard which currently points to extsd.
TC can currently with Android 4.3.1 and could on Android 4.0.4 before to move files/folders on/to/from extsd, but the function to create New text file or New text file (UTF-8) don't work on extsd (and didn't work on Android 4.0.4).
However, once made a new folder with the empty file ghisler_temp.jpg inside (maybe it was while on Android 4.0.4, currently on 4.3.1 I can't reproduce it: TC creates empty folders on extsd), which could mean that actually TC can make a new file on extSD. If true, would be nice to see New text file creation feature to work on extsd too.
Donate for Ukraine to help stop Russian invasion!
Ukraine's National Bank special bank account:
UA843000010000000047330992708
User avatar
DrShark
Power Member
Power Member
Posts: 1872
Joined: 2006-11-03, 22:26 UTC
Location: Kyiv, 68/262
Contact:

Post by *DrShark »

2ghisler(Author)
A also have to add that sometimes TC4A shows error calling su when trying to create a new text file, even though my device is not rooted, but usually it's just an writing file error. TC4A can show diffrerntg kind of error even for one new filename on one location on extsd, so I don't know what exactly causes this.

Since in this post you mentioned that writing to text file on extsd may fail on a rooted device, it may be the case that TC doesn't detect the root status on my device correctly.
Donate for Ukraine to help stop Russian invasion!
Ukraine's National Bank special bank account:
UA843000010000000047330992708
User avatar
DrShark
Power Member
Power Member
Posts: 1872
Joined: 2006-11-03, 22:26 UTC
Location: Kyiv, 68/262
Contact:

Post by *DrShark »

DrShark wrote:New text file or New text file (UTF-8) don't work on extsd
No changes in TC4A 2.81 beta 7. I got the following error when trying to create New text file:

Code: Select all

----
Write error
----
Error writing to target file!
/storage/extsd/testfile.txt

su error:
su call failed!
----
OK
----
It appeared after I tried to create a first text file since the updated TC 2.81 beta 7 launched.
After trying to create this file again (after clicking OK in above error window and selecting New text file from context menu of .. item in /storage/extsd), next error appeared:

Code: Select all

----
Write error
----
Error writing to target file!
/storage/extsd/testfile.txt
----
OK
----
Donate for Ukraine to help stop Russian invasion!
Ukraine's National Bank special bank account:
UA843000010000000047330992708
User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 48021
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) »

Sorry, this is currently not possible.
Author of Total Commander
https://www.ghisler.com
User avatar
DrShark
Power Member
Power Member
Posts: 1872
Joined: 2006-11-03, 22:26 UTC
Location: Kyiv, 68/262
Contact:

Post by *DrShark »

history2.txt wrote:2017-08-11 Fixed: Could not create new text file (via long tap on "..") on secondary storage (e.g. SD card) when device was rooted
Maybe this fixed something on rooted devices, but my Android 4.3.1 device is not rooted, and I still get error messages mentioned in this post. Also Write error/su error appears if I change the path in file copy dialog manually (changing the target path to /original target path on extsd/new dir name/name.ext or /new target path on extsd/name.ext or just newname.ext).

What's important is if Write error/su error will appear after each of several continuous tries of creating a new file, something like a memory leak happens: interfaces of apps and reaction to keypresses on Android Navigation keys are slower, Android starts to close apps and notifications (like TC Media Player). In TC4A panels associated icons of files may change to default/general file icons (they may re-appear again after a refresh or re-enter to the folder.) Restart of TC4A doesn't help. After such a thing happened I had to reboot a device.
Donate for Ukraine to help stop Russian invasion!
Ukraine's National Bank special bank account:
UA843000010000000047330992708
User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 48021
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) »

Sorry, this function is currently only supported on Android 5 and newer.
Author of Total Commander
https://www.ghisler.com
User avatar
DrShark
Power Member
Power Member
Posts: 1872
Joined: 2006-11-03, 22:26 UTC
Location: Kyiv, 68/262
Contact:

New text file creation on Android 4 extsd

Post by *DrShark »

ghisler(Author) wrote: 2017-08-31, 08:39 UTC Sorry, this function is currently only supported on Android 5 and newer.
Is there a chance for TC4A 3.x to get new file creation working on external SD in Android 4.x?
Donate for Ukraine to help stop Russian invasion!
Ukraine's National Bank special bank account:
UA843000010000000047330992708
User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 48021
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Re: sdcard2 not writable on Tablet

Post by *ghisler(Author) »

Unfortuantely I don't currently have any 4.4 devices with write restrictions to the card, so I cannot say what's wrong.
The strange thing is that I can create new files in other restricted directories like /data/data/other_app

Since you have root, why not apply the SD-Card root fix? For this, go to
/system/etc/permissions
Then make a backup of the file platform.xml and note its permissions.
Now edit the file and change the two relevant sections to:

Code: Select all

<permission name="android.permission.WRITE_EXTERNAL_STORAGE" >
    <group gid="sdcard_r" />
    <group gid="sdcard_rw" />
    <group gid="media_rw" />
</permission>
<permission name="android.permission.WRITE_MEDIA_STORAGE" >
    <group gid="sdcard_rw" />
    <group gid="media_rw" />
</permission>
Author of Total Commander
https://www.ghisler.com
User avatar
DrShark
Power Member
Power Member
Posts: 1872
Joined: 2006-11-03, 22:26 UTC
Location: Kyiv, 68/262
Contact:

Re: sdcard2 not writable on Tablet

Post by *DrShark »

ghisler(Author) wrote: 2019-03-07, 08:24 UTC Unfortuantely I don't currently have any 4.4 devices ... Since you have root...
My device runs Android 4.3.1, and I don't have a root (see my signature for more details.)
Donate for Ukraine to help stop Russian invasion!
Ukraine's National Bank special bank account:
UA843000010000000047330992708
User avatar
DrShark
Power Member
Power Member
Posts: 1872
Joined: 2006-11-03, 22:26 UTC
Location: Kyiv, 68/262
Contact:

Re: sdcard2 not writable on Tablet

Post by *DrShark »

On TC4A 3.0 beta 3 creation of new text file (also UTF-8) works fine on my Android 4.3.1 device, thanks for this fix! Also, on BlackBerry device with QNX+Android 4.2.2 where extsd is mounted as part of internal memory (so new text file creation worked even in previous TC4A versions), this function still works without problems.
Donate for Ukraine to help stop Russian invasion!
Ukraine's National Bank special bank account:
UA843000010000000047330992708
User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 48021
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Re: sdcard2 not writable on Tablet

Post by *ghisler(Author) »

Great, thanks for letting me know! Indeed I'm calling the special sd-card function I use when copying files (but don't write to the file) when the function via File API fails.
Author of Total Commander
https://www.ghisler.com
User avatar
DrShark
Power Member
Power Member
Posts: 1872
Joined: 2006-11-03, 22:26 UTC
Location: Kyiv, 68/262
Contact:

Re: sdcard2 not writable on Tablet

Post by *DrShark »

TC4A 3.0 beta 3 can't pack to ZIP archives (both new and existing) on Android 4.3.1 device's extsd (neither in extsd->extsd nor in internal memory->extsd direction). Is it possible to fix this using special sd-card function for copying files you used for above new file creation fix?
Donate for Ukraine to help stop Russian invasion!
Ukraine's National Bank special bank account:
UA843000010000000047330992708
Post Reply