How to change the file/folder permission programmatically in android
Asked Answered
F

1

2

I want to change the permission of a folder were application database is being stored.

After searching on Google I found this:-

public int chmod(File path, int mode) throws Exception {
  Class fileUtils = Class.forName("android.os.FileUtils");
  Method setPermissions =
      fileUtils.getMethod("setPermissions", String.class, int.class, int.class, int.class);
  return (Integer) setPermissions.invoke(null, path.getAbsolutePath(), mode, -1, -1);
}

...
chmod("/foo/bar/baz", 0755);
...

Here the FileUtils class should be a part of android.os package but I wasn't able to find it while importing the package.

Any idea how to use FileUtils or some other way to change the permission of folder?

I am changing the permission because after installing my app when I try to access the database, app stops working. As my device is rooted so when I change the permission of the database folder from 771 to 777 using Root Browser the app starts working perfectly.

So how to change the permission of the folder while installation of app i.e. programmatically in unrooted devices?

My DBHelper class:-

public class DBHelper extends SQLiteOpenHelper {

public SQLiteDatabase database = null;
public File databaseFile;
public static String databaseName = "Db1.sqlite";
public String databasePath = "";
Context mContext;

public DBHelper(Context paramContext) {

    super(paramContext, databaseName, null, 1);
    this.mContext = paramContext;

    Log.d("data", "package name:" + paramContext.getPackageName());

    //this.databasePath = ("data/data/" + paramContext.getPackageName() + "/databases/"+databaseName);
    this.databasePath = (Environment.getExternalStorageDirectory().getAbsolutePath()+"/Android/data/"+paramContext.getPackageName()+"/"+databaseName);
    System.out.println(databasePath);
    this.databaseFile = new File(this.databasePath);
    if (!this.databaseFile.exists())
        try {
            deployDataBase(DBHelper.databaseName, this.databasePath);
            return;
        } catch (IOException localIOException) {
            localIOException.printStackTrace();
        }
}

private void deployDataBase(String dbNAme, String dbPath)
        throws IOException {
    InputStream localInputStream = this.mContext.getAssets().open(dbNAme);
    FileOutputStream localFileOutputStream = new FileOutputStream(dbPath);
    byte[] arrayOfByte = new byte[1024];
    while (true) {
        int i = localInputStream.read(arrayOfByte);
        if (i <= 0) {
            localFileOutputStream.flush();
            localFileOutputStream.close();
            localInputStream.close();
            return;
        }
        localFileOutputStream.write(arrayOfByte, 0, i);
    }
}

@Override
public synchronized void close() {

    if (database != null)
        database.close();

    super.close();

}
@Override
public void onCreate(SQLiteDatabase db) {
    // TODO Auto-generated method stub

}
Fsh answered 20/8, 2014 at 5:40 Comment(8)
You're playing a dangerous game.Ingenue
@SotiriosDelimanolis But if I don't do this how can I solve my problem?Fsh
y not have your db defined in external sdcard ?Refrigeration
@Javanator what if the device is not having external sdcard?Fsh
most of the devices these days dont have external storage slot but have external storage as emulated partition of internal storageRefrigeration
Environment.getExternalStorageDirectory() . If this gives a path to you. your are good to go to use this to have db there and things are completely public out here AFAIK. Let me know if you need code to do thatRefrigeration
@Javanator I am using "data/data/" + paramContext.getPackageName() + "/databases/"+databaseName path to store the db.Fsh
Let us continue this discussion in chat.Refrigeration
R
2
  • Do not play with db path and file permissions for your case.

  • IMO Rooted and Normal Device are mutually exclusive audience.

  • Only For your testing rooted devices create db on sd card with path derived from Environment.getExternalStorage** method.

TO HAVE YOUR DB ON SD CARD. DO SOMETHING LIKE THIS.

Put this class in your code packages.

package com.test.db;

import java.io.File;

import android.content.Context;
import android.content.ContextWrapper;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.os.Environment;

/** 
 * Custom context wrapper to proxy the database file path.
 * Instead of storing data on internal storage for app
 * we will storing the data on external sd card.
 */
public class DatabaseContext extends ContextWrapper {

    /*
     * Used for logging.
     */
    private static final String DEBUG_CONTEXT = "DatabaseContext";

    /*
     * Constructor wrapping given app context.
     */
    public DatabaseContext(Context base) {
        super(base);
    }

    /**
     * Proxy the path to data base file for every operation
     * @see android.content.ContextWrapper#getDatabasePath(java.lang.String)
     */
    @Override
    public File getDatabasePath(String name) {

        String state = Environment.getExternalStorageState();

        if (Environment.MEDIA_MOUNTED.equals(state)) {
            // We can read and write the media
            File sdcard = Environment.getExternalStorageDirectory();
            String dbfile = sdcard.getAbsolutePath() + File.separator + "com.test" +     File.separator + "database" + File.separator
                + name;
            if (!dbfile.endsWith(".db")) {
                dbfile += ".db";
            }

            File result = new File(dbfile);

            if (!result.getParentFile().exists()) {
                if(!result.getParentFile().mkdirs()){
                    result = new File(sdcard, name);
                }
            }

            if (android.util.Log.isLoggable(DEBUG_CONTEXT, android.util.Log.WARN)) {
                android.util.Log.w(DEBUG_CONTEXT,
                    "getDatabasePath(" + name + ") = " + result.getAbsolutePath());
            }

            return result;

        } else {
            // Something else is wrong. It may be one of many other states,
            // Writing data on internal storage
            return super.getDatabasePath(name);
        }

    }

    @Override
    public SQLiteDatabase openOrCreateDatabase(String name, int mode,
            CursorFactory factory) {
        return openOrCreateDatabase(name, mode, factory, null);
    }

    @Override
    public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,
        DatabaseErrorHandler errorHandler) {
        SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name)
            .getAbsolutePath(), null, errorHandler);

        return result;
    }
}

Extend SqliteOpenHelper class like this

package com.test.db;

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

import android.content.Context; 
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

/**
 * Custom SqliteOpenHelper.
 */
public class MySQLiteOpenHelper extends SQLiteOpenHelper {

    private static final String TAG = My.class.getSimpleName();

    private final Context context;

    public  MySQLiteOpenHelper(Context context, String name, int version, String mResourceName) {
        super(new DatabaseContext(context), name, /*factory*/null, version);
        this.context = context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
      // Create tables here
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }

}

This is tested piece to create db in sd card. Please check

Refrigeration answered 20/8, 2014 at 7:39 Comment(10)
I used Environment.getExternalStorageDirectory().getAbsolutePath()+"/Android/data/"+paramContext.getPackageName()+"/"+databaseName as path to store my db but I can't see it there :(Fsh
print the full path hereRefrigeration
/storage/sdcard/Android/data/com.test/Db1.sqliteFsh
The app gives an exception:- java.io.FileNotFoundException: /storage/sdcard/Android/data/com.test/Db1.sqlite: open failed: ENOENT (No such file or directory)Fsh
Because there is no file there. you have to create it. Check the above code pieces. It will do that for you.Refrigeration
Please check my DBHelper class file. I think it does all the work.Fsh
Try using MySQLiteOpenHelper i provided. Modify path in DatabaseContext class according to you.Refrigeration
How does your DatabaseContext class knows the name of db stored in assets folder?Fsh
It dont. firstly i would suggest to leave your asset db aside and try sample db operation on normal app db first. Are you able to do that. The files i provided will create your app db in sd card. Try sample operation on itRefrigeration
db was copied but with permission :- 075(---rwxr-x) i.e. the user don't have permission to access the db. Due to this the app crashed again.Fsh

© 2022 - 2024 — McMap. All rights reserved.