package de.joel.zoomhelper; import android.annotation.SuppressLint; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; import android.util.AttributeSet; import android.util.Base64; import android.view.View; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.EditText; import android.widget.ImageView; import android.widget.ScrollView; import android.widget.Toast; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.EOFException; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.Objects; class InstantAutoComplete extends androidx.appcompat.widget.AppCompatAutoCompleteTextView { public InstantAutoComplete(Context context) { super(context); } public InstantAutoComplete(Context arg0, AttributeSet arg1) { super(arg0, arg1); } public InstantAutoComplete(Context arg0, AttributeSet arg1, int arg2) { super(arg0, arg1, arg2); } @Override public boolean enoughToFilter() { return true; } } public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final ScrollView scrollview = ((ScrollView) findViewById(R.id.scrollArea)); scrollview.post(() -> scrollview.scrollTo(0, scrollview.getChildAt(0).getHeight())); watchMeetingNameBox(); fillDropdownMeetingName(); if (getLastMeeting() != -1) { try { fillMeeting(getLastMeeting()); } catch (IndexOutOfBoundsException e) { AlertDialog.Builder dialog=new AlertDialog.Builder(this); dialog.setMessage(R.string.resetDataText); dialog.setTitle(R.string.hint); AlertDialog alertDialog=dialog.create(); alertDialog.show(); setLastMeeting(-1); saveMeetingList(new ArrayList<>()); } } watchSaveIcon(); watchAttIcon(); watchDeleteIcon(); watchNewIcon(); watchShareIcon(); } private void watchShareIcon() { ImageView ShareIcon = findViewById(R.id.imageShare); ShareIcon.setOnClickListener(v -> shareMeeting(createCurrMeetingFromUI())); } private void shareMeeting(Meeting meeting) { Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_TEXT, meeting.info()); sendIntent.setType("text/plain"); Intent shareIntent = Intent.createChooser(sendIntent, null); startActivity(shareIntent); } private void watchNewIcon() { ImageView AddIcon = findViewById(R.id.imageAdd); AddIcon.setOnClickListener(v -> fillBlank()); } private void watchAttIcon() { ImageView AttIcon = findViewById(R.id.imageAttend); AttIcon.setOnClickListener(v -> btnJoin_onClick(null)); } private void watchDeleteIcon() { ImageView trashIcon = findViewById(R.id.imageTrash); trashIcon.setOnClickListener(v -> removeMeeting(getLastMeeting())); } private void removeMeeting(int meeting) { ArrayList meetings = getMeetings(); if (meetings.size() > 0) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.app_name); builder.setMessage(getString(R.string.suretoremove, meetings.get(meeting).meetingName)); builder.setPositiveButton(R.string.yes, (dialog, which) -> { dialog.dismiss(); meetings.remove(meeting); saveMeetingList(meetings); if (meetings.size() > 1) { fillDropdownMeetingName(); if (getLastMeeting() > meetings.size()-1) { setLastMeeting(meetings.size()-1); fillMeeting(getLastMeeting()); } } else if (meetings.size() == 1) { setLastMeeting(0); fillDropdownMeetingName(); fillMeeting(getLastMeeting()); } else { setLastMeeting(-1); fillDropdownMeetingName(); fillBlank(); } }); builder.setNegativeButton(R.string.no, (dialog, which) -> { dialog.dismiss(); }); AlertDialog alert = builder.create(); alert.show(); } } private void fillBlank() { EditText editMeetingName = findViewById(R.id.TextMeetingName); EditText editID = findViewById(R.id.textBoxID); EditText editPW = findViewById(R.id.editTextTextPassword2); AutoCompleteTextView editName = findViewById(R.id.textBoxName); EditText editAtt = findViewById(R.id.editAtt); editMeetingName.setText(""); editID.setText(""); editPW.setText(""); editName.setText(""); editName.setAdapter(null); editAtt.setText(""); } private void watchSaveIcon() { ImageView saveIcon = findViewById(R.id.imageSave); saveIcon.setOnClickListener(v -> saveAllMeetings()); } public void watchMeetingNameBox() { EditText meetingNameBox = findViewById(R.id.TextMeetingName); meetingNameBox.setOnFocusChangeListener((v, hasFocus) -> { if (!hasFocus) { fillWithSelectedMeeting(); } }); } public void fillWithSelectedMeeting() { AutoCompleteTextView textMeetingName = findViewById(R.id.TextMeetingName); int search = searchMeetingInList(getMeetings(), textMeetingName.getText().toString()); if (search != -1) { fillMeeting(search); } } @SuppressLint("ClickableViewAccessibility") public void fillDropdownMeetingName() { ArrayList meetings = getMeetings(); String[] meetingNames = new String[meetings.size()]; for (int i = 0; i < meetings.size(); i++) { meetingNames[i] = meetings.get(i).meetingName; } AutoCompleteTextView textMeetingName = findViewById(R.id.TextMeetingName); ImageView dropdown = findViewById(R.id.image); ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, meetingNames); textMeetingName.setAdapter(adapter); textMeetingName.setOnTouchListener((View.OnTouchListener) (paramView, paramMotionEvent) -> { adapter.getFilter().filter(null); textMeetingName.showDropDown(); return false; }); textMeetingName.setOnItemClickListener((arg0, view, arg2, arg3) -> fillWithSelectedMeeting()); dropdown.setOnClickListener(v -> { textMeetingName.showDropDown(); adapter.getFilter().filter(null); }); } public void fillDropdownAttendeeName(int meetingIndex) { Meeting meeting = getMeetings().get(meetingIndex); ArrayList attendees = meeting.attendees; String[] attNames = new String[attendees.size()]; for (int i = 0; i < attendees.size(); i++) { attNames[i] = attendees.get(i).name; } AutoCompleteTextView textName = findViewById(R.id.textBoxName); ImageView dropdown = findViewById(R.id.image2); ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, attNames); textName.setAdapter(adapter); textName.setOnItemClickListener((arg0, view, arg2, arg3) -> fillWithSelectedAtt()); dropdown.setOnClickListener(v -> { textName.showDropDown(); adapter.getFilter().filter(null); }); } private void fillWithSelectedAtt() { AutoCompleteTextView textName = findViewById(R.id.textBoxName); EditText editAtt = findViewById(R.id.editAtt); int found = getMeetings().get(getLastMeeting()).searchAttendee(textName.getText().toString()); editAtt.setText(getMeetings().get(getLastMeeting()).attendees.get(found).num); } public void fillMeeting(int id) { ArrayList meetings = getMeetings(); EditText editMeetingName = findViewById(R.id.TextMeetingName); EditText editID = findViewById(R.id.textBoxID); EditText editPW = findViewById(R.id.editTextTextPassword2); EditText editName = findViewById(R.id.textBoxName); EditText editAtt = findViewById(R.id.editAtt); editID.setError(null); editID.clearFocus(); editMeetingName.setText(meetings.get(id).meetingName); editID.setText(meetings.get(id).meetingID); editPW.setText(meetings.get(id).meetingPWD); editName.setText(meetings.get(id).attendees.get(meetings.get(id).lastAtt).name); editAtt.setText(meetings.get(id).attendees.get(meetings.get(id).lastAtt).num); fillDropdownAttendeeName(id); } private void launchZoomUrl(String url) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } //For Debugging: Show URL in Alert AlertDialog.Builder dialog=new AlertDialog.Builder(this); dialog.setMessage(url); dialog.setTitle("Zoom URL (for testing)"); AlertDialog alertDialog=dialog.create(); alertDialog.show(); } private String buildZoomURL(String confno, String pwd, String name, String attendees) { Uri.Builder builder = new Uri.Builder(); builder.scheme("zoomus") .authority("zoom.us") .appendPath("join") .appendQueryParameter("confno",confno.replace(" ", "")) .appendQueryParameter("pwd", pwd); if (!Objects.equals(attendees, "")) { builder.appendQueryParameter("uname", name + " (" + attendees + ")"); } else builder.appendQueryParameter("uname", name); return builder.build().toString(); } public String meetingsToString(ArrayList listMeetings) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objOutputStream = null; try { objOutputStream = new ObjectOutputStream(byteArrayOutputStream); } catch (IOException e) { e.printStackTrace(); } for (Object obj : listMeetings) { try { if (objOutputStream == null) throw new AssertionError(); objOutputStream.writeObject(obj); } catch (IOException e) { e.printStackTrace(); } try { objOutputStream.reset(); } catch (IOException e) { e.printStackTrace(); } } try { if (objOutputStream == null) throw new AssertionError(); objOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } return Base64.encodeToString(byteArrayOutputStream.toByteArray(), 0); } public ArrayList stringToMeetings(String string) { byte[] bytes = Base64.decode(string, 0); ArrayList listMeetings = new ArrayList<>(); ByteArrayInputStream bis = new ByteArrayInputStream(bytes); ObjectInputStream obj = null; try { obj = new ObjectInputStream(bis); } catch (IOException e) { e.printStackTrace(); } try { while (bis.available() != -1) { //Read object from file if (obj == null) throw new AssertionError(); Meeting meeting = (Meeting) obj.readObject(); listMeetings.add(meeting); } } catch (EOFException ex) { //ex.printStackTrace(); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } return listMeetings; } @SuppressLint("ApplySharedPref") public void saveMeetingList(ArrayList meetingList) { SharedPreferences mPrefs = getPreferences(MODE_PRIVATE); SharedPreferences.Editor prefsEditor = mPrefs.edit(); prefsEditor.putString("Meetings", meetingsToString(meetingList)); prefsEditor.commit(); } @SuppressLint("ApplySharedPref") public void setLastMeeting(int id) { SharedPreferences mPrefs = getPreferences(MODE_PRIVATE); SharedPreferences.Editor prefsEditor = mPrefs.edit(); prefsEditor.putInt("LastMeeting", id); prefsEditor.commit(); } public int getLastMeeting() { SharedPreferences mPrefs = getPreferences(MODE_PRIVATE); return mPrefs.getInt("LastMeeting", -1); } public ArrayList getMeetings() { SharedPreferences mPrefs = getPreferences(MODE_PRIVATE); String value = mPrefs.getString("Meetings", ""); ArrayList meetingList; if (value.equals("")) { meetingList = new ArrayList<>(); } else { meetingList = stringToMeetings(value); } return meetingList; } public int searchMeetingInList(ArrayList meetings, String name) { int found = -1; for (int i = 0; i < meetings.size(); i++) { if (meetings.get(i).meetingName.equals(name)) { found = i; break; } } return found; } public void btnSave_onClick(View view) { saveAllMeetings(); } public void btnJoin_onClick(View view) { saveAllMeetings(); Meeting currMeeting = createCurrMeetingFromUI(); String url = buildZoomURL(currMeeting.meetingID, currMeeting.meetingPWD, currMeeting.attendees.get(currMeeting.lastAtt).name, currMeeting.attendees.get(currMeeting.lastAtt).num); launchZoomUrl(url); } public Meeting createCurrMeetingFromUI() { EditText editMeetingName = findViewById(R.id.TextMeetingName); EditText editID = findViewById(R.id.textBoxID); EditText editPW = findViewById(R.id.editTextTextPassword2); EditText editName = findViewById(R.id.textBoxName); EditText editAtt = findViewById(R.id.editAtt); return new Meeting(editMeetingName.getText().toString(), editID.getText().toString(), editPW.getText().toString(), editName.getText().toString(), editAtt.getText().toString()); } public void saveAllMeetings() { ArrayList listMeetings = getMeetings(); Meeting currMeetingUI = createCurrMeetingFromUI(); if (currMeetingUI.meetingID.equals("")) { EditText editID = findViewById(R.id.textBoxID); editID.requestFocus(); editID.setError("Meeting kann nicht ohne ID gespeichert werden!"); return; } else if (currMeetingUI.meetingName.equals("")) { EditText editMName = findViewById(R.id.TextMeetingName); editMName.setText(currMeetingUI.meetingID); currMeetingUI.meetingName = currMeetingUI.meetingID; } int foundCurr = searchMeetingInList(listMeetings, currMeetingUI.meetingName); if (foundCurr == -1) { listMeetings.add(currMeetingUI); if (listMeetings.size() == 1) { setLastMeeting(0); } else { setLastMeeting(listMeetings.size() - 1); } } else { Meeting currMeeting = getMeetings().get(foundCurr); currMeeting.meetingID = currMeetingUI.meetingID; currMeeting.meetingPWD = currMeetingUI.meetingPWD; currMeeting.updateAttendee(currMeetingUI.attendees.get(0).name, currMeetingUI.attendees.get(0).num); listMeetings.set(foundCurr, currMeeting); setLastMeeting(foundCurr); } saveMeetingList(listMeetings); fillDropdownMeetingName(); fillDropdownAttendeeName(getLastMeeting()); Toast.makeText(getApplicationContext(),"Meeting gespeichert",Toast.LENGTH_SHORT).show(); } } class Attendee implements Serializable { public String name; public String num; public Attendee(String name, String num) { this.name = name; this.num = num; } } class Meeting implements Serializable { public String meetingName; public String meetingID; public String meetingPWD; public ArrayList attendees; public int lastAtt; public Meeting(String meetingName, String meetingID, String meetingPWD, String nameAttendee, String numAttendee) { this.meetingName = meetingName; this.meetingID = meetingID; this.meetingPWD = meetingPWD; this.attendees = new ArrayList<>(); Attendee attendee = new Attendee(nameAttendee, numAttendee); this.attendees.add(attendee); this.lastAtt = 0; } public void addAttendee(String name, String num) { Attendee attendee = new Attendee(name, num); this.attendees.add(attendee); this.lastAtt = attendees.size() - 1; } public int searchAttendee(String name) { int found = -1; for (int i = 0; i < this.attendees.size(); i++) { if (this.attendees.get(i).name.equals(name)) { found = i; break; } } return found; } public void updateAttendee(String name, String num) { int found = searchAttendee(name); if (found == -1) { addAttendee(name, num); } else { this.attendees.get(found).num = num; this.lastAtt = found; } } public String info() { return "Meeting Name: " + this.meetingName + "\n" + "Meeting-ID: " + this.meetingID + "\n" + "Kenncode: " + this.meetingPWD; } }