質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

2回答

7851閲覧

Androidにおけるデータベースファイルのエクスポート・インポート

birdbird

総合スコア20

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2017/04/30 05:34

編集2017/05/02 06:19

###目的
Android端末内にあるデータベースファイルを、PCとUSB接続することでバックアップをとれるようにしたい
また、後々は、逆にインポートによる読込もしたい

###実現したいこと
Androidでデータベースを使用したアプリを開発しています。
データベースファイルを外部ストレージにコピーしたいです。

なお、データベースファイルの存在は、ターミナルから確認済みです。
参考:端末にあるデータベースの中身を見る方法

###該当のソースコード
SQLiteOpenHelperを継承したクラスは以下のようにしており、Activityクラスからのデータ操作は何ら問題なく行えております。
このようにして作成したデータベースファイルは、どのようにして外部ストレージにコピーすればよいのか教えていただきたいです。
よろしくお願いいたします。

Java

1public class DBhelper extends SQLiteOpenHelper { 2 static final private String DBNAME = "sample.sqlite"; 3 static final private int VERSION = 1; 4 5 public DBhelper(Context context) { 6 super(context, DBNAME, null, VERSION); 7 } 8 9 @Override 10 public void onOpen(SQLiteDatabase db) { 11 super.onOpen(db); 12 } 13 14 @Override 15 public void onCreate(SQLiteDatabase db) { 16 db.execSQL("CREATE TABLE sample_test (" + 17 "_id INTEGER PRIMARY KEY, " + 18 "testTEXT TEXT)"); 19 } 20 21 @Override 22 public void onUpgrade(SQLiteDatabase db, int old_v, int new_v) { 23 db.execSQL("DROP TABLE IF EXISTS sample_test"); 24 onCreate(db); 25 } 26}

また、マニフェストファイルにパーミッションの記述はしております。
###試したこと
参考にさせていただいたサイトを数個挙げます。
AndroidのデータベースファイルをSDカードにコピーする方法
→「FAILED_TO_CREATE_PATH_ON_SD」と出てきてしまう
SDカードにファイルを保存する
→データベースファイルについてではない
SQLiteのDBファイルをSDにコピー
→「フォルダの作成に失敗しました」と出てきてしまう。mkdir()が成功していない模様。
Androidでmkdir()を実行してみる
→ここを参考に、「/storage/sdcard/Android/data/{プロジェクトパッケージ}/"testtest"」としても上手くいかず。

###補足情報(言語/FW/ツール等のバージョンなど)
AndroidStudio 2.3.1
エミュレータのAPI 24

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

ストレージ権限ですがAndroid6.0以降からはユーザー側で権限付与(Runtime Permission)も必要なっています。
確認している環境API24ですので、上記に当たる場合はそちらも付与する必要があります。

本題のファイルをSDカード(外部ストレージ)にコピーする方法についてですが。
LoliPop以降は基本的にStorage Access Frameworkでファイル操作をする必要があります。
面倒な仕様ですので以下の公式をご参照ください。
ストレージ アクセス フレームワーク | Android Developers

補足ですが、外部ストレージ内のファイルについてIntentを利用したファイル共有等を行う場合、MarshmallowまでならFileクラスを利用したりしても動きますが、Nougat以降ですとStorage Access Frameworkに則った方法でUriを利用しないと動きません(確か例外がでたはず)のでご注意を。

投稿2017/04/30 14:30

uniko

総合スコア448

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

birdbird

2017/04/30 18:07 編集

ご回答ありがとうございます。 情報の記載不足で申し訳ないのですが、この度はAPI16にも対応する必要があるアプリとなっております。 その際に、以下のように書いてみたところ、API16の実機をPCにusb接続してtesttestファイルおよびtest.dbを確認することができました。 しかし、API24のエミュレータにおいて、デバイスモニターからtesttestファイル及びtest.dbファイルを見つけることができませんでした。 「API16〜24あたりを網羅して今回の目的を達成する最良の策」を教えていただければ幸いです。 よろしくお願いいたします。 //ActivityのonCreate内に以下を記述 ```Java db = helper.getWritableDatabase(); String sd_dir = Environment.getExternalStorageDirectory().getPath(); String sd_stt = Environment.getExternalStorageState(); String db_file = db.getPath(); boolean b; b=sd_stt.equals(Environment.MEDIA_MOUNTED); if (b == false){ return; } File f = new File(sd_dir + "/testtest"); b=f.exists(); if (b==false){ b=f.mkdir(); if (b==false){ return; } } filecopy(db_file , sd_dir+"/test.db"); ``` //filecopy関数 ```Java private void filecopy(String file_src,String file_dist) { FileOutputStream fos; FileInputStream fis; File fi =new File(file_src); File fo=new File(file_dist); try{ fis = new FileInputStream(fi); FileChannel chi = fis.getChannel(); fos=new FileOutputStream(fo); FileChannel cho = fos.getChannel(); chi.transferTo(0,chi.size(),cho); chi.close(); cho.close(); }catch (FileNotFoundException e){ Toast.makeText(this, "a",Toast.LENGTH_LONG).show(); }catch (IOException e){ } } ```
birdbird

2017/04/30 17:41

【追記】 private DBhelper helper = null; は宣言済みです。
uniko

2017/04/30 23:22

Build.VERSION.SDK_INTでバージョンで処理を分けてください。なお4.4は仕様上SDは無理かと。それ以前はFileクラス(参考にしているブログのようなやり方)で書き込み可能。
uniko

2017/04/30 23:25

記載しているソースについての話ですがエラーがでているのでしょうか? 回答にも記載していますが、ユーザー側で権限付与をしていますか?
birdbird

2017/05/01 04:02

バージョンで処理を分ける必要があるのですね。 ソースについてですが、API24のエミュレータにおいてエラーは出ませんが、SDカードにファイルを作成 することが成功していません。 ので、4.4以前は上記のようなコードでにして、4.4以降は教えていただいたフレームワークを使用して、バージョンで処理を分けて完成させたいと思います。 初心者の質問に回答して下さり、本当にありがとうございました。 最後に当質問についてまとめておきます。 問題:SDカードにファイルを作成、コピーできない 原因:4.4以前と以降とで外部ストレージの仕様が異なっていることを理解できていなかった。    ゆえに、エミュレータ(API24)では失敗するのに、実機(API16)では成功するという状況になっていた。 解決策:バージョンで処理を分け、4.4以降はStorage Access Frameworkを利用すべきとの指摘を頂いた。
uniko

2017/05/01 05:21 編集

一応記載しておきます。 外部ストレージの仕様はOS、端末毎に違います。Environment.getExternalStorageDirectory() = 外部SDカードが保障されてるわけではありませんので注意してください。ちゃんと外部ストレージが返るのは2.x系までくらいです。4.0以降であれば内部ストレージが基本返されるかと思います。 そのため私が問題を勘違いしていたら申し訳ありませんが、Environment.getExternalStorageDirectory()で取得したパスを利用したいという事が問題だったのであればStorage Access Frameworkを使う必要はないかと(内部ストレージのため)。 ファイルが作られないのはエラーが無いと言う事ですので、filecopy関数まで処理が到達しているかも見た方がいいかと思います(途中でreturnされてるやも)。
birdbird

2017/05/01 06:20

unikoさんのおっしゃる通り「外部ストレージを使用」して、PCにバックアップをとりたいというのが目的です。 つまりは、現在API16の実機(Android4.1)でusbストレージに内部ストレージのデータ(私のアプリのデータベースファイル)をコピーすることに成功できているのは、Environment.getExternalStorageDirectory()で取得したパスが外部ストレージのパスと一致しているからということでしょうか。 ただし、Environment.getExternalStorageDirectory()が外部ストレージを返すとは限らない(特に4.4以降)ので、Android4.4以降の場合はStorage Access Frameworkで外部ストレージへのアクセスを実装すべきということでしょうか。 長々とすみません。 よろしくお願いいたします。
uniko

2017/05/01 06:57

ご確認の端末で外部ストレージの中に保存できているのであればそうかと思われます。なお、getExternalStorageDirectoryは外部というわけではなく共有可能なストレージになりますのでAPIのレベルにこだわらないでください。場合によって違います。 APIのリファレンスもお読みください。 https://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory() そのためAPI24で書き込めないと言っている端末は別の問題(権限が付与されていない等)で書き込めないのではと思っています。 *この権限が付与されていないというのはRuntime Permissionの事でAndroidManifest.xmlに記載する権限とは別のお話です。 なお、外部ストレージに対して確実なパスを取得するようなAPIは提供されていないというのが現状で様々な方法を駆使してパスを取得する他ありません。そして4.4以降はパスが取得できたとしても外部ストレージの場合は書き込み権限があっても書き込めません。 ただしStorage Access Frameworkからの操作であれば外部ストレージであっても書き込みが可能になります。なので外部ストレージに保存をしたいと言う場合はStorage Access Framework利用するといった形になります。 ストレージ関連についてまとめたりしてくださっているブログもいくつかあるようですので参照するといいかと思います。 https://akira-watson.com/android/sdcard_path.html http://blog.lciel.jp/blog/2014/02/08/android-about-storage/ *古い記事は4.x系を扱う際の参考にのみ見るといいかと思います。
birdbird

2017/05/01 12:45

大変詳しくありがとうございます! APIリファレンスを確実に読み、その上で紹介していただいたブログにも目を通したいと思います。 この度は長らく、そして丁寧にお付き合いしていただきありがとうございました。
guest

0

マニフェストファイルにパーミッションの記述をしましたか?忘れがちですが重要です。

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

http://techbooster.jpn.org/andriod/application/1126/

投稿2017/04/30 07:42

TakeoAsai

総合スコア880

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

birdbird

2017/04/30 07:49

マニフェストファイルにパーミッションの記述はしてあるのですが、上手くいきませんでした。 データベースファイルをSDカードにコピーするプロセスの過程に問題があるのではないかと思っています。
TakeoAsai

2017/04/30 08:07

私もコピーするところに原因があると思い、Permissionかと思ったのですがお力になれず申し訳ありません
birdbird

2017/04/30 08:14

私の記載不足もあり、申し訳ありません。またあ、読んで下さり、そして回答をして下さり本当にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問