शुभ संध्या, मैं एक एंड्रॉइड ऐप विकसित कर रहा हूं, इसमें SQLite डेटाबेस है, मुझे डेटाबेस को डिवाइस के बाहरी स्टोरेज में कॉपी करने का एक तरीका चाहिए, जहां मैं किसी अन्य डिवाइस पर कॉपी कर सकता हूं और इसलिए मैं डेटाबेस को दूसरे डिवाइस में आयात कर सकता हूं .

उदाहरण के लिए:

मान लीजिए कि एप्लिकेशन "उदाहरण" कहता है, डेटाबेस "/data/data/com.gnd.example/databases" फ़ोल्डर में है और इसे data.db कहा जाता है, इसे "उदाहरण / बैकअप" फ़ोल्डर में कॉपी करने की आवश्यकता है, उदाहरण के लिए" / स्टोरेज / एमुलेटेड / 0 / उदाहरण / बैकअप "। यह पहला भाग है।

दूसरा भाग आयात है, जहां एप्लिकेशन को "उदाहरण / आयात" फ़ोल्डर से फ़ाइल को "/data/data/com.gnd.example/databases" फ़ोल्डर में कॉपी करना चाहिए।

इसके लिए मेरे पास दो बटन गतिविधि है, btn_export और btn_import।

मैंने पहले से ही निम्नलिखित समाधानों पर भरोसा किया है:

Android sqlite डेटाबेस में आयात / निर्यात Android पर SQLite डेटाबेस का सरल निर्यात और आयात

मैंने इसे पहले ही AndroidManifest . में डाला है

मैं उपयोगकर्ता से अनुमति के लिए कैसे पूछूं?

मैंने इस कोड का उपयोग करके कॉपी करने की कोशिश की जिसे मैंने उदाहरणों में से एक में लिया था

private void backupDatabase () throws IOException {
   String inFileName = "/data/data/com.gnd.example/databases/dados.db";
   File dbFile = new File (inFileName);
   FileInputStream fis = new FileInputStream (dbFile);

   String outFileName = Environment.getExternalStorageDirectory () + "/ example / backup / data.db";
   OutputStream output = new FileOutputStream (outFileName);
   byte [] buffer = new byte [1024];
   int length;
   while ((length = fis.read (buffer))> 0) {
       output.write (buffer, 0, length);
   }
   output.flush ();
   output.close ();
   fis.close ();

}

बटन इस तरह दिखता है:

   @Override
   public void onClick (View view) {
       try {
           backupDatabase ();
       } catch (IOException e1) {
           e1.printStackTrace ();
       }
   
});

जब मैं बटन दबाता हूं तो लॉग इन करें:

07/01 19:35:39: Launching app
$ adb shell am start -n "com.gnd.keepkey / com.gnd.keepkey.Telephone" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Client not ready yet..Waiting for process to come online
Waiting for process to come online
Connected to process 27724 on device motorola-moto_z2_play-0039635857
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
I / zygote: Do partial code cache collection, code = 20KB, data = 29KB
I / zygote: After code cache collection, code = 20KB, data = 29KB
    Increasing code cache capacity to 128KB
I / zygote: Do partial code cache collection, code = 20KB, data = 47KB
I / zygote: After code cache collection, code = 20KB, data = 47KB
    Increasing code cache capacity to 256KB
I / zygote: Compiler allocated 4MB to compile void android.widget.TextView. <Init> (android.content.Context, android.util.AttributeSet, int, int)
I / zygote: Full code cache collection, code = 120KB, data = 82KB
I / zygote: After code cache collection, code = 117KB, data = 62KB
I / zygote: Do partial code cache collection, code = 125KB, date = 79KB
I / zygote: After code cache collection, code = 125KB, data = 79KB
    Increasing code cache capacity to 512KB
W / System.err: java.io.FileNotFoundException: /storage/emulated/0/teste/dados.db (No such file or directory)
        at java.io.FileOutputStream.open0 (Native Method)
W / System.err: at java.io.FileOutputStream.open (FileOutputStream.java:287)
        at java.io.FileOutputStream. <init> (FileOutputStream.java:223)
        at java.io.FileOutputStream. <init> (FileOutputStream.java:110)
        at com.gnd.keepkey.funcoes.Exportar_Importar.backupDatabase (Export_Importar.java:87)
        at com.gnd.keepkey.funcoes.Exportar_Importar.access $ 000 (Export_Importar.java:42)
        at com.gnd.keepkey.funcoes.Export_Import $ 1.onClick (Export_Import.java:69)
W / System.err: at android.view.View.performClick (View.java:6259)
        at android.view.View $ PerformClick.run (View.java:24732)
        at android.os.Handler.handleCallback (Handler.java:789)
        at android.os.Handler.dispatchMessage (Handler.java:98)
        at android.os.Looper.loop (Looper.java:164)
        at android.app.ActivityThread.main (ActivityThread.java:6592)
        at java.lang.reflect.Method.invoke (Native Method)
W / System.err: at com.android.internal.os.Zygote $ MethodAndArgsCaller.run (Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:769)
2
Gabriel Delfino 2 जुलाई 2019, 01:08

2 जवाब

सबसे बढ़िया उत्तर

FileNotFoundException संभवत: teste निर्देशिका के कारण मौजूद नहीं है, शायद अनुमतियों के कारण।

का उपयोग करना: -

private void backupDatabase () throws IOException {
    String inFileName = "/data/data/com.gnd.example/databases/dados.db";
    File dbFile = new File (inFileName);
    FileInputStream fis = new FileInputStream (dbFile);

    String outFileName = Environment.getExternalStorageDirectory () + "/ example / backup / data.db";
    //<<<<<<<<<<< CODE ADDED >>>>>>>>>>
    File os = new File(outFileName); 
    if (!os.getParentFile().exists()) {
        os.getParentFile().mkdirs();
    }
    //<<<<<<<<<< END Of ADDED CODE >>>>>>>>>>
    OutputStream output = new FileOutputStream(os); //<<<<<<<<<< CHANGED
    byte [] buffer = new byte [1024];
    int length;
    while ((length = fis.read (buffer))> 0) {
        output.write (buffer, 0, length);
    }
    output.flush ();
    output.close ();
    fis.close ();
}

यदि वे मौजूद नहीं हैं तो निर्देशिकाएँ बनाएंगे (अनुमतियाँ सही हैं)

कार्य उदाहरण:-

निम्नलिखित एक कार्यशील ऐप है

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="aso.so56843045backup">
    <uses-permission android:name="android.permission.WRITE_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>
</manifest> 
  • <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> (पुराने उपकरणों के लिए) नोट करें

बाहरी स्टोरेज अनुमतियां।जावा

class ExternalStoragePermissions {

    public int API_VERSION = Build.VERSION.SDK_INT;
    private static final int REQUEST_EXTERNAL_STORAGE = 1;
    private static String[] PERMISSIONS_STORAGE = {

            //Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
    };
    public static final String THISCLASS = ExternalStoragePermissions.class.getSimpleName();
    private static final String LOGTAG = "SW_ESP";

    public ExternalStoragePermissions() {}
    // Note call this method
    public static void verifyStoragePermissions(Activity activity) {
        int permission = ActivityCompat.checkSelfPermission(
                activity,
                Manifest.permission.WRITE_EXTERNAL_STORAGE);

        if(permission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                    activity,
                    PERMISSIONS_STORAGE,
                    REQUEST_EXTERNAL_STORAGE
            );
        }
    }
}
  • यदि अनुमति नहीं दी गई है तो निर्देशिका नहीं बनाई जा सकती जिसके परिणामस्वरूप FileNotFoundException हो सकता है।

डीबी हेल्पर.जावा

public class DBHelper extends SQLiteOpenHelper {

    public static final String DBNAME = "dados.db";
    public static final int DBVERSION = 1;

    public DBHelper(Context context) {
        super(context, DBNAME, null, DBVERSION);
        this.getWritableDatabase();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

    }

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

    }
}
  • एक बहुत ही बुनियादी खाली डेटाबेस (अपवाद android_metadata तालिका), बैकअप की जांच करने के लिए पर्याप्त है।

मुख्य गतिविधि.जावा

public class MainActivity extends AppCompatActivity {

    DBHelper mDBHlpr;
    Button mBackup;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBackup = this.findViewById(R.id.backup);
        mBackup.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDBHlpr.close();
                try {
                    backupDatabase();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
        ExternalStoragePermissions.verifyStoragePermissions(this);
        mDBHlpr = new DBHelper(this);
    }

    private void backupDatabase () throws IOException {
        FileInputStream fis = new FileInputStream (this.getDatabasePath("dados.db").getPath());
        String outFileName = Environment.getExternalStorageDirectory () + "/example/backup/" + String.valueOf(System.currentTimeMillis()) + "data.db";
        Log.d("OSFILEPATH",outFileName);
        File os = new File(outFileName);
        if (!os.getParentFile().exists()) {
            os.getParentFile().mkdirs();
        }
        OutputStream output = new FileOutputStream(os);
        byte [] buffer = new byte [1024];
        int length;
        while ((length = fis.read (buffer))> 0) {
            output.write (buffer, 0, length);
        }
        output.flush ();
        output.close ();
        fis.close ();
    }
}

टिप्पणियाँ

  • जब पहली बार स्थापित करने के बाद बाद के उपकरणों के लिए अनुमति का अनुरोध किया जाएगा (अनुमति पर क्लिक करें)।

  • बैकअप को टाइमस्टैम्प के साथ नामित किया गया है ताकि कई बैकअप मौजूद हो सकें।

  • डेटाबेस बंद है, (यह एंड्रॉइड पाई + के साथ सामना करना चाहिए, जहां डिफ़ॉल्ट वाल मोड है, क्लोज को खाली (परिवर्तनों को प्रतिबद्ध) -वाल और -एसएचएम फाइलों को खाली करना चाहिए, इस प्रकार अतिरिक्त फाइलों का बैकअप लेने की आवश्यकता को नकारना चाहिए)।

नतीजा

enter image description here

1
MikeT 2 जुलाई 2019, 02:33

आपके दुर्घटना के संबंध में:

  • आपने निर्देशिका नहीं बनाई है, कम से कम अपने कोड के माध्यम से नहीं। अपनी इच्छित निर्देशिका की ओर इशारा करते हुए एक File ऑब्जेक्ट बनाएं, फिर उस ऑब्जेक्ट पर mkdirs() पर कॉल करें।

  • हो सकता है कि आपके पास WRITE_EXTERNAL_STORAGE अनुमति न हो, जिसमें रनटाइम पर अनुरोध करना भी शामिल है। देखें https://developer.android.com/training/permissions/requesting

यहां अन्य समस्याओं में शामिल हैं:

  • आपके पास अपने अनुरोधित स्थान पर लिखने की क्षमता नहीं होगी Android Q में (डिफ़ॉल्ट रूप से) और Android R (सभी ऐप्स के लिए) में। मेरा सुझाव है कि आप getExternalFilesDir() (Context पर पाए गए) को लिखें या स्टोरेज एक्सेस फ्रेमवर्क का उपयोग करें।

  • आप मुख्य एप्लिकेशन थ्रेड पर डिस्क I/O कर रहे हैं। I/O होने के दौरान यह आपके UI को फ्रीज कर देगा। उपयोगकर्ता सोच सकते हैं कि आपका ऐप टूट गया है। इसे संबोधित करने के कई तरीके हैं, हालांकि जेटपैक दृष्टिकोण ViewModel और LiveData का उपयोग करना होगा।

  • आप अपनी फ़ाइल को MediaStore द्वारा अनुक्रमित करने की व्यवस्था नहीं कर रहे हैं, इसलिए उपयोगकर्ता इसे अपने डेस्कटॉप फ़ाइल प्रबंधक में नहीं देख पाएगा। फ़ाइल को अनुक्रमित करने के लिए MediaScannerConnection.scanFile() का प्रयोग करें।

  • "/data/data/com.gnd.example/databases/dados.db" कई Android उपकरणों पर गलत पथ है। हार्डकोड पथ कभी नहीं। अपने डेटाबेस का पथ प्राप्त करने के लिए getDatabasePath() का उपयोग Context पर करें।

यह नमूना Java ऐप दिखाता है कि यह कितना है डेटाबेस बैकअप समाधान के बजाय टेक्स्ट एडिटर के संदर्भ में किया जाता है।

सामान्य तौर पर, मेरा सुझाव है कि आप इस प्रोजेक्ट को कुछ समय के लिए अलग रख दें और Android ऐप डेवलपमेंट पर एक अप-टू-डेट किताब पढ़ें। जिन समस्याओं का मैं यहां उल्लेख कर रहा हूं उनमें से अधिकांश उन विषयों पर हैं जिन्हें एंड्रॉइड पर एक अच्छी किताब में शामिल किया जाएगा।

1
CommonsWare 2 जुलाई 2019, 02:00