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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Android Studio

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

Q&A

解決済

1回答

1773閲覧

OneDriveAPIでの複数ファイルの非同期ダウンロードを制御したい

rafiene3249

総合スコア53

Android Studio

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

0グッド

0クリップ

投稿2017/09/11 05:14

編集2017/09/11 05:20

いつもお世話になっております。OneDriveAPIでの複数ファイルの非同期ダウンロードを制御したいのですが、
上手く行かず困っていて皆様のお知恵をお借りしたい所存です。

latch.awaitをしなければ複数ファイルの非同期ダウンロード自体は出来るのですが、
該当月の全ファイルをダウンロードし終わった時に表示を更新する処理を行いたいので
latchを使い全ファイルをダウンロードし終わったのを監視しようとした所、
ダウンロードをせずにlatch.awaitが先に働いてしまい何も出来ない状態になります。

###1:latchを組み込む前のログ
D/デバッグ: initializeControl が呼ばれました
D/デバッグ: 20170929.txt を削除しました
D/デバッグ: DrawMainActivity.onPostExecute
D/デバッグ: DrawMainActivity.sendBroadcast
D/デバッグ: BroadcastReceiver : mDrawReceiver が呼ばれました
D/デバッグ: DrawMonthlyCalendar : dayTextList.size()=42
D/デバッグ: 20170929.txt ちゃん、見~つけた
D/デバッグ: 20170929.txt(main_data) をダウンロードしています...
D/デバッグ: 20170929.txt をダウンロードしました

ダウンロードより先に描画が走っています
これをなんとかする為にlatchを組み込んだのですが

###2:下記のコードを実機にて実行した時のログ
D/デバッグ: initializeControl が呼ばれました
D/デバッグ: 全ファイルのダウンロード待ちに入ります

ダウンロードを始める前に待ちに入ってしまい、そのまま動かなくなります。
どの様に修正すればlatchで全ファイルのダウンロードを監視出来るかご教授頂けると助かります。

MainActivity.java(抜粋) public void hoge(int offset) { //カレンダーテーブル作成 CalendarInfo cl = new CalendarInfo(currentYear, currentMonth); final CountDownLatch latch = new CountDownLatch(cl.lastDate); ← lastDateには月の末日が帰ってきます Hoge hoge2 = new Hoge(); hoge2.setmLatch(latch); hoge2.setmYear(this.currentYear); hoge2.setmMonth(this.currentMonth); hoge2.run(); }
Hoge.java(一部省略) public class Hoge { private static CountDownLatch mLatch; private static int mYear; private static int mMonth; private static int row; private static int col; public void run() { final CountDownLatch latch = new CountDownLatch(42); //カレンダーテーブル作成 final CalendarInfo cl = new CalendarInfo(Hoge.mYear, Hoge.mMonth); row = 0; col = 0; for (int i = 0; i < 42; i++) { if (cl.calendarMatrix[row][col] != 0) { new Thread(new Runnable() { @Override public void run() { try { final App app = (App) getsApplication(); String DataFileName = String.format("%04d%02d%02d.txt", Hoge.mYear, Hoge.mMonth, cl.calendarMatrix[row][col]); // OneDriveからスケジュールファイルを取得する前にスケジュールファイルを削除する File file = new File(getsApplication().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), DataFileName); if (file.exists()) { file.delete(); Log.d("デバッグ", String.format("%s を削除しました", DataFileName)); } final DownloadFiles schedule = new DownloadFiles(); // DownloadTaskを実行する // 引数がdoInBackground()メソッドに渡される schedule.setCountDownLatch(Hoge.mLatch); schedule.execute(DataFileName, "main_data", null, null); } catch (NullPointerException e) { e.printStackTrace(); } } }).start(); } col += 1; if (col == 7) { row += 1; col = 0; } } new Thread(new Runnable() { @Override public void run() { try { // 全ファイルのダウンロード待ち Log.d("デバッグ", "全ファイルのダウンロード待ちに入ります"); mLatch.await(); Log.d("デバッグ", "全ファイルのダウンロード待ちから抜けました"); } catch(InterruptedException e) { } } }).start(); } }

DownloadFiles.java

1DownloadFiles.java(一部省略) 2 3public final class DownloadFiles extends AsyncTask<String,Void,Boolean> { 4 5 private static CountDownLatch mLatch; 6 7 public static void setCountDownLatch(CountDownLatch latch ) { 8 mLatch = latch; 9 } 10 11 @Override 12 protected Boolean doInBackground(final String... param) { 13 String FileName = param[0]; 14 String Mode = param[1]; 15 download_file(FileName, Mode); 16 17 return true; 18 } 19 20 private void DownloadWait(String FileName, String Mode) { 21 Log.d("デバッグ", String.format("%s(%s) をダウンロードしています...", FileName, Mode) ); 22 23 try { 24 while(true) { 25 File file = new File(getsApplication().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), FileName ); 26 if( file.exists() && file.length() > 0 ) { 27 final App app = (App)getsApplication(); 28 if( Mode.equals("set_staff") ) { 29 //略 30 } 31 else if( Mode.equals("sub_staff") ) { 32 //略 33 } 34 else if( Mode.equals("sub_data") ) { 35 //略 36 } 37 else if( Mode.equals("main_data") ) { 38 Log.d("デバッグ", String.format("%s をダウンロードしました", FileName) ); 39 // ダウンロードしたファイルの読み込みはしない 40 // 画面の更新はしない 41 mLatch.countDown(); 42 Log.d("デバッグ", String.format("latch count:%d", mLatch.getCount() )); 43 } 44 break; 45 } 46 Thread.sleep(100); 47 } 48 } catch (InterruptedException e) { 49 Log.d("デバッグ", String.format("%s", e.getMessage() ) ); 50 } 51 } 52 53 private ICallback<Item> getDownloadCallback(final App context, final String filename, final String mode ) { 54 return new DefaultCallback<Item>(context) { 55 @Override 56 public void success(final Item item) { 57 if (item.children == null || item.children.getCurrentPage().isEmpty()) { 58 Log.d("デバッグ","OneDrive 空なんですけど・・"); 59 } else { 60 boolean findflag; 61 findflag = false; 62 for (final Item childItem : item.children.getCurrentPage()) { 63 if( childItem.name.equals(filename) ) { 64 findflag = true; 65 Log.d("デバッグ", String.format("%s ちゃん、見~つけた", filename)); 66 final DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); 67 final String downloadUrl = childItem.getRawObject().get("@content.downloadUrl").getAsString(); 68 final DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downloadUrl)); 69 request.setTitle(childItem.name); 70 Resources res = context.getResources(); 71 request.setDescription(res.getString(R.string.file_from_onedrive)); 72 request.allowScanningByMediaScanner(); 73 if (childItem.file != null) { 74 request.setMimeType(childItem.file.mimeType); 75 } 76 request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); 77 78 File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), filename); 79 request.setDestinationUri(Uri.fromFile(file)); 80 81 downloadManager.enqueue(request); 82 //toast( res.getString(R.string.starting_download_message), Toast.LENGTH_SHORT ); 83 84 DownloadWait(filename, mode); 85 86 break; 87 } 88 } 89 if ( findflag == false ) { 90 Log.d("デバッグ", String.format("%s ちゃん、居ませんでした", filename)); 91 mLatch.countDown(); 92 Log.d("デバッグ", String.format("latch count:%d", mLatch.getCount() )); 93 } 94 } 95 } 96 97 @Override 98 public void failure(final ClientException error) { 99 Log.d("デバッグ","Itemが見つかんねぇ"); 100 } 101 }; 102 } 103 104 private void download_file( String filename, String mode ) { 105 final App app = (App)getsApplication(); 106 107 try { 108 final IOneDriveClient oneDriveClient = getOneDriveClient(); 109 final ICallback<Item> itemCallback = getDownloadCallback(app, filename, mode); 110 111 final String itemId; 112 itemId = "root"; 113 114 oneDriveClient 115 .getDrive() 116 .getItems(itemId) 117 .buildRequest() 118 .expand(getExpansionOptions(oneDriveClient)) 119 .get(itemCallback); 120 } catch ( RuntimeException e ) { 121 Log.d("デバッグ", String.format("%s", e.getMessage()) ); 122 } 123 } 124}

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

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

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

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

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

guest

回答1

0

自己解決

結論から言うと、UIスレッドでfor文で時間のかかる非同期処理を行うスレッドを
複数個作成しようとしたのがそもそも間違いでした。

UIスレッドでスレッドを作成し、そのスレッド内でfor文を回し時間のかかる非同期処理を
複数回呼ぶよう変更した所、思った様な挙動が得られました。

尚、確認作業を単純化する為に元のソースを弄らずに、
スレッドとラッチの動作確認の為の新規プロジェクトを作成し、
今回上手く動作しなかったプロジェクトのモデルケースを作成。
時間のかかる非同期処理はsleep()で擬似的に再現して動作を確認し、
元のプロジェクトと同様の挙動をする事を確認出来たので、
その後上記修正を行い思った様な挙動が得られた為、
元のソースに変更内容を反映して最終的な動作確認を行い修正完了となりました。

以下はモデルケースのソースです。

Hoje.java(抜粋) public class Hoge { public void run() { Log.d("デバッグ", String.format("Hoge() latch Count : %02d", latch.getCount()) ); new Thread(new Runnable() { @Override public void run() { try { Log.d("デバッグ", "スレッド呼び出し開始" ); for (int i = 0; i < 31; i++) { String DataFileName = String.format("%04d%02d%02d.txt", 2017, 9, i); DownHoge dh = new DownHoge(); dh.execute(DataFileName, null, null); } Log.d("デバッグ", "スレッド呼び出し終了" ); } catch (NullPointerException e) { Log.d("デバッグ", e.getMessage() ); } } }).start(); new Thread(new Runnable() { @Override public void run() { try { // 全ファイルのダウンロード待ち Log.d("デバッグ", "全ファイルのダウンロード待ちに入ります"); latch.await(); Log.d("デバッグ", "全ファイルのダウンロード待ちから抜けました"); } catch(InterruptedException e) { Log.d("デバッグ", e.getMessage() ); } } }).start(); } }

投稿2017/09/14 04:16

rafiene3249

総合スコア53

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問