Improved audio/video notes plugin

This commit is contained in:
Alexey Kulish 2015-12-23 20:11:58 +03:00
parent 70a312f21f
commit 3ccdf16280
14 changed files with 767 additions and 134 deletions

View file

@ -0,0 +1,11 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="0dp"
android:shape="ring"
android:thicknessRatio="2"
android:useLevel="false">
<solid android:color="@android:color/transparent" />
<stroke
android:width="1dp"
android:color="#28727272" />
</shape>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/circle_outline_background_normal"/>
</selector>

View file

@ -0,0 +1,5 @@
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/osmand_orange"/>
</shape>

View file

@ -0,0 +1,5 @@
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/osmand_orange_dark"/>
</shape>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/orange_circle_background_pressed" android:state_pressed="true"/>
<item android:drawable="@drawable/orange_circle_background_normal"></item>
</selector>

View file

@ -33,7 +33,7 @@
android:orientation="horizontal">
<LinearLayout
android:id="@+id/showHideView"
android:id="@+id/leftButtonView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
@ -47,7 +47,7 @@
android:gravity="left|center_vertical">
<ImageView
android:id="@+id/showHideIcon"
android:id="@+id/leftButtonIcon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
@ -55,7 +55,7 @@
tools:src="@drawable/ic_action_minimize"/>
<TextView
android:id="@+id/showHideText"
android:id="@+id/leftButtonText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
@ -70,7 +70,7 @@
</LinearLayout>
<LinearLayout
android:id="@+id/recView"
android:id="@+id/centerButtonView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
@ -83,7 +83,7 @@
android:gravity="center">
<ImageView
android:id="@+id/recIcon"
android:id="@+id/centerButtonIcon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
@ -91,7 +91,45 @@
tools:src="@drawable/ic_action_rec_stop"/>
<TextView
android:id="@+id/recText"
android:id="@+id/centerButtonText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:text="@string/shared_string_control_stop"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/rightButtonView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?attr/selectableItemBackground"
android:visibility="gone"
tools:visibility="visible">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center">
<ImageView
android:id="@+id/rightButtonIcon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:scaleType="center"
tools:src="@drawable/ic_action_rec_stop"/>
<TextView
android:id="@+id/rightButtonText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"

View file

@ -42,7 +42,7 @@
android:orientation="horizontal">
<LinearLayout
android:id="@+id/showHideView"
android:id="@+id/leftButtonView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
@ -56,7 +56,7 @@
android:gravity="left|center_vertical">
<ImageView
android:id="@+id/showHideIcon"
android:id="@+id/leftButtonIcon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
@ -64,7 +64,7 @@
tools:src="@drawable/ic_action_minimize"/>
<TextView
android:id="@+id/showHideText"
android:id="@+id/leftButtonText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
@ -79,7 +79,7 @@
</LinearLayout>
<LinearLayout
android:id="@+id/recView"
android:id="@+id/centerButtonView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
@ -92,7 +92,7 @@
android:gravity="center">
<ImageView
android:id="@+id/recIcon"
android:id="@+id/centerButtonIcon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
@ -100,7 +100,45 @@
tools:src="@drawable/ic_action_rec_stop"/>
<TextView
android:id="@+id/recText"
android:id="@+id/centerButtonText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:text="@string/shared_string_control_stop"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/rightButtonView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?attr/selectableItemBackground"
android:visibility="gone"
tools:visibility="visible">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center">
<ImageView
android:id="@+id/rightButtonIcon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:scaleType="center"
tools:src="@drawable/ic_action_rec_stop"/>
<TextView
android:id="@+id/rightButtonText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"

View file

@ -0,0 +1,169 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
android:id="@+id/recording_note_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_black"
android:clickable="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/viewfinder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/buttonsContainer"
android:layout_width="match_parent"
android:layout_height="108dp"
android:layout_gravity="bottom"
android:background="#3c212121"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/leftButtonView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="right|center_vertical">
<ImageView
android:id="@+id/leftButtonIcon"
android:layout_width="42dp"
android:layout_height="42dp"
android:layout_gravity="center_vertical"
android:background="@drawable/circle_outline_background_style"
android:scaleType="center"
android:src="@drawable/ic_action_refresh_dark"/>
<TextView
android:id="@+id/leftButtonText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:text="@string/shared_string_hide"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
android:visibility="gone"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/centerButtonView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1.6">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center">
<ImageView
android:id="@+id/centerButtonIcon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_vertical"
android:background="@drawable/orange_circle_background_style"
android:scaleType="center"
android:src="@drawable/ic_action_done"/>
<TextView
android:id="@+id/centerButtonText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:text="@string/shared_string_control_stop"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
android:visibility="gone"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/rightButtonView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="left|center_vertical">
<ImageView
android:id="@+id/rightButtonIcon"
android:layout_width="42dp"
android:layout_height="42dp"
android:layout_gravity="center_vertical"
android:background="@drawable/circle_outline_background_style"
android:scaleType="center"
android:src="@drawable/ic_action_device_camera"/>
<TextView
android:id="@+id/rightButtonText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:text="@string/shared_string_control_stop"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
android:visibility="gone"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/timeView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:visibility="gone">
<TextView
android:id="@+id/timeText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:gravity="right"
android:text="00:00:00"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"/>
</LinearLayout>
</LinearLayout>
</FrameLayout>

View file

@ -2,11 +2,13 @@ package net.osmand;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.text.format.DateFormat;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewParent;
@ -116,4 +118,19 @@ public class AndroidUtils {
);
}
public static int getStatusBarHeight(Context ctx) {
int result = 0;
int resourceId = ctx.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = ctx.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
public static int getScreenHeight(Activity activity) {
DisplayMetrics dm = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
return dm.heightPixels;
}
}

View file

@ -1,8 +1,7 @@
package net.osmand.plus.audionotes;
import android.content.res.Resources;
import android.os.Handler;
import android.util.TypedValue;
import android.util.DisplayMetrics;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
@ -10,6 +9,7 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import net.osmand.AndroidUtils;
import net.osmand.plus.IconsCache;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
@ -21,42 +21,84 @@ import net.osmand.util.Algorithms;
import java.util.Timer;
import java.util.TimerTask;
import static android.util.TypedValue.COMPLEX_UNIT_DIP;
public class AudioVideoNoteRecordingMenu {
private View view;
private LinearLayout viewfinder;
private AudioVideoNotesPlugin plugin;
private long startTime;
private Handler handler;
private boolean portraitMode;
private boolean largeDevice;
private Timer recTimer;
protected View view;
protected LinearLayout viewfinder;
protected AudioVideoNotesPlugin plugin;
protected long startTime;
protected Handler handler;
protected boolean portraitMode;
protected boolean largeDevice;
protected Timer recTimer;
protected double lat;
protected double lon;
private int screenHeight;
private int buttonsHeight;
private int statusBarHeight;
public static boolean showViewfinder = true;
public AudioVideoNoteRecordingMenu(AudioVideoNotesPlugin plugin) {
public AudioVideoNoteRecordingMenu(AudioVideoNotesPlugin plugin, double lat, double lon) {
this.plugin = plugin;
this.lat = lat;
this.lon = lon;
handler = new Handler();
MapActivity mapActivity = plugin.getMapActivity();
portraitMode = AndroidUiHelper.isOrientationPortrait(mapActivity);
largeDevice = AndroidUiHelper.isXLargeDevice(mapActivity);
view = mapActivity.findViewById(R.id.recording_note_layout);
initView(mapActivity);
viewfinder = (LinearLayout) view.findViewById(R.id.viewfinder);
showViewfinder = true;
screenHeight = AndroidUtils.getScreenHeight(getMapActivity());
statusBarHeight = AndroidUtils.getStatusBarHeight(getMapActivity());
buttonsHeight = getMapActivity().getResources().getDimensionPixelSize(R.dimen.map_route_buttons_height);
update();
}
public MapActivity getMapActivity() {
return plugin.getMapActivity();
}
protected void initView(MapActivity mapActivity) {
view = mapActivity.findViewById(R.id.recording_note_layout);
}
public SurfaceView prepareSurfaceView() {
return prepareSurfaceView(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
}
public SurfaceView prepareSurfaceView(int width, int height) {
int w = width;
int h = height;
if (w != ViewGroup.LayoutParams.MATCH_PARENT && h != ViewGroup.LayoutParams.MATCH_PARENT) {
int vfw = getViewfinderWidth();
int vfh = getViewfinderHeight();
float vfRatio = vfw / (float) vfh;
float sourceRatio;
if (vfRatio > 1) {
sourceRatio = width / (float) height;
} else {
sourceRatio = height / (float) width;
}
if (sourceRatio > vfRatio) {
w = vfw;
h = (int) (w / sourceRatio);
} else {
h = vfh;
w = (int) (h * sourceRatio);
}
}
viewfinder.removeAllViews();
SurfaceView surfaceView = new SurfaceView(viewfinder.getContext());
surfaceView.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
surfaceView.setLayoutParams(new LinearLayout.LayoutParams(w, h));
surfaceView.setZOrderMediaOverlay(true);
viewfinder.addView(surfaceView);
@ -85,29 +127,29 @@ public class AudioVideoNoteRecordingMenu {
CurrentRecording recording = plugin.getCurrentRecording();
IconsCache iconsCache = plugin.getMapActivity().getMyApplication().getIconsCache();
ImageView showHideIcon = (ImageView) view.findViewById(R.id.showHideIcon);
View showHideView = view.findViewById(R.id.showHideView);
ImageView leftButtonIcon = (ImageView) view.findViewById(R.id.leftButtonIcon);
View leftButtonView = view.findViewById(R.id.leftButtonView);
if (recording.getType() != AVActionType.REC_AUDIO) {
showHideIcon.setImageDrawable(iconsCache.getContentIcon(R.drawable.ic_action_minimize));
TextView showHideText = (TextView) view.findViewById(R.id.showHideText);
leftButtonIcon.setImageDrawable(iconsCache.getContentIcon(R.drawable.ic_action_minimize));
TextView showHideText = (TextView) view.findViewById(R.id.leftButtonText);
showHideText.setText(showViewfinder ?
view.getResources().getString(R.string.shared_string_hide) : view.getResources().getString(R.string.shared_string_show));
showHideView.setVisibility(View.VISIBLE);
leftButtonView.setVisibility(View.VISIBLE);
viewfinder.setVisibility(showViewfinder ? View.VISIBLE : View.GONE);
} else {
showHideView.setVisibility(View.INVISIBLE);
leftButtonView.setVisibility(View.INVISIBLE);
viewfinder.setVisibility(View.GONE);
}
showHideView.setOnClickListener(new View.OnClickListener() {
leftButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showHideViewfinder();
}
});
View recView = view.findViewById(R.id.recView);
ImageView recIcon = (ImageView) view.findViewById(R.id.recIcon);
TextView recText = (TextView) view.findViewById(R.id.recText);
View centerButtonView = view.findViewById(R.id.centerButtonView);
ImageView recIcon = (ImageView) view.findViewById(R.id.centerButtonIcon);
TextView recText = (TextView) view.findViewById(R.id.centerButtonText);
View timeView = view.findViewById(R.id.timeView);
switch (recording.getType()) {
case REC_AUDIO:
@ -124,7 +166,7 @@ public class AudioVideoNoteRecordingMenu {
timeView.setVisibility(View.INVISIBLE);
break;
}
recView.setOnClickListener(new View.OnClickListener() {
centerButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
rec(plugin.getMapActivity());
@ -139,7 +181,7 @@ public class AudioVideoNoteRecordingMenu {
timeText.setText(Algorithms.formatDuration(duration));
}
private void applyViewfinderVisibility() {
protected void applyViewfinderVisibility() {
MapActivity mapActivity = plugin.getMapActivity();
CurrentRecording recording = plugin.getCurrentRecording();
boolean show = showViewfinder && recording != null && recording.getType() != AVActionType.REC_AUDIO;
@ -147,7 +189,7 @@ public class AudioVideoNoteRecordingMenu {
int buttonsHeight = view.findViewById(R.id.buttonsContainer).getHeight();
int tileBoxHeight = mapActivity.getMapView().getCurrentRotatedTileBox().getPixHeight();
int h = show ? tileBoxHeight : buttonsHeight;
view.setLayoutParams(new LinearLayout.LayoutParams(dpToPx(320f, mapActivity), h));
view.setLayoutParams(new LinearLayout.LayoutParams(AndroidUtils.dpToPx(mapActivity, 320f), h));
view.requestLayout();
}
viewfinder.setVisibility(show ? View.VISIBLE : View.GONE);
@ -155,17 +197,43 @@ public class AudioVideoNoteRecordingMenu {
public void showHideViewfinder() {
showViewfinder = !showViewfinder;
TextView showHideText = (TextView) view.findViewById(R.id.showHideText);
TextView showHideText = (TextView) view.findViewById(R.id.leftButtonText);
showHideText.setText(showViewfinder ? view.getResources().getString(R.string.shared_string_hide) : view.getResources().getString(R.string.shared_string_show));
applyViewfinderVisibility();
}
public int getViewfinderWidth() {
return viewfinder.getWidth();
int res;
CurrentRecording recording = plugin.getCurrentRecording();
if (recording.getType() == AVActionType.REC_PHOTO) {
DisplayMetrics dm = new DisplayMetrics();
getMapActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
res = dm.widthPixels;
} else {
if (isLandscapeLayout()) {
res = AndroidUtils.dpToPx(getMapActivity(), 320 - 16f);
} else {
res = AndroidUtils.dpToPx(getMapActivity(), 240f);
}
}
return res;
}
public int getViewfinderHeight() {
return viewfinder.getHeight();
int res;
CurrentRecording recording = plugin.getCurrentRecording();
if (recording.getType() == AVActionType.REC_PHOTO) {
DisplayMetrics dm = new DisplayMetrics();
getMapActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
res = dm.heightPixels;
} else {
if (isLandscapeLayout()) {
res = screenHeight - statusBarHeight - buttonsHeight;
} else {
res = AndroidUtils.dpToPx(getMapActivity(), 240f);
}
}
return res;
}
public void rec(final MapActivity mapActivity) {
@ -185,6 +253,21 @@ public class AudioVideoNoteRecordingMenu {
}, 200);
}
public void recExternal(final MapActivity mapActivity) {
stopCounter();
handler.postDelayed(new Runnable() {
@Override
public void run() {
CurrentRecording recording = plugin.getCurrentRecording();
if (recording != null) {
if (recording.getType() == AVActionType.REC_PHOTO) {
plugin.takePhotoExternal(lat, lon, mapActivity);
}
}
}
}, 20);
}
private void startCounter() {
startTime = System.currentTimeMillis();
@ -213,13 +296,4 @@ public class AudioVideoNoteRecordingMenu {
recTimer = null;
}
}
private int dpToPx(float dp, MapActivity mapActivity) {
Resources r = mapActivity.getResources();
return (int) TypedValue.applyDimension(
COMPLEX_UNIT_DIP,
dp,
r.getDisplayMetrics()
);
}
}

View file

@ -0,0 +1,83 @@
package net.osmand.plus.audionotes;
import android.support.v4.app.Fragment;
import android.view.View;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import java.lang.ref.WeakReference;
public class AudioVideoNoteRecordingMenuFullScreen extends AudioVideoNoteRecordingMenu {
public AudioVideoNoteRecordingMenuFullScreen(AudioVideoNotesPlugin plugin, double lat, double lon) {
super(plugin, lat, lon);
}
protected void initView(MapActivity mapActivity) {
mapActivity.getContextMenu().hide();
AudioVideoNoteRecordingMenuFullScreenFragment.showInstance(this);
WeakReference<AudioVideoNoteRecordingMenuFullScreenFragment> fragmentRef = findMenuFragment();
if (fragmentRef != null) {
view = fragmentRef.get().getView();
}
if (view == null) {
super.initView(mapActivity);
}
}
@Override
protected void applyViewfinderVisibility() {
}
public void show() {
}
public void hide() {
plugin.stopCamera();
WeakReference<AudioVideoNoteRecordingMenuFullScreenFragment> fragmentRef = findMenuFragment();
if (fragmentRef != null) {
fragmentRef.get().dismiss();
}
}
public void update() {
View leftButtonView = view.findViewById(R.id.leftButtonView);
leftButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
plugin.shootAgain();
}
});
View centerButtonView = view.findViewById(R.id.centerButtonView);
centerButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finishRecording();
}
});
View rightButtonView = view.findViewById(R.id.rightButtonView);
rightButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
plugin.finishPhotoRecording(true);
recExternal(plugin.getMapActivity());
}
});
}
public void finishRecording() {
plugin.finishPhotoRecording(false);
}
public WeakReference<AudioVideoNoteRecordingMenuFullScreenFragment> findMenuFragment() {
Fragment fragment = getMapActivity().getSupportFragmentManager().findFragmentByTag(AudioVideoNoteRecordingMenuFullScreenFragment.TAG);
if (fragment != null && !fragment.isDetached()) {
return new WeakReference<>((AudioVideoNoteRecordingMenuFullScreenFragment) fragment);
} else {
return null;
}
}
}

View file

@ -0,0 +1,63 @@
package net.osmand.plus.audionotes;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import net.osmand.plus.R;
public class AudioVideoNoteRecordingMenuFullScreenFragment extends Fragment {
public static final String TAG = "AudioVideoNoteRecordingMenuFullScreenFragment";
private AudioVideoNoteRecordingMenuFullScreen menu;
private boolean dismissing;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.recording_note_fragment_fullscreen, container, false);
}
@Override
public void onResume() {
super.onResume();
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
@Override
public void onPause() {
super.onPause();
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
@Override
public void onDestroyView() {
super.onDestroyView();
if (!dismissing) {
menu.finishRecording();
}
}
public static void showInstance(AudioVideoNoteRecordingMenuFullScreen menu) {
AudioVideoNoteRecordingMenuFullScreenFragment fragment = new AudioVideoNoteRecordingMenuFullScreenFragment();
fragment.menu = menu;
FragmentManager fragmentManager = menu.getMapActivity().getSupportFragmentManager();
fragmentManager.beginTransaction()
//.setCustomAnimations(R.anim.abc_fade_in, R.anim.abc_fade_out, R.anim.abc_fade_in, R.anim.abc_fade_out)
.add(R.id.fragmentContainer, fragment, TAG)
.addToBackStack(TAG).commit();
fragmentManager.executePendingTransactions();
}
public void dismiss() {
dismissing = true;
getActivity().getSupportFragmentManager().popBackStack();
}
}

View file

@ -151,8 +151,12 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
private static File mediaRecFile;
private static MediaRecorder mediaRec;
private File lastTakingPhoto;
private byte[] photoRawData;
private Timer photoTimer;
private Camera cam;
private List<Camera.Size> mSupportedPreviewSizes;
private int requestedOrientation;
private boolean autofocus;
private AudioVideoNoteRecordingMenu recordingMenu;
private CurrentRecording currentRecording;
@ -786,7 +790,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
public void mapActivityPause(MapActivity activity) {
if (isRecording()) {
if (currentRecording.getType() == AVActionType.REC_PHOTO) {
recordingMenu.hide();
finishPhotoRecording(false);
} else {
activity.getContextMenu().close();
stopRecording(activity);
@ -804,9 +808,13 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
return currentRecording != null;
}
private void initRecMenu(AVActionType actionType) {
private void initRecMenu(AVActionType actionType, double lat, double lon) {
currentRecording = new CurrentRecording(actionType);
recordingMenu = new AudioVideoNoteRecordingMenu(this);
if (actionType == AVActionType.REC_PHOTO) {
recordingMenu = new AudioVideoNoteRecordingMenuFullScreen(this, lat, lon);
} else {
recordingMenu = new AudioVideoNoteRecordingMenu(this, lat, lon);
}
recordingDone = false;
lockScreenOrientation();
}
@ -821,7 +829,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
== PackageManager.PERMISSION_GRANTED) {
openCamera();
if (cam != null) {
initRecMenu(AVActionType.REC_VIDEO);
initRecMenu(AVActionType.REC_VIDEO, lat, lon);
recordVideoCamera(lat, lon, mapActivity);
}
} else {
@ -835,7 +843,29 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
}
public void recordVideoCamera(final double lat, final double lon, final MapActivity mapActivity) {
SurfaceView view = recordingMenu.prepareSurfaceView();
final CamcorderProfile p = CamcorderProfile.get(AV_VIDEO_QUALITY.get());
final Camera.Size mPreviewSize;
if (mSupportedPreviewSizes != null) {
int width;
int height;
if (recordingMenu.isLandscapeLayout()) {
width = p.videoFrameWidth;
height = p.videoFrameHeight;
} else {
height = p.videoFrameWidth;
width = p.videoFrameHeight;
}
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
} else {
mPreviewSize = null;
}
final SurfaceView view;
if (mPreviewSize != null) {
view = recordingMenu.prepareSurfaceView(mPreviewSize.width, mPreviewSize.height);
} else {
view = recordingMenu.prepareSurfaceView();
}
view.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
view.getHolder().addCallback(new Callback() {
@ -849,9 +879,19 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
MediaRecorder mr = new MediaRecorder();
try {
Parameters parameters = cam.getParameters();
// camera focus type
List<String> sfm = parameters.getSupportedFocusModes();
if (sfm.contains("continuous-video")) {
parameters.setFocusMode("continuous-video");
}
int cameraOrientation = getCamOrientation(mapActivity, Camera.CameraInfo.CAMERA_FACING_BACK);
cam.setDisplayOrientation(cameraOrientation);
parameters.set("rotation", cameraOrientation);
if (mPreviewSize != null) {
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
}
cam.setParameters(parameters);
cam.setPreviewDisplay(holder);
cam.startPreview();
@ -885,7 +925,6 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
giveMediaRecorderHintRotatedScreen(mapActivity, mr);
//mr.setPreviewDisplay(holder.getSurface());
CamcorderProfile p = CamcorderProfile.get(AV_VIDEO_QUALITY.get());
mr.setProfile(p);
mr.setOutputFile(f.getAbsolutePath());
try {
@ -936,6 +975,9 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
}
try {
cam = Camera.open();
if (mSupportedPreviewSizes == null) {
mSupportedPreviewSizes = cam.getParameters().getSupportedPreviewSizes();
}
} catch (Exception e) {
logErr(e);
}
@ -964,6 +1006,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
protected void stopCamera() {
try {
if (cam != null) {
cam.cancelAutoFocus();
cam.stopPreview();
cam.setPreviewDisplay(null);
}
@ -991,7 +1034,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
public void recordAudio(double lat, double lon, final MapActivity mapActivity) {
if (ActivityCompat.checkSelfPermission(mapActivity, Manifest.permission.RECORD_AUDIO)
== PackageManager.PERMISSION_GRANTED) {
initRecMenu(AVActionType.REC_AUDIO);
initRecMenu(AVActionType.REC_AUDIO, lat, lon);
MediaRecorder mr = new MediaRecorder();
final File f = getBaseFileName(lat, lon, app, THREEGP_EXTENSION);
mr.setAudioSource(MediaRecorder.AudioSource.MIC);
@ -1035,7 +1078,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
private void takePhotoInternalOrExternal(double lat, double lon, MapActivity mapActivity) {
openCamera();
if (cam != null) {
initRecMenu(AVActionType.REC_PHOTO);
initRecMenu(AVActionType.REC_PHOTO, lat, lon);
takePhotoWithCamera(lat, lon, mapActivity);
} else {
takePhotoExternal(lat, lon, mapActivity);
@ -1046,7 +1089,31 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
final MapActivity mapActivity) {
try {
lastTakingPhoto = getBaseFileName(lat, lon, app, IMG_EXTENSION);
final SurfaceView view = recordingMenu.prepareSurfaceView();
final Camera.Size mPreviewSize;
Parameters parameters = cam.getParameters();
List<Camera.Size> psps = parameters.getSupportedPictureSizes();
int camPicSizeIndex = AV_CAMERA_PICTURE_SIZE.get();
// camera picture size
log.debug("takePhotoWithCamera() index=" + camPicSizeIndex);
if (camPicSizeIndex == AV_PHOTO_SIZE_DEFAULT) {
camPicSizeIndex = cameraPictureSizeDefault;
log.debug("takePhotoWithCamera() Default value of picture size. Set index to cameraPictureSizeDefault. Now index="
+ camPicSizeIndex);
}
final Camera.Size selectedCamPicSize = psps.get(camPicSizeIndex);
if (mSupportedPreviewSizes != null) {
int width = selectedCamPicSize.width;
int height = selectedCamPicSize.height;
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
} else {
mPreviewSize = null;
}
final SurfaceView view;
if (mPreviewSize != null) {
view = recordingMenu.prepareSurfaceView(mPreviewSize.width, mPreviewSize.height);
} else {
view = recordingMenu.prepareSurfaceView();
}
view.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
view.getHolder().addCallback(new Callback() {
@ -1061,13 +1128,11 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
if (AV_PHOTO_PLAY_SOUND.get()) {
if (sp == null)
sp = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
log.info("Play sound on photo");
if (shotId == 0) {
try {
AssetFileDescriptor assetFileDescriptor = app.getAssets().openFd("sounds/camera_click.ogg");
shotId = sp.load(assetFileDescriptor, 1);
assetFileDescriptor.close();
log.debug("loaded file sound ID: " + shotId);
} catch (Exception e) {
log.error("cannot get shotId for sounds/camera_click.ogg");
}
@ -1075,24 +1140,12 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
}
Parameters parameters = cam.getParameters();
// camera picture size
List<Camera.Size> psps = parameters.getSupportedPictureSizes();
int index = AV_CAMERA_PICTURE_SIZE.get();
log.debug("takePhotoWithCamera() index=" + index);
if (index == AV_PHOTO_SIZE_DEFAULT) {
index = cameraPictureSizeDefault;
log.debug("takePhotoWithCamera() Default value of picture size. Set index to cameraPictureSizeDefault. Now index="
+ index);
}
Camera.Size selectedCamPicSize = psps.get(index);
parameters.setPictureSize(selectedCamPicSize.width, selectedCamPicSize.height);
log.debug("takePhotoWithCamera() set Picture size: width=" + selectedCamPicSize.width
+ " height=" + selectedCamPicSize.height);
// camera focus type
boolean autofocus = true;
// boolean autofocus = !Boolean.parseBoolean(parameters.get("auto-exposure-lock-supported"));
autofocus = true;
parameters.setGpsLatitude(lat);
parameters.setGpsLongitude(lon);
switch (AV_CAMERA_FOCUS_TYPE.get()) {
@ -1134,17 +1187,14 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
int cameraOrientation = getCamOrientation(mapActivity, Camera.CameraInfo.CAMERA_FACING_BACK);
cam.setDisplayOrientation(cameraOrientation);
parameters.set("rotation", cameraOrientation);
// if (cameraOrientation == 0 || cameraOrientation == 180) {
// parameters.setPreviewSize(recordingMenu.getViewfinderWidth(), recordingMenu.getViewfinderHeight());
// } else {
// parameters.setPreviewSize(recordingMenu.getViewfinderHeight(), recordingMenu.getViewfinderWidth());
// }
if (mPreviewSize != null) {
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
}
cam.setParameters(parameters);
cam.setPreviewDisplay(holder);
cam.startPreview();
if (autofocus) {
cam.autoFocus(null);
}
internalShoot();
} catch (Exception e) {
logErr(e);
closeRecordingMenu();
@ -1154,10 +1204,6 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
}
}
private void printCamParams(Parameters parameters, boolean autoExposure) {
log.info("Cam params auto exposure=" + autoExposure + " focus_distances=" + parameters.get("focus-distances"));
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@ -1171,6 +1217,64 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
}
}
private void internalShoot() {
if (!autofocus) {
cam.takePicture(null, null, new AudioVideoPhotoHandler());
} else {
cam.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
cam.cancelAutoFocus();
try {
cam.takePicture(null, null, new AudioVideoPhotoHandler());
} catch (Exception e) {
logErr(e);
closeRecordingMenu();
closeCamera();
finishRecording();
e.printStackTrace();
}
}
});
}
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio;
if (w > h) {
targetRatio = (double) w / h;
} else {
targetRatio = (double) h / w;
}
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - h) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - h);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - h) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - h);
}
}
}
return optimalSize;
}
private static int getCamOrientation(MapActivity mapActivity, int cameraId) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
@ -1208,7 +1312,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
recordingDone = true;
if (cam != null && lastTakingPhoto != null) {
try {
cam.takePicture(null, null, new AudioVideoPhotoHandler(lastTakingPhoto));
cam.takePicture(null, null, new AudioVideoPhotoHandler());
} catch (RuntimeException e) {
closeRecordingMenu();
closeCamera();
@ -1218,7 +1322,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
}
}
private void takePhotoExternal(double lat, double lon, final MapActivity mapActivity) {
public void takePhotoExternal(double lat, double lon, final MapActivity mapActivity) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
final File f = getBaseFileName(lat, lon, app, IMG_EXTENSION);
lastTakingPhoto = f;
@ -1626,40 +1730,73 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
}
public class AudioVideoPhotoHandler implements PictureCallback {
private File pictureFile;
public AudioVideoPhotoHandler(File fileName) {
this.pictureFile = fileName;
public AudioVideoPhotoHandler() {
}
@Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
indexFile(true, pictureFile);
// play sound after photo - sound file must be loaded at this time:
if (AV_PHOTO_PLAY_SOUND.get()) {
if (sp != null && shotId != 0) {
int ret = sp.play(shotId, 0.7f, 0.7f, 0, 0, 1);
log.debug("play sound shot success!");
log.debug("sp.play()=" + ret);
// sp.release();
// sp=null;
// shotId=0
} else {
log.error("can not play sound on shot - not init SoundPool or not loaded sound");
}
}
public void onPictureTaken(final byte[] data, Camera camera) {
photoRawData = data;
if (AV_PHOTO_PLAY_SOUND.get()) {
if (sp != null && shotId != 0) {
sp.play(shotId, 0.7f, 0.7f, 0, 0, 1);
}
}
startPhotoTimer();
}
}
private void startPhotoTimer() {
if (photoTimer != null) {
cancelPhotoTimer();
}
photoTimer = new Timer();
photoTimer.schedule(new TimerTask() {
@Override
public void run() {
finishPhotoRecording(false);
}
}, 4000);
}
private void cancelPhotoTimer() {
if (photoTimer != null) {
photoTimer.cancel();
photoTimer = null;
}
}
public synchronized void shootAgain() {
cancelPhotoTimer();
photoRawData = null;
cam.startPreview();
internalShoot();
}
public synchronized void finishPhotoRecording(boolean cancel) {
cancelPhotoTimer();
if (photoRawData != null && photoRawData.length > 0 && lastTakingPhoto != null) {
try {
if (!cancel) {
FileOutputStream fos = new FileOutputStream(lastTakingPhoto);
fos.write(photoRawData);
fos.close();
indexFile(true, lastTakingPhoto);
}
} catch (Exception error) {
logErr(error);
} finally {
photoRawData = null;
closeRecordingMenu();
closeCamera();
finishRecording();
if (!cancel) {
finishRecording();
}
}
} else if (cancel) {
closeRecordingMenu();
}
}

View file

@ -10,7 +10,6 @@ import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
@ -139,10 +138,10 @@ public class MapContextMenuFragment extends Fragment implements DownloadEvents {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
screenHeight = getScreenHeight();
screenHeight = AndroidUtils.getScreenHeight(getActivity());
skipHalfScreenStateLimit = screenHeight * SKIP_HALF_SCREEN_STATE_KOEF;
viewHeight = screenHeight - getStatusBarHeight();
viewHeight = screenHeight - AndroidUtils.getStatusBarHeight(getMapActivity());
fabPaddingTopPx = dpToPx(FAB_PADDING_TOP_DP);
markerPaddingPx = dpToPx(MARKER_PADDING_DP);
@ -1150,21 +1149,6 @@ public class MapContextMenuFragment extends Fragment implements DownloadEvents {
);
}
private int getScreenHeight() {
DisplayMetrics dm = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
return dm.heightPixels;
}
public int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
public void updateLocation(boolean centerChanged, boolean locationChanged, boolean compassChanged) {
updateDistanceDirection();
}