Add recordings list view
|
@ -110,6 +110,7 @@ import org.linphone.purchase.InAppPurchaseActivity;
|
|||
import org.linphone.views.AddressText;
|
||||
import org.linphone.utils.LinphoneGenericActivity;
|
||||
import org.linphone.utils.LinphoneUtils;
|
||||
import org.linphone.recording.RecordingListFragment;
|
||||
import org.linphone.xmlrpc.XmlRpcHelper;
|
||||
import org.linphone.xmlrpc.XmlRpcListenerBase;
|
||||
|
||||
|
@ -135,7 +136,7 @@ public class LinphoneActivity extends LinphoneGenericActivity implements OnClick
|
|||
private StatusFragment statusFragment;
|
||||
private TextView missedCalls, missedChats;
|
||||
private RelativeLayout contacts, history, dialer, chat;
|
||||
private View contacts_selected, history_selected, dialer_selected, chat_selected;
|
||||
private View contacts_selected, history_selected, dialer_selected, chat_selected, record_selected;
|
||||
private LinearLayout mTopBar;
|
||||
private TextView mTopBarTitle;
|
||||
private ImageView cancel;
|
||||
|
@ -428,6 +429,9 @@ public class LinphoneActivity extends LinphoneGenericActivity implements OnClick
|
|||
case CONTACT_DEVICES:
|
||||
fragment = new DevicesFragment();
|
||||
break;
|
||||
case RECORDING_LIST:
|
||||
fragment = new RecordingListFragment();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -638,7 +642,7 @@ public class LinphoneActivity extends LinphoneGenericActivity implements OnClick
|
|||
}
|
||||
|
||||
public void displayRecordings() {
|
||||
|
||||
changeCurrentFragment(FragmentsAvailable.RECORDING_LIST, null);
|
||||
}
|
||||
|
||||
public void displayContactsForEdition(String sipAddress, String displayName) {
|
||||
|
@ -1634,7 +1638,7 @@ public class LinphoneActivity extends LinphoneGenericActivity implements OnClick
|
|||
LinphoneActivity.instance().displayInapp();
|
||||
}
|
||||
}
|
||||
if (sideMenuItemList.getAdapter().getItem(i).toString().equals(R.string.menu_recordings)) {
|
||||
if (sideMenuItemList.getAdapter().getItem(i).toString().equals(getString(R.string.menu_recordings))) {
|
||||
LinphoneActivity.instance().displayRecordings();
|
||||
}
|
||||
openOrCloseSideMenu(false);
|
||||
|
|
|
@ -37,7 +37,8 @@ public enum FragmentsAvailable {
|
|||
INFO_GROUP_CHAT,
|
||||
GROUP_CHAT,
|
||||
MESSAGE_IMDN,
|
||||
CONTACT_DEVICES;
|
||||
CONTACT_DEVICES,
|
||||
RECORDING_LIST;
|
||||
|
||||
public boolean shouldAddItselfToTheRightOf(FragmentsAvailable fragment) {
|
||||
switch (this) {
|
||||
|
|
152
app/src/main/java/org/linphone/recording/Recording.java
Normal file
|
@ -0,0 +1,152 @@
|
|||
package org.linphone.recording;
|
||||
|
||||
/*
|
||||
Recording.java
|
||||
Copyright (C) 2018 Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.core.Player;
|
||||
import org.linphone.core.PlayerListener;
|
||||
import org.linphone.mediastream.Log;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Recording implements PlayerListener, Comparable<Recording> {
|
||||
private String recordPath, name;
|
||||
private Date recordDate;
|
||||
private Player player;
|
||||
private RecordingListener listener;
|
||||
private Timer timer;
|
||||
private TimerTask updateCurrentPositionTimer;
|
||||
|
||||
private static final Pattern mRecordPattern = Pattern.compile(".*/(.*)_(\\d{2}-\\d{2}-\\d{4}-\\d{2}-\\d{2}-\\d{2})\\..*");
|
||||
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
public Recording(String recordPath) {
|
||||
this.recordPath = recordPath;
|
||||
|
||||
Matcher m = mRecordPattern.matcher(recordPath);
|
||||
if (m.matches()) {
|
||||
name = m.group(1);
|
||||
|
||||
try {
|
||||
recordDate = new SimpleDateFormat("dd-MM-yyyy-HH-mm-ss").parse(m.group(2));
|
||||
} catch (ParseException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
}
|
||||
|
||||
timer = new Timer();
|
||||
updateCurrentPositionTimer = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (listener != null) listener.currentPositionChanged(getCurrentPosition());
|
||||
}
|
||||
};
|
||||
|
||||
player = LinphoneManager.getLc().createLocalPlayer(null, null, null);
|
||||
player.setListener(this);
|
||||
player.open(recordPath);
|
||||
}
|
||||
|
||||
public String getRecordPath() {
|
||||
return recordPath;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Date getRecordDate() {
|
||||
return recordDate;
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return player.getState() == Player.State.Closed;
|
||||
}
|
||||
|
||||
public void play() {
|
||||
player.start();
|
||||
//timer.scheduleAtFixedRate(updateCurrentPositionTimer, 0, 1000);
|
||||
}
|
||||
|
||||
public boolean isPlaying() {
|
||||
return player.getState() == Player.State.Playing;
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
if (!isClosed()) {
|
||||
player.pause();
|
||||
|
||||
timer.cancel();
|
||||
timer.purge();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPaused() {
|
||||
return player.getState() == Player.State.Paused;
|
||||
}
|
||||
|
||||
public void seek(int i) {
|
||||
if (!isClosed()) player.seek(i);
|
||||
}
|
||||
|
||||
public int getCurrentPosition() {
|
||||
return player.getCurrentPosition();
|
||||
}
|
||||
|
||||
public int getDuration() {
|
||||
return player.getDuration();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
player.close();
|
||||
}
|
||||
|
||||
public void setRecordingListener(RecordingListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEofReached(Player player) {
|
||||
if (listener != null) listener.endOfRecordReached();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof Recording) {
|
||||
Recording r = (Recording) o;
|
||||
return recordPath.equals(r.getRecordPath());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NonNull Recording o) {
|
||||
return -recordDate.compareTo(o.getRecordDate());
|
||||
}
|
||||
}
|
275
app/src/main/java/org/linphone/recording/RecordingAdapter.java
Normal file
|
@ -0,0 +1,275 @@
|
|||
package org.linphone.recording;
|
||||
|
||||
/*
|
||||
RecordingAdapter.java
|
||||
Copyright (C) 2018 Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.linphone.R;
|
||||
import org.linphone.mediastream.Log;
|
||||
import org.linphone.ui.SelectableAdapter;
|
||||
import org.linphone.ui.SelectableHelper;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class RecordingAdapter extends SelectableAdapter<RecordingAdapter.ViewHolder> {
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
||||
public ImageView playButton;
|
||||
public TextView name, date, currentPosition, duration;
|
||||
public SeekBar progressionBar;
|
||||
public CheckBox select;
|
||||
public LinearLayout separator;
|
||||
public TextView separatorText;
|
||||
private RecordingAdapter.ViewHolder.ClickListener listener;
|
||||
|
||||
public ViewHolder(View view, RecordingAdapter.ViewHolder.ClickListener listener) {
|
||||
super(view);
|
||||
|
||||
playButton = view.findViewById(R.id.record_play);
|
||||
name = view.findViewById(R.id.record_name);
|
||||
date = view.findViewById(R.id.record_date);
|
||||
currentPosition = view.findViewById(R.id.record_current_time);
|
||||
duration = view.findViewById(R.id.record_duration);
|
||||
progressionBar = view.findViewById(R.id.record_progression_bar);
|
||||
select = view.findViewById(R.id.delete);
|
||||
separator = view.findViewById(R.id.separator);
|
||||
separatorText = view.findViewById(R.id.separator_text);
|
||||
|
||||
this.listener = listener;
|
||||
view.setOnClickListener(this);
|
||||
view.setOnLongClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (listener != null) {
|
||||
listener.onItemClicked(getAdapterPosition());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
if (listener != null) {
|
||||
return listener.onItemLongClicked(getAdapterPosition());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public interface ClickListener {
|
||||
void onItemClicked(int position);
|
||||
|
||||
boolean onItemLongClicked(int position);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Recording> recordings;
|
||||
private Context context;
|
||||
private RecordingAdapter.ViewHolder.ClickListener clickListener;
|
||||
|
||||
public RecordingAdapter(Context context, List<Recording> recordings, RecordingAdapter.ViewHolder.ClickListener listener, SelectableHelper helper) {
|
||||
super(helper);
|
||||
|
||||
this.recordings = recordings;
|
||||
this.context = context;
|
||||
this.clickListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return recordings.get(position);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
|
||||
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.recording_cell, viewGroup, false);
|
||||
return new RecordingAdapter.ViewHolder(v, clickListener);
|
||||
}
|
||||
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final ViewHolder viewHolder, int i) {
|
||||
final Recording record = recordings.get(i);
|
||||
|
||||
viewHolder.name.setSelected(true); // For automated horizontal scrolling of long texts
|
||||
|
||||
Calendar recordTime = Calendar.getInstance();
|
||||
recordTime.setTime(record.getRecordDate());
|
||||
viewHolder.separatorText.setText(DateToHumanDate(recordTime));
|
||||
viewHolder.select.setVisibility(isEditionEnabled() ? View.VISIBLE : View.GONE);
|
||||
viewHolder.select.setChecked(isSelected(i));
|
||||
|
||||
if (i > 0) {
|
||||
Recording previousRecord = recordings.get(i - 1);
|
||||
Date previousRecordDate = previousRecord.getRecordDate();
|
||||
Calendar previousRecordTime = Calendar.getInstance();
|
||||
previousRecordTime.setTime(previousRecordDate);
|
||||
|
||||
if (isSameDay(previousRecordTime, recordTime)) {
|
||||
viewHolder.separator.setVisibility(View.GONE);
|
||||
} else {
|
||||
viewHolder.separator.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
viewHolder.separator.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (record.isPlaying()) {
|
||||
viewHolder.playButton.setImageResource(R.drawable.record_pause);
|
||||
} else {
|
||||
viewHolder.playButton.setImageResource(R.drawable.record_play);
|
||||
}
|
||||
viewHolder.playButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (record.isPaused()) {
|
||||
record.play();
|
||||
viewHolder.playButton.setImageResource(R.drawable.record_pause);
|
||||
} else {
|
||||
record.pause();
|
||||
viewHolder.playButton.setImageResource(R.drawable.record_play);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
viewHolder.name.setText(record.getName());
|
||||
viewHolder.date.setText(new SimpleDateFormat("HH:mm").format(record.getRecordDate()));
|
||||
|
||||
int position = record.getCurrentPosition();
|
||||
viewHolder.currentPosition.setText(String.format("%02d:%02d",
|
||||
TimeUnit.MILLISECONDS.toMinutes(position),
|
||||
TimeUnit.MILLISECONDS.toSeconds(position) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(position))
|
||||
));
|
||||
//viewHolder.currentPosition.setText("00:00");
|
||||
|
||||
int duration = record.getDuration();
|
||||
viewHolder.duration.setText(String.format("%02d:%02d",
|
||||
TimeUnit.MILLISECONDS.toMinutes(duration),
|
||||
TimeUnit.MILLISECONDS.toSeconds(duration) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration))
|
||||
));
|
||||
|
||||
viewHolder.progressionBar.setMax(100);
|
||||
viewHolder.progressionBar.setProgress(0);
|
||||
viewHolder.progressionBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
if (fromUser) {
|
||||
if (progress == 0) {
|
||||
record.seek(0);
|
||||
} else if (progress == seekBar.getMax()) {
|
||||
if (record.isPlaying()) record.pause();
|
||||
record.seek(0);
|
||||
seekBar.setProgress(0);
|
||||
} else {
|
||||
record.seek(progress);
|
||||
|
||||
int currentPosition = record.getCurrentPosition();
|
||||
viewHolder.currentPosition.setText(String.format("%02d:%02d",
|
||||
TimeUnit.MILLISECONDS.toMinutes(currentPosition),
|
||||
TimeUnit.MILLISECONDS.toSeconds(currentPosition) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(currentPosition))
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
record.setRecordingListener(new RecordingListener() {
|
||||
@Override
|
||||
public void currentPositionChanged(int currentPosition) {
|
||||
viewHolder.currentPosition.setText(String.format("%02d:%02",
|
||||
currentPosition % 60,
|
||||
currentPosition - (currentPosition % 60) * 60, Locale.getDefault()));
|
||||
viewHolder.progressionBar.setProgress(currentPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endOfRecordReached() {
|
||||
record.pause();
|
||||
record.seek(0);
|
||||
viewHolder.progressionBar.setProgress(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return recordings.size();
|
||||
}
|
||||
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
private String DateToHumanDate(Calendar cal) {
|
||||
SimpleDateFormat dateFormat;
|
||||
if (isToday(cal)) {
|
||||
return context.getString(R.string.today);
|
||||
} else if (isYesterday(cal)) {
|
||||
return context.getString(R.string.yesterday);
|
||||
} else {
|
||||
dateFormat = new SimpleDateFormat(context.getResources().getString(R.string.history_date_format));
|
||||
}
|
||||
|
||||
return dateFormat.format(cal.getTime());
|
||||
}
|
||||
|
||||
private boolean isSameDay(Calendar cal1, Calendar cal2) {
|
||||
if (cal1 == null || cal2 == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) &&
|
||||
cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
|
||||
cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));
|
||||
}
|
||||
|
||||
private boolean isToday(Calendar cal) {
|
||||
return isSameDay(cal, Calendar.getInstance());
|
||||
}
|
||||
|
||||
private boolean isYesterday(Calendar cal) {
|
||||
Calendar yesterday = Calendar.getInstance();
|
||||
yesterday.roll(Calendar.DAY_OF_MONTH, -1);
|
||||
return isSameDay(cal, yesterday);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
package org.linphone.recording;
|
||||
|
||||
/*
|
||||
RecordingListFragment.java
|
||||
Copyright (C) 2018 Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.DividerItemDecoration;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.linphone.LinphoneUtils;
|
||||
import org.linphone.R;
|
||||
import org.linphone.activities.LinphoneActivity;
|
||||
import org.linphone.fragments.FragmentsAvailable;
|
||||
import org.linphone.mediastream.Log;
|
||||
import org.linphone.ui.SelectableHelper;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class RecordingListFragment extends Fragment implements View.OnClickListener, AdapterView.OnItemClickListener, RecordingAdapter.ViewHolder.ClickListener, SelectableHelper.DeleteListener {
|
||||
private RecyclerView recordingList;
|
||||
private List<Recording> recordings;
|
||||
private TextView noRecordings;
|
||||
private RecordingAdapter recordingAdapter;
|
||||
private LinearLayoutManager layoutManager;
|
||||
private Context context;
|
||||
private SelectableHelper selectableHelper;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.recordings, container, false);
|
||||
|
||||
context = getActivity().getApplicationContext();
|
||||
selectableHelper = new SelectableHelper(view, this);
|
||||
|
||||
recordingList = view.findViewById(R.id.recording_list);
|
||||
noRecordings = view.findViewById(R.id.no_recordings);
|
||||
|
||||
layoutManager = new LinearLayoutManager(context);
|
||||
recordingList.setLayoutManager(layoutManager);
|
||||
|
||||
//Divider between items
|
||||
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recordingList.getContext(),
|
||||
layoutManager.getOrientation());
|
||||
dividerItemDecoration.setDrawable(context.getResources().getDrawable(R.drawable.divider));
|
||||
recordingList.addItemDecoration(dividerItemDecoration);
|
||||
|
||||
recordings = new ArrayList<>();
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private void hideRecordingListAndDisplayMessageIfEmpty() {
|
||||
if (recordings == null || recordings.isEmpty()) {
|
||||
noRecordings.setVisibility(View.VISIBLE);
|
||||
recordingList.setVisibility(View.GONE);
|
||||
} else {
|
||||
noRecordings.setVisibility(View.GONE);
|
||||
recordingList.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
public void searchForRecordings() {
|
||||
String recordingsDirectory = LinphoneUtils.getRecordingsDirectory(context);
|
||||
File directory = new File(recordingsDirectory);
|
||||
|
||||
if (directory.exists() && directory.isDirectory()) {
|
||||
File[] existingRecordings = directory.listFiles();
|
||||
|
||||
for (File f : existingRecordings) {
|
||||
boolean exists = false;
|
||||
for(Recording r : recordings) {
|
||||
if (r.getRecordPath().equals(f.getPath())) {
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists) recordings.add(new Recording(f.getPath()));
|
||||
}
|
||||
|
||||
Collections.sort(recordings);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
if (LinphoneActivity.isInstanciated()) {
|
||||
LinphoneActivity.instance().selectMenu(FragmentsAvailable.RECORDING_LIST);
|
||||
}
|
||||
|
||||
searchForRecordings();
|
||||
|
||||
hideRecordingListAndDisplayMessageIfEmpty();
|
||||
recordingAdapter = new RecordingAdapter(getActivity().getApplicationContext(), recordings, this, selectableHelper);
|
||||
recordingList.setAdapter(recordingAdapter);
|
||||
selectableHelper.setAdapter(recordingAdapter);
|
||||
selectableHelper.setDialogMessage(R.string.recordings_delete_dialog);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
// Close all opened recordings
|
||||
for (Recording r : recordings) {
|
||||
if (!r.isClosed()) {
|
||||
if (r.isPlaying()) r.pause();
|
||||
r.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
if (recordingAdapter.isEditionEnabled()) {
|
||||
Recording record = recordings.get(position);
|
||||
recordings.remove(position);
|
||||
|
||||
if (record.isPlaying()) record.pause();
|
||||
record.close();
|
||||
|
||||
File recordingFile = new File(record.getRecordPath());
|
||||
recordingFile.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClicked(int position) {
|
||||
if (recordingAdapter.isEditionEnabled()) {
|
||||
recordingAdapter.toggleSelection(position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemLongClicked(int position) {
|
||||
if (!recordingAdapter.isEditionEnabled()) {
|
||||
selectableHelper.enterEditionMode();
|
||||
}
|
||||
recordingAdapter.toggleSelection(position);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeleteSelection(Object[] objectsToDelete) {
|
||||
int size = recordingAdapter.getSelectedItemCount();
|
||||
for (int i = 0; i < size; i++) {
|
||||
Recording record = (Recording) objectsToDelete[i];
|
||||
recordings.remove(record);
|
||||
|
||||
if (record.isPlaying()) record.pause();
|
||||
record.close();
|
||||
|
||||
File recordingFile = new File(record.getRecordPath());
|
||||
recordingFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package org.linphone.recording;
|
||||
|
||||
/*
|
||||
RecordingListener.java
|
||||
Copyright (C) 2018 Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
public interface RecordingListener {
|
||||
void currentPositionChanged(int currentPosition);
|
||||
|
||||
void endOfRecordReached();
|
||||
}
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
BIN
app/src/main/res/drawable-xhdpi/record_pause.png
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
app/src/main/res/drawable-xhdpi/record_play.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
141
app/src/main/res/layout/recording_cell.xml
Normal file
|
@ -0,0 +1,141 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:background="@color/colorH"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/separator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/separator_text"
|
||||
style="@style/font1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:gravity="center" />
|
||||
|
||||
<ImageView
|
||||
android:background="@color/colorE"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_margin="5dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/record_play"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="match_parent"
|
||||
android:adjustViewBounds="true"
|
||||
android:padding="5dp"
|
||||
android:gravity="center"/>
|
||||
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/delete"
|
||||
android:button="@drawable/checkbox"
|
||||
android:contentDescription="@string/content_description_delete"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerInParent="true"
|
||||
android:visibility="gone"
|
||||
android:clickable="false"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingRight="5dp" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toRightOf="@id/record_play"
|
||||
android:layout_toLeftOf="@id/delete"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="10dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/record_description"
|
||||
style="@style/font6"
|
||||
android:lines="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentStart="true">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/record_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView
|
||||
android:text=" - "
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/record_date"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/record_time"
|
||||
android:orientation="horizontal"
|
||||
style="@style/font6"
|
||||
android:lines="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/record_current_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView
|
||||
android:text="/"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/record_duration"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/record_progression_bar"
|
||||
style="@style/Widget.AppCompat.SeekBar.Discrete"
|
||||
android:progressTint="@color/colorA"
|
||||
android:thumbTint="@color/colorA"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:paddingEnd="0dp"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
67
app/src/main/res/layout/recordings.xml
Normal file
|
@ -0,0 +1,67 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:background="@color/colorH"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/top_bar"
|
||||
android:orientation="horizontal"
|
||||
android:background="@color/colorF"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp">
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="0.8"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/edit"
|
||||
android:src="@drawable/delete"
|
||||
android:background="@drawable/toolbar_button"
|
||||
android:contentDescription="@string/content_description_edit_list"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="0.2"
|
||||
android:padding="15dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<include layout="@layout/edit_list"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/recording_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:divider="@color/colorE"
|
||||
android:cacheColorHint="@color/transparent"
|
||||
android:dividerHeight="1dp"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/recording_fetch_in_progress"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:visibility="gone"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/no_recordings"
|
||||
android:text="@string/no_recordings"
|
||||
style="@style/font6"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:layout_centerVertical="true"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
|
@ -289,6 +289,7 @@
|
|||
|
||||
<!-- Recordings -->
|
||||
<string name="no_recordings">No recordings.</string>
|
||||
<string name="recordings_delete_dialog">Do you really want to delete and leave the selected recordings?</string>
|
||||
|
||||
<!-- About -->
|
||||
<string name="menu_send_log">Send log</string>
|
||||
|
|