Skip to content

Commit

Permalink
位置情報を追加する際に一時ファイルがMesiaScannerに使われないようにした
Browse files Browse the repository at this point in the history
  • Loading branch information
tateisu committed Mar 24, 2017
1 parent fff78b7 commit 02ff94b
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public class DownloadService extends Service{

NotificationManager mNotificationManager;
WorkerTracker worker_tracker;
MediaScannerTracker media_tracker;

@Override public void onCreate(){
super.onCreate();
Expand Down Expand Up @@ -95,6 +96,8 @@ public class DownloadService extends Service{
}
} );

media_tracker = new MediaScannerTracker(this,log);

wifi_tracker = new NetworkTracker( this, log, new NetworkTracker.Callback(){
@Override public void onConnectionEvent( boolean is_connected ,String cause){
if( is_connected ){
Expand All @@ -115,7 +118,11 @@ public class DownloadService extends Service{

worker_tracker.dispose();


media_tracker.dispose();

location_tracker.dispose();

wifi_tracker.dispose();

if( mGoogleApiClient.isConnected() ){
Expand Down
97 changes: 64 additions & 33 deletions app/src/main/java/jp/juggler/fadownloader/DownloadWorker.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Location;
import android.media.MediaScannerConnection;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
Expand All @@ -18,12 +17,15 @@
import android.support.annotation.NonNull;
import android.text.TextUtils;

import org.apache.commons.io.IOUtils;

import it.sephiroth.android.library.exif2.ExifInterface;
import jp.juggler.fadownloader.targets.FlashAir;
import jp.juggler.fadownloader.targets.PentaxKP;
import jp.juggler.fadownloader.targets.PqiAirCard;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
Expand Down Expand Up @@ -233,18 +235,29 @@ public static class ErrorAndMessage{

@NonNull public ErrorAndMessage updateFileLocation( final Location location, ScanItem item ){
ErrorAndMessage em = null;
boolean bDeleteTempFile = false;
LocalFile local_temp =null;
try{
LocalFile file = item.local_file;

LocalFile tmp_path = new LocalFile( file.getParent(), "tmp-" + currentThread().getId() + "-" + android.os.Process.myPid() + "-" + file.getName() );
if( ! tmp_path.prepareFile( log, true ,item.mime_type) ){
return new ErrorAndMessage( true, "file creation failed." );
LocalFile local_file = item.local_file;
LocalFile local_parent = local_file.getParent();

// MediaScannerが一時ファイルを勝手にスキャンしてしまう
// DocumentFile はMIME TYPE に合わせてファイル拡張子を変えてしまう
// なので、一時ファイルの拡張子とMIME TYPE は無害なものに設定するしかない
String tmp_name = local_file.getName()+ ".tmp-" + currentThread().getId() + "-" + android.os.Process.myPid();
local_temp = new LocalFile( local_parent, tmp_name );

if( ! local_temp.prepareFile( log,true,Utils.MIME_TYPE_APPLICATION_OCTET_STREAM )){
log.e("prepareFile() failed.");
return new ErrorAndMessage( false,"prepareFile() failed." );
}

bDeleteTempFile = true;

try{
OutputStream os = tmp_path.openOutputStream( service );
OutputStream os = local_temp.openOutputStream( service );
try{
InputStream is = file.openInputStream( service );
InputStream is = item.local_file.openInputStream( service );
try{
ExifInterface.modifyExifTag( is, ExifInterface.Options.OPTION_ALL
, os, new ExifInterface.ModifyExifTagCallback(){
Expand Down Expand Up @@ -284,30 +297,60 @@ public static class ErrorAndMessage{
em = new ErrorAndMessage( true, LogWriter.formatError( ex, "exif mangling failed." ) );
}

if( em != null ){
tmp_path.delete();
return em;
}
if( em != null ) return em;

// 更新後の方がファイルが小さいことがあるのか?
if( tmp_path.length( log ) < file.length( log ) ){
if( local_temp.length(log) < local_file.length(log) ){
log.e( "EXIF付与したファイルの方が小さい!付与前後のファイルを残しておく" );
// この場合両方のファイルを残しておく
bDeleteTempFile = false;
return new ErrorAndMessage( true, "EXIF付与したファイルの方が小さい" );
}

if( ! file.delete() || ! tmp_path.renameTo( file.getName() ) ){
log.e( "EXIF追加後のファイル操作に失敗" );
return new ErrorAndMessage( true, "EXIF追加後のファイル操作に失敗" );
// DocumentFile にはsetMimeType が存在しないから
// 一時ファイルをrename してもMIME TYPEを補正できない
// 仕方ないので元のファイルを上書きする
// 更新後に再度MediaScannerでスキャンし直すのでなんとかなるだろう。。。

try{
InputStream is = local_temp.openInputStream( service );
try{
OutputStream os = local_file.openOutputStream( service );
try{
IOUtils.copy( is, os );
}finally{
try{
os.close();
}catch( Throwable ignored ){
}
}
}finally{
try{
is.close();
}catch( Throwable ignored ){
}
}
}catch(Throwable ex){
ex.printStackTrace();
log.e( ex, "file copy failed." );
return new ErrorAndMessage( false, "file copy failed." );
}

log.i( "%s に位置情報を付与しました", file.getName() );
log.i( "%s に位置情報を付与しました", local_file.getName() );
return new ErrorAndMessage( false, "embedded" );

}catch( Throwable ex ){
ex.printStackTrace();
log.e( ex, "exif mangling failed." );
return new ErrorAndMessage( true, LogWriter.formatError( ex, "exif mangling failed." ) );
}finally{
if( local_temp != null && bDeleteTempFile ){
try{
//noinspection ResultOfMethodCallIgnored
local_temp.delete();
}catch( Throwable ignored ){
}
}
}
}

Expand Down Expand Up @@ -381,6 +424,7 @@ public void afterDownload( long time_start, byte[] data, ScanItem item ){

Location location = callback.getLocation();
if( location != null && DownloadWorker.reJPEG.matcher( item.name ).find() ){

DownloadWorker.ErrorAndMessage em = updateFileLocation( location, item );
if( item.time > 0L ) item.local_file.setFileTime( service, log, item.time );

Expand All @@ -391,7 +435,8 @@ public void afterDownload( long time_start, byte[] data, ScanItem item ){
, "GeoTagging: " + em.message
);

setMediaScanner( item );
service.media_tracker.addFile( item.local_file.getFile(service,log),item.mime_type );

}else{
if( item.time > 0L ) item.local_file.setFileTime( service, log, item.time );

Expand All @@ -401,26 +446,12 @@ public void afterDownload( long time_start, byte[] data, ScanItem item ){
, DownloadRecord.STATE_COMPLETED
, "OK"
);
setMediaScanner( item );

service.media_tracker.addFile( item.local_file.getFile(service,log),item.mime_type );
}
}

}

private void setMediaScanner( ScanItem item ){
if( item.mime_type != null ){
File file = item.local_file.getFile(service,log);
if( file != null ){
MediaScannerConnection.scanFile(
service
,new String[]{ file.getAbsolutePath() }
,new String[]{ item.mime_type}
,null
);
}
}
}

public void onFileScanStart(){
job_queue = new ScanItem.Queue();
Expand Down
11 changes: 11 additions & 0 deletions app/src/main/java/jp/juggler/fadownloader/LocalFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,17 @@ public long length( LogWriter log ){
return 0L;
}

public boolean isFile( LogWriter log ){
if( prepareFile( log, false,null ) ){
if( Build.VERSION.SDK_INT >= DOCUMENT_FILE_VERSION ){
return ( (DocumentFile) local_file ).isFile();
}else{
return ( (File) local_file ).isFile();
}
}
return false;
}

public OutputStream openOutputStream( Context context ) throws FileNotFoundException{
if( Build.VERSION.SDK_INT >= DOCUMENT_FILE_VERSION ){
Uri file_uri = ( (DocumentFile) local_file ).getUri();
Expand Down
97 changes: 97 additions & 0 deletions app/src/main/java/jp/juggler/fadownloader/MediaScannerTracker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package jp.juggler.fadownloader;

import android.content.Context;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Handler;
import android.os.SystemClock;
import android.text.TextUtils;

import java.io.File;
import java.util.concurrent.ConcurrentLinkedQueue;

public class MediaScannerTracker implements MediaScannerConnection.MediaScannerConnectionClient{

@Override public void onMediaScannerConnected(){
handler.post( queue_reader );
}

@Override public void onScanCompleted( String path, Uri uri ){
}

final Context context;
final LogWriter log;
final MediaScannerConnection conn;
final Handler handler;
long last_connect_start;

volatile boolean is_dispose = false;

void dispose(){
is_dispose = true;
}

public MediaScannerTracker( Context context, LogWriter log ){
this.context = context;
this.log = log;
this.conn = new MediaScannerConnection( context, this );
this.handler = new Handler();
prepareConnection();
}

static class Item{

String path;
String mime_type;
}

final ConcurrentLinkedQueue<Item> queue = new ConcurrentLinkedQueue<>();

public void addFile( File file, String mime_type ){
if( file == null || ! file.isFile() ) return;
if( TextUtils.isEmpty( mime_type ) ) return;
Item item = new Item();
item.path = file.getAbsolutePath();
item.mime_type = mime_type;
queue.add( item );
handler.post( queue_reader );
}

private boolean prepareConnection(){
if( conn.isConnected() ) return true;

long now = SystemClock.elapsedRealtime();
if( now - last_connect_start >= 5000L ){
last_connect_start = now;
conn.connect();
}
return false;
}

final Runnable queue_reader = new Runnable(){
@Override public void run(){
handler.removeCallbacks( queue_reader );
for( ; ; ){

Item item = queue.peek();

if( item == null ){
if( is_dispose ){
conn.disconnect();
}
break;
}

if( ! prepareConnection() ){
handler.postDelayed( queue_reader, 1000L );
break;
}

conn.scanFile( item.path, item.mime_type );

queue.poll();
}
}
};

}
4 changes: 3 additions & 1 deletion app/src/main/java/jp/juggler/fadownloader/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,8 @@ static String findMimeTypeEx(String ext){
}
}

public static final String MIME_TYPE_APPLICATION_OCTET_STREAM = "application/octet-stream";

public static String getMimeType( LogWriter log, String src ){
String ext = MimeTypeMap.getFileExtensionFromUrl( src );
if( !TextUtils.isEmpty( ext ) ){
Expand All @@ -513,7 +515,7 @@ public static String getMimeType( LogWriter log, String src ){

if( mime_type == null && log != null ) log.w("getMimeType(): unknown file extension '%s'",ext);
}
return "application/octet-stream";
return MIME_TYPE_APPLICATION_OCTET_STREAM;
}

static class FileInfo{
Expand Down

0 comments on commit 02ff94b

Please sign in to comment.