1 package net.osdn.gokigen.pkremote.playback.detail;
4 import android.app.Activity;
5 import android.graphics.Bitmap;
6 import android.os.Bundle;
7 import android.util.Log;
8 import android.view.LayoutInflater;
9 import android.view.Menu;
10 import android.view.MenuInflater;
11 import android.view.MenuItem;
12 import android.view.View;
13 import android.view.ViewGroup;
14 import android.widget.ImageView;
16 import net.osdn.gokigen.pkremote.R;
17 import net.osdn.gokigen.pkremote.camera.interfaces.control.ICameraRunMode;
18 import net.osdn.gokigen.pkremote.camera.interfaces.playback.ICameraContent;
19 import net.osdn.gokigen.pkremote.camera.interfaces.playback.ICameraFileInfo;
20 import net.osdn.gokigen.pkremote.camera.interfaces.playback.IContentInfoCallback;
21 import net.osdn.gokigen.pkremote.camera.interfaces.playback.IDownloadThumbnailImageCallback;
22 import net.osdn.gokigen.pkremote.camera.interfaces.playback.IPlaybackControl;
24 import java.text.SimpleDateFormat;
25 import java.util.Date;
26 import java.util.List;
27 import java.util.Locale;
30 import androidx.annotation.NonNull;
31 import androidx.appcompat.app.ActionBar;
32 import androidx.appcompat.app.AlertDialog;
33 import androidx.appcompat.app.AppCompatActivity;
34 import androidx.collection.LruCache;
35 import androidx.fragment.app.Fragment;
36 import androidx.fragment.app.FragmentActivity;
37 import androidx.viewpager.widget.PagerAdapter;
38 import androidx.viewpager.widget.ViewPager;
40 public class ImagePagerViewFragment extends Fragment
42 private final String TAG = this.toString();
43 private static final String JPEG_SUFFIX = ".JPG";
45 private IPlaybackControl playbackControl;
46 private ICameraRunMode runMode;
48 private List<CameraContentEx> contentList = null;
49 private int contentIndex = 0;
51 private LayoutInflater layoutInflater = null;
52 private ViewPager viewPager = null;
53 private LruCache<String, Bitmap> imageCache =null;
56 public static ImagePagerViewFragment newInstance(@NonNull IPlaybackControl playbackControl, @NonNull ICameraRunMode runMode, @NonNull List<CameraContentEx> contentList, int contentIndex)
58 ImagePagerViewFragment fragment = new ImagePagerViewFragment();
59 fragment.setInterface(playbackControl, runMode);
60 fragment.setContentList(contentList, contentIndex);
65 private void setInterface(@NonNull IPlaybackControl playbackControl, @NonNull ICameraRunMode runMode)
67 this.playbackControl = playbackControl;
68 this.runMode = runMode;
72 private void setContentList(@NonNull List<CameraContentEx> contentList, int contentIndex)
74 this.contentList = contentList;
75 this.contentIndex = contentIndex;
79 public void onCreate(Bundle savedInstanceState)
81 super.onCreate(savedInstanceState);
82 imageCache = new LruCache<>(7);
83 setHasOptionsMenu(true);
87 public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
89 layoutInflater = inflater;
90 View view = layoutInflater.inflate(R.layout.fragment_image_pager_view, container, false);
91 viewPager = view.findViewById(R.id.viewPager1);
92 viewPager.setAdapter(new ImagePagerAdapter());
93 viewPager.addOnPageChangeListener(new ImagePageChangeListener());
99 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
103 CameraContentEx info = contentList.get(contentIndex);
104 ICameraContent file = info.getFileInfo();
105 String path = file.getContentPath() + "/" + file.getContentName();
107 AppCompatActivity activity = (AppCompatActivity) getActivity();
108 if (activity != null)
110 ActionBar bar = activity.getSupportActionBar();
117 String lowerCasePath = path.toUpperCase();
118 if (lowerCasePath.endsWith(JPEG_SUFFIX))
122 inflater.inflate(R.menu.image_view_with_raw, menu);
123 MenuItem downloadMenuItem = menu.findItem(R.id.action_download_with_raw);
124 downloadMenuItem.setEnabled(true);
128 inflater.inflate(R.menu.image_view, menu);
129 MenuItem downloadMenuItem = menu.findItem(R.id.action_download);
130 downloadMenuItem.setEnabled(true);
135 inflater.inflate(R.menu.movie_view, menu);
136 MenuItem downloadMenuItem = menu.findItem(R.id.action_download_movie);
137 downloadMenuItem.setEnabled(true);
147 public boolean onOptionsItemSelected(MenuItem item)
149 boolean doDownload = false;
150 boolean getInformation = false;
151 boolean isSmallSize = false;
152 boolean isRaw = false;
153 if ((item.getItemId() == R.id.action_get_information)||(item.getItemId() == R.id.action_get_information_raw))
155 getInformation = true;
157 else if ((item.getItemId() == R.id.action_download_original_size)||(item.getItemId() == R.id.action_download_original_size_raw))
161 else if ((item.getItemId() == R.id.action_download_640x480)||(item.getItemId() == R.id.action_download_640x480_raw))
166 else if (item.getItemId() == R.id.action_download_original_movie)
170 else if (item.getItemId() == R.id.action_download_raw)
178 Thread thread = new Thread(new Runnable() {
182 showFileInformation((contentList.get(contentIndex)).getFileInfo());
200 saveImageWithDialog(isRaw, isSmallSize);
207 return (super.onOptionsItemSelected(item));
214 private void showFileInformation(final ICameraContent contentInfo)
216 if (playbackControl != null)
218 playbackControl.getContentInfo(contentInfo.getContentPath(), contentInfo.getContentName(), new IContentInfoCallback() {
224 public void onCompleted(final ICameraFileInfo fileInfo)
226 runOnUiThread(new Runnable() {
231 String model = fileInfo.getModel();
232 String dateTime = "";
233 Date date = fileInfo.getDatetime();
235 dateTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US).format(date);
237 String path = fileInfo.getDirectoryPath() + "/" + fileInfo.getFilename();
238 String shutter = fileInfo.getShutterSpeed();
239 shutter = shutter.replace(".", "/");
240 String aperture = fileInfo.getAperature();
241 String iso = fileInfo.getIsoSensitivity();
242 String expRev = fileInfo.getExpRev();
244 message = path + "\r\n" + dateTime + "\r\n" + "- - - - - - - - - -\r\n " + shutter + " F" + aperture + " (" + expRev + ")" + " ISO" + iso + "\r\n" + "- - - - - - - - - -\r\n" + " model : " + model + "\r\n";
250 presentMessage(getString(R.string.download_control_get_information_title), message);
261 public void onErrorOccurred(Exception e)
271 public void onResume()
274 AppCompatActivity activity = (AppCompatActivity)getActivity();
275 if (activity != null)
277 ActionBar bar = activity.getSupportActionBar();
280 bar.setDisplayShowHomeEnabled(true);
285 if (runMode.isRecordingMode())
287 // Threadで呼んではダメみたいだ...
288 runMode.changeRunMode(false);
291 viewPager.setCurrentItem(contentIndex);
295 public void onPause()
298 AppCompatActivity activity = (AppCompatActivity)getActivity();
299 if (activity != null)
301 ActionBar bar = activity.getSupportActionBar();
308 if (!runMode.isRecordingMode())
310 // Threadで呼んではダメみたいだ...
311 runMode.changeRunMode(true);
315 private class ImagePagerAdapter extends PagerAdapter
319 public int getCount()
324 count = contentList.size();
334 public boolean isViewFromObject(@NonNull View view, @NonNull Object object)
336 return (view.equals(object));
340 public @NonNull Object instantiateItem(@NonNull ViewGroup container, int position)
342 ImageView view = (ImageView)layoutInflater.inflate(R.layout.view_image_page, container, false);
343 container.addView(view);
344 downloadImage(position, view);
349 public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object)
351 container.removeView((ImageView)object);
356 private class ImagePageChangeListener implements ViewPager.OnPageChangeListener
360 public void onPageScrollStateChanged(int state)
366 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
372 public void onPageSelected(int position)
374 contentIndex = position;
377 ICameraContent file = (contentList.get(contentIndex)).getFileInfo();
378 String path = file.getContentPath() + "/" + file.getContentName();
380 AppCompatActivity activity = (AppCompatActivity) getActivity();
381 if (activity != null)
383 ActionBar bar = activity.getSupportActionBar();
388 //activity.getSupportActionBar().setTitle(path);
389 activity.getFragmentManager().invalidateOptionsMenu();
403 private void downloadImage(final int position, final ImageView view)
405 Thread thread = new Thread(new Runnable() {
408 downloadImageImpl(position, view);
425 private void downloadImageImpl(int position, final ImageView view)
429 ICameraContent file = (contentList.get(position)).getFileInfo();
430 final String path = file.getContentPath() + "/" + file.getContentName();
432 // Get the cached image.
433 final Bitmap bitmap = imageCache.get(path);
436 if (view != null && viewPager.indexOfChild(view) > -1)
438 runOnUiThread(new Runnable()
443 view.setImageBitmap(bitmap);
450 // Download the image.
451 playbackControl.downloadContentScreennail(path, new IDownloadThumbnailImageCallback() {
453 //public void onCompleted(final byte[] data, final Map<String, Object> metadata) {
454 public void onCompleted(final Bitmap bitmap, final Map<String, Object> metadata) {
455 // Cache the downloaded image.
457 //final Bitmap bitmap = createRotatedBitmap(data, metadata);
464 if (imageCache != null)
466 imageCache.put(path, bitmap);
473 runOnUiThread(new Runnable() {
476 if ((bitmap != null) && (view != null) && (viewPager.indexOfChild(view) > -1))
478 view.setImageBitmap(bitmap);
485 public void onErrorOccurred(Exception e) {
486 final String message = e.getMessage();
487 runOnUiThread(new Runnable() {
490 presentMessage("Load failed", message);
503 * デバイスに画像ファイルをダウンロード(保存)する
505 * @param isRaw RAWファイルをダウンロードするか
506 * @param isSmallSize 小さいサイズの量にするか
508 private void saveImageWithDialog(final boolean isRaw, final boolean isSmallSize)
510 Log.v(TAG, "saveImageWithDialog() : raw : " + isRaw + " (small : " + isSmallSize + ")");
513 final Activity activity = getActivity();
514 if (activity != null)
516 Thread thread = new Thread(new Runnable() {
519 MyContentDownloader contentDownloader = new MyContentDownloader(activity, playbackControl);
520 CameraContentEx infoEx = contentList.get(contentIndex);
523 ICameraContent fileInfo = infoEx.getFileInfo();
524 contentDownloader.startDownload(fileInfo, "", (isRaw) ? infoEx.getRawSuffix() : null, isSmallSize);
537 // -------------------------------------------------------------------------
539 // -------------------------------------------------------------------------
541 private void presentMessage(final String title, final String message)
543 runOnUiThread(new Runnable() {
546 FragmentActivity activity = getActivity();
547 if (activity != null) {
548 AlertDialog.Builder builder = new AlertDialog.Builder(activity);
549 builder.setTitle(title).setMessage(message);
556 private void runOnUiThread(Runnable action)
558 if (getActivity() == null)
562 getActivity().runOnUiThread(action);
566 private Bitmap createRotatedBitmap(byte[] data, Map<String, Object> metadata)
571 bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
573 catch (OutOfMemoryError e)
585 int degrees = getRotationDegrees(data, metadata);
588 Matrix m = new Matrix();
589 m.postRotate(degrees);
592 bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true);
594 catch (OutOfMemoryError e)
604 private int getRotationDegrees(byte[] data, Map<String, Object> metadata)
607 int orientation = ExifInterface.ORIENTATION_UNDEFINED;
609 if (metadata != null && metadata.containsKey("Orientation")) {
610 orientation = Integer.parseInt((String)metadata.get("Orientation"));
614 // Gets image orientation to display a picture.
617 File tempFile = File.createTempFile("temp", null);
619 FileOutputStream outStream = new FileOutputStream(tempFile.getAbsolutePath());
620 outStream.write(data);
623 ExifInterface exifInterface = new ExifInterface(tempFile.getAbsolutePath());
624 orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
625 if (!tempFile.delete())
627 Log.v(TAG, "temp file delete failure.");
630 catch (IOException e)
638 case ExifInterface.ORIENTATION_NORMAL:
641 case ExifInterface.ORIENTATION_ROTATE_90:
644 case ExifInterface.ORIENTATION_ROTATE_180:
647 case ExifInterface.ORIENTATION_ROTATE_270: