Simplified gpodder login process
This commit is contained in:
parent
d1426f9774
commit
7b8208a2a7
|
@ -292,19 +292,6 @@
|
|||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".activity.gpoddernet.GpodnetAuthenticationActivity"
|
||||
android:configChanges="orientation"
|
||||
android:label="@string/gpodnet_auth_label">
|
||||
<intent-filter>
|
||||
<action android:name=".activity.gpoddernet.GpodnetAuthenticationActivity"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="de.danoeh.antennapod.activity.PreferenceActivity"/>
|
||||
</activity>
|
||||
|
||||
<receiver android:name=".receiver.ConnectivityActionReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
|
||||
|
|
|
@ -1,395 +0,0 @@
|
|||
package de.danoeh.antennapod.activity.gpoddernet;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.ViewFlipper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import de.danoeh.antennapod.BuildConfig;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
|
||||
import de.danoeh.antennapod.core.sync.SyncService;
|
||||
import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetService;
|
||||
import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetServiceException;
|
||||
import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetDevice;
|
||||
|
||||
/**
|
||||
* Guides the user through the authentication process
|
||||
* Step 1: Request username and password from user
|
||||
* Step 2: Choose device from a list of available devices or create a new one
|
||||
* Step 3: Choose from a list of actions
|
||||
*/
|
||||
public class GpodnetAuthenticationActivity extends AppCompatActivity {
|
||||
private static final String TAG = "GpodnetAuthActivity";
|
||||
|
||||
private ViewFlipper viewFlipper;
|
||||
|
||||
private static final int STEP_DEFAULT = -1;
|
||||
private static final int STEP_LOGIN = 0;
|
||||
private static final int STEP_DEVICE = 1;
|
||||
private static final int STEP_FINISH = 2;
|
||||
|
||||
private int currentStep = -1;
|
||||
|
||||
private GpodnetService service;
|
||||
private volatile String username;
|
||||
private volatile String password;
|
||||
private volatile GpodnetDevice selectedDevice;
|
||||
|
||||
private View[] views;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
setTheme(UserPreferences.getTheme());
|
||||
super.onCreate(savedInstanceState);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
setContentView(R.layout.gpodnetauth_activity);
|
||||
service = new GpodnetService(AntennapodHttpClient.getHttpClient(), GpodnetPreferences.getHostname());
|
||||
|
||||
viewFlipper = findViewById(R.id.viewflipper);
|
||||
LayoutInflater inflater = (LayoutInflater)
|
||||
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
views = new View[]{
|
||||
inflater.inflate(R.layout.gpodnetauth_credentials, viewFlipper, false),
|
||||
inflater.inflate(R.layout.gpodnetauth_device, viewFlipper, false),
|
||||
inflater.inflate(R.layout.gpodnetauth_finish, viewFlipper, false)
|
||||
};
|
||||
for (View view : views) {
|
||||
viewFlipper.addView(view);
|
||||
}
|
||||
advance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void setupLoginView(View view) {
|
||||
final EditText username = view.findViewById(R.id.etxtUsername);
|
||||
final EditText password = view.findViewById(R.id.etxtPassword);
|
||||
final Button login = view.findViewById(R.id.butLogin);
|
||||
final TextView txtvError = view.findViewById(R.id.txtvError);
|
||||
final ProgressBar progressBar = view.findViewById(R.id.progBarLogin);
|
||||
|
||||
password.setOnEditorActionListener((v, actionID, event) ->
|
||||
actionID == EditorInfo.IME_ACTION_GO && login.performClick());
|
||||
|
||||
login.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
final String usernameStr = username.getText().toString();
|
||||
final String passwordStr = password.getText().toString();
|
||||
|
||||
if (usernameHasUnwantedChars(usernameStr)) {
|
||||
txtvError.setText(R.string.gpodnetsync_username_characters_error);
|
||||
txtvError.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
}
|
||||
if (BuildConfig.DEBUG) Log.d(TAG, "Checking login credentials");
|
||||
AsyncTask<GpodnetService, Void, Void> authTask = new AsyncTask<GpodnetService, Void, Void>() {
|
||||
|
||||
volatile Exception exception;
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
login.setEnabled(false);
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
txtvError.setVisibility(View.GONE);
|
||||
// hide the keyboard
|
||||
InputMethodManager inputManager = (InputMethodManager)
|
||||
getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
inputManager.hideSoftInputFromWindow(login.getWindowToken(),
|
||||
InputMethodManager.HIDE_NOT_ALWAYS);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void aVoid) {
|
||||
super.onPostExecute(aVoid);
|
||||
login.setEnabled(true);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
|
||||
if (exception == null) {
|
||||
advance();
|
||||
} else {
|
||||
txtvError.setText(exception.getCause().getMessage());
|
||||
txtvError.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(GpodnetService... params) {
|
||||
try {
|
||||
params[0].authenticate(usernameStr, passwordStr);
|
||||
GpodnetAuthenticationActivity.this.username = usernameStr;
|
||||
GpodnetAuthenticationActivity.this.password = passwordStr;
|
||||
} catch (GpodnetServiceException e) {
|
||||
e.printStackTrace();
|
||||
exception = e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
authTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, service);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupDeviceView(View view) {
|
||||
final EditText deviceID = view.findViewById(R.id.etxtDeviceID);
|
||||
final EditText caption = view.findViewById(R.id.etxtCaption);
|
||||
final Button createNewDevice = view.findViewById(R.id.butCreateNewDevice);
|
||||
final Button chooseDevice = view.findViewById(R.id.butChooseExistingDevice);
|
||||
final TextView txtvError = view.findViewById(R.id.txtvError);
|
||||
final ProgressBar progBarCreateDevice = view.findViewById(R.id.progbarCreateDevice);
|
||||
final Spinner spinnerDevices = view.findViewById(R.id.spinnerChooseDevice);
|
||||
|
||||
|
||||
// load device list
|
||||
final AtomicReference<List<GpodnetDevice>> devices = new AtomicReference<>();
|
||||
new AsyncTask<GpodnetService, Void, List<GpodnetDevice>>() {
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
chooseDevice.setEnabled(false);
|
||||
spinnerDevices.setEnabled(false);
|
||||
createNewDevice.setEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(List<GpodnetDevice> gpodnetDevices) {
|
||||
super.onPostExecute(gpodnetDevices);
|
||||
if (gpodnetDevices != null) {
|
||||
List<String> deviceNames = new ArrayList<>();
|
||||
for (GpodnetDevice device : gpodnetDevices) {
|
||||
deviceNames.add(device.getCaption());
|
||||
}
|
||||
spinnerDevices.setAdapter(new ArrayAdapter<>(GpodnetAuthenticationActivity.this,
|
||||
android.R.layout.simple_spinner_dropdown_item, deviceNames));
|
||||
spinnerDevices.setEnabled(true);
|
||||
if (!deviceNames.isEmpty()) {
|
||||
chooseDevice.setEnabled(true);
|
||||
}
|
||||
devices.set(gpodnetDevices);
|
||||
deviceID.setText(generateDeviceID(gpodnetDevices));
|
||||
createNewDevice.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<GpodnetDevice> doInBackground(GpodnetService... params) {
|
||||
try {
|
||||
return params[0].getDevices();
|
||||
} catch (GpodnetServiceException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}.execute(service);
|
||||
|
||||
|
||||
createNewDevice.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (checkDeviceIDText(deviceID, caption, txtvError, devices.get())) {
|
||||
final String deviceStr = deviceID.getText().toString();
|
||||
final String captionStr = caption.getText().toString();
|
||||
|
||||
new AsyncTask<GpodnetService, Void, GpodnetDevice>() {
|
||||
|
||||
private volatile Exception exception;
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
createNewDevice.setEnabled(false);
|
||||
chooseDevice.setEnabled(false);
|
||||
progBarCreateDevice.setVisibility(View.VISIBLE);
|
||||
txtvError.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(GpodnetDevice result) {
|
||||
super.onPostExecute(result);
|
||||
createNewDevice.setEnabled(true);
|
||||
chooseDevice.setEnabled(true);
|
||||
progBarCreateDevice.setVisibility(View.GONE);
|
||||
if (exception == null) {
|
||||
selectedDevice = result;
|
||||
advance();
|
||||
} else {
|
||||
txtvError.setText(exception.getMessage());
|
||||
txtvError.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GpodnetDevice doInBackground(GpodnetService... params) {
|
||||
try {
|
||||
params[0].configureDevice(deviceStr, captionStr, GpodnetDevice.DeviceType.MOBILE);
|
||||
return new GpodnetDevice(deviceStr, captionStr, GpodnetDevice.DeviceType.MOBILE.toString(), 0);
|
||||
} catch (GpodnetServiceException e) {
|
||||
e.printStackTrace();
|
||||
exception = e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}.execute(service);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
chooseDevice.setOnClickListener(v -> {
|
||||
final int position = spinnerDevices.getSelectedItemPosition();
|
||||
if (position != AdapterView.INVALID_POSITION) {
|
||||
selectedDevice = devices.get().get(position);
|
||||
advance();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private String generateDeviceID(List<GpodnetDevice> gpodnetDevices) {
|
||||
// devices names must be of a certain form:
|
||||
// https://gpoddernet.readthedocs.org/en/latest/api/reference/general.html#devices
|
||||
// This is more restrictive than needed, but I think it makes for more readable names.
|
||||
String baseId = Build.MODEL.replaceAll("\\W", "");
|
||||
String id = baseId;
|
||||
int num = 0;
|
||||
|
||||
while (isDeviceWithIdInList(id, gpodnetDevices)) {
|
||||
id = baseId + "_" + num;
|
||||
num++;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
private boolean isDeviceWithIdInList(String id, List<GpodnetDevice> gpodnetDevices) {
|
||||
if (gpodnetDevices == null) {
|
||||
return false;
|
||||
}
|
||||
for (GpodnetDevice device : gpodnetDevices) {
|
||||
if (device.getId().equals(id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkDeviceIDText(EditText deviceID, EditText caption, TextView txtvError, List<GpodnetDevice> devices) {
|
||||
String text = deviceID.getText().toString();
|
||||
if (text.length() == 0) {
|
||||
txtvError.setText(R.string.gpodnetauth_device_errorEmpty);
|
||||
txtvError.setVisibility(View.VISIBLE);
|
||||
return false;
|
||||
} else if (caption.length() == 0) {
|
||||
txtvError.setText(R.string.gpodnetauth_device_caption_errorEmpty);
|
||||
txtvError.setVisibility(View.VISIBLE);
|
||||
return false;
|
||||
} else {
|
||||
if (devices != null) {
|
||||
if (isDeviceWithIdInList(text, devices)) {
|
||||
txtvError.setText(R.string.gpodnetauth_device_errorAlreadyUsed);
|
||||
txtvError.setVisibility(View.VISIBLE);
|
||||
return false;
|
||||
}
|
||||
txtvError.setVisibility(View.GONE);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void setupFinishView(View view) {
|
||||
final Button sync = view.findViewById(R.id.butSyncNow);
|
||||
final Button back = view.findViewById(R.id.butGoMainscreen);
|
||||
|
||||
sync.setOnClickListener(v -> {
|
||||
finish();
|
||||
SyncService.sync(getApplicationContext());
|
||||
});
|
||||
back.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(GpodnetAuthenticationActivity.this, MainActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
startActivity(intent);
|
||||
});
|
||||
}
|
||||
|
||||
private void writeLoginCredentials() {
|
||||
if (BuildConfig.DEBUG) Log.d(TAG, "Writing login credentials");
|
||||
GpodnetPreferences.setUsername(username);
|
||||
GpodnetPreferences.setPassword(password);
|
||||
GpodnetPreferences.setDeviceID(selectedDevice.getId());
|
||||
}
|
||||
|
||||
private void advance() {
|
||||
if (currentStep < STEP_FINISH) {
|
||||
|
||||
View view = views[currentStep + 1];
|
||||
if (currentStep == STEP_DEFAULT) {
|
||||
setupLoginView(view);
|
||||
} else if (currentStep == STEP_LOGIN) {
|
||||
if (username == null || password == null) {
|
||||
throw new IllegalStateException("Username and password must not be null here");
|
||||
} else {
|
||||
setupDeviceView(view);
|
||||
}
|
||||
} else if (currentStep == STEP_DEVICE) {
|
||||
if (selectedDevice == null) {
|
||||
throw new IllegalStateException("Device must not be null here");
|
||||
} else {
|
||||
writeLoginCredentials();
|
||||
setupFinishView(view);
|
||||
}
|
||||
}
|
||||
if (currentStep != STEP_DEFAULT) {
|
||||
viewFlipper.showNext();
|
||||
}
|
||||
currentStep++;
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean usernameHasUnwantedChars(String username) {
|
||||
Pattern special = Pattern.compile("[!@#$%&*()+=|<>?{}\\[\\]~]");
|
||||
Matcher containsUnwantedChars = special.matcher(username);
|
||||
return containsUnwantedChars.find();
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
package de.danoeh.antennapod.dialog;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
|
||||
import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetService;
|
||||
|
||||
/**
|
||||
* Creates a dialog that lets the user change the hostname for the gpodder.net service.
|
||||
*/
|
||||
public class GpodnetSetHostnameDialog {
|
||||
|
||||
private GpodnetSetHostnameDialog(){}
|
||||
|
||||
private static final String TAG = "GpodnetSetHostnameDialog";
|
||||
|
||||
public static AlertDialog createDialog(final Context context) {
|
||||
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
|
||||
final EditText et = new EditText(context);
|
||||
et.setText(GpodnetPreferences.getHostname());
|
||||
et.setInputType(InputType.TYPE_TEXT_VARIATION_URI);
|
||||
dialog.setTitle(R.string.pref_gpodnet_sethostname_title)
|
||||
.setView(setupContentView(context, et))
|
||||
.setPositiveButton(R.string.confirm_label, (dialog1, which) -> {
|
||||
final Editable e = et.getText();
|
||||
if (e != null) {
|
||||
GpodnetPreferences.setHostname(e.toString());
|
||||
}
|
||||
dialog1.dismiss();
|
||||
})
|
||||
.setNegativeButton(R.string.cancel_label, (dialog1, which) -> dialog1.cancel())
|
||||
.setNeutralButton(R.string.pref_gpodnet_sethostname_use_default_host, (dialog1, which) -> {
|
||||
GpodnetPreferences.setHostname(GpodnetService.DEFAULT_BASE_HOST);
|
||||
dialog1.dismiss();
|
||||
})
|
||||
.setCancelable(true);
|
||||
return dialog.show();
|
||||
}
|
||||
|
||||
private static View setupContentView(Context context, EditText et) {
|
||||
LinearLayout ll = new LinearLayout(context);
|
||||
ll.addView(et);
|
||||
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) et.getLayoutParams();
|
||||
if (params != null) {
|
||||
params.setMargins(8, 8, 8, 8);
|
||||
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
params.height = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
}
|
||||
return ll;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,322 @@
|
|||
package de.danoeh.antennapod.fragment.preferences;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.graphics.Paint;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RadioGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.ViewFlipper;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
|
||||
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
|
||||
import de.danoeh.antennapod.core.sync.SyncService;
|
||||
import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetService;
|
||||
import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetDevice;
|
||||
import de.danoeh.antennapod.core.util.FileNameGenerator;
|
||||
import de.danoeh.antennapod.core.util.IntentUtils;
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Guides the user through the authentication process.
|
||||
*/
|
||||
public class GpodderAuthenticationFragment extends DialogFragment {
|
||||
public static final String TAG = "GpodnetAuthActivity";
|
||||
|
||||
private ViewFlipper viewFlipper;
|
||||
|
||||
private static final int STEP_DEFAULT = -1;
|
||||
private static final int STEP_HOSTNAME = 0;
|
||||
private static final int STEP_LOGIN = 1;
|
||||
private static final int STEP_DEVICE = 2;
|
||||
private static final int STEP_FINISH = 3;
|
||||
|
||||
private int currentStep = -1;
|
||||
|
||||
private GpodnetService service;
|
||||
private volatile String username;
|
||||
private volatile String password;
|
||||
private volatile GpodnetDevice selectedDevice;
|
||||
private List<GpodnetDevice> devices;
|
||||
private List<List<String>> synchronizedDevices;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
|
||||
AlertDialog.Builder dialog = new AlertDialog.Builder(getContext());
|
||||
dialog.setTitle(GpodnetService.DEFAULT_BASE_HOST);
|
||||
dialog.setNegativeButton(R.string.cancel_label, null);
|
||||
dialog.setCancelable(false);
|
||||
this.setCancelable(false);
|
||||
|
||||
View root = View.inflate(getContext(), R.layout.gpodnetauth_dialog, null);
|
||||
viewFlipper = root.findViewById(R.id.viewflipper);
|
||||
advance();
|
||||
dialog.setView(root);
|
||||
|
||||
return dialog.create();
|
||||
}
|
||||
|
||||
private void setupHostView(View view) {
|
||||
final Button selectHost = view.findViewById(R.id.chooseHostButton);
|
||||
final RadioGroup serverRadioGroup = view.findViewById(R.id.serverRadioGroup);
|
||||
final EditText serverUrlText = view.findViewById(R.id.serverUrlText);
|
||||
if (!GpodnetService.DEFAULT_BASE_HOST.equals(GpodnetPreferences.getHostname())) {
|
||||
serverUrlText.setText(GpodnetPreferences.getHostname());
|
||||
}
|
||||
final TextInputLayout serverUrlTextInput = view.findViewById(R.id.serverUrlTextInput);
|
||||
serverRadioGroup.setOnCheckedChangeListener((group, checkedId) -> {
|
||||
serverUrlTextInput.setVisibility(checkedId == R.id.customServerRadio ? View.VISIBLE : View.GONE);
|
||||
});
|
||||
selectHost.setOnClickListener(v -> {
|
||||
if (serverRadioGroup.getCheckedRadioButtonId() == R.id.customServerRadio) {
|
||||
GpodnetPreferences.setHostname(serverUrlText.getText().toString());
|
||||
} else {
|
||||
GpodnetPreferences.setHostname(GpodnetService.DEFAULT_BASE_HOST);
|
||||
}
|
||||
service = new GpodnetService(AntennapodHttpClient.getHttpClient(), GpodnetPreferences.getHostname());
|
||||
getDialog().setTitle(GpodnetPreferences.getHostname());
|
||||
advance();
|
||||
});
|
||||
}
|
||||
|
||||
private void setupLoginView(View view) {
|
||||
final EditText username = view.findViewById(R.id.etxtUsername);
|
||||
final EditText password = view.findViewById(R.id.etxtPassword);
|
||||
final Button login = view.findViewById(R.id.butLogin);
|
||||
final TextView txtvError = view.findViewById(R.id.credentialsError);
|
||||
final ProgressBar progressBar = view.findViewById(R.id.progBarLogin);
|
||||
final TextView createAccount = view.findViewById(R.id.createAccountButton);
|
||||
|
||||
createAccount.setPaintFlags(createAccount.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
|
||||
createAccount.setOnClickListener(v -> IntentUtils.openInBrowser(getContext(), "https://gpodder.net/register/"));
|
||||
|
||||
password.setOnEditorActionListener((v, actionID, event) ->
|
||||
actionID == EditorInfo.IME_ACTION_GO && login.performClick());
|
||||
|
||||
login.setOnClickListener(v -> {
|
||||
final String usernameStr = username.getText().toString();
|
||||
final String passwordStr = password.getText().toString();
|
||||
|
||||
if (usernameHasUnwantedChars(usernameStr)) {
|
||||
txtvError.setText(R.string.gpodnetsync_username_characters_error);
|
||||
txtvError.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
}
|
||||
|
||||
login.setEnabled(false);
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
txtvError.setVisibility(View.GONE);
|
||||
InputMethodManager inputManager = (InputMethodManager) getContext()
|
||||
.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
inputManager.hideSoftInputFromWindow(login.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
|
||||
|
||||
Completable.fromAction(() -> {
|
||||
service.authenticate(usernameStr, passwordStr);
|
||||
devices = service.getDevices();
|
||||
synchronizedDevices = service.getSynchronizedDevices();
|
||||
GpodderAuthenticationFragment.this.username = usernameStr;
|
||||
GpodderAuthenticationFragment.this.password = passwordStr;
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(() -> {
|
||||
login.setEnabled(true);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
advance();
|
||||
}, error -> {
|
||||
login.setEnabled(true);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
txtvError.setText(error.getCause().getMessage());
|
||||
txtvError.setVisibility(View.VISIBLE);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void setupDeviceView(View view) {
|
||||
final EditText deviceName = view.findViewById(R.id.deviceName);
|
||||
final LinearLayout deviceGroups = view.findViewById(R.id.deviceGroups);
|
||||
deviceName.setText(generateDeviceName());
|
||||
|
||||
MaterialButton newGroupButton = view.findViewById(R.id.startNewGroupButton);
|
||||
newGroupButton.setOnClickListener(v -> createDevice(view, null));
|
||||
|
||||
for (List<String> syncGroup : synchronizedDevices) {
|
||||
StringBuilder devicesString = new StringBuilder();
|
||||
for (int i = 0; i < syncGroup.size(); i++) {
|
||||
String deviceId = syncGroup.get(i);
|
||||
devicesString.append(findDevice(deviceId).getCaption());
|
||||
if (i != syncGroup.size() - 1) {
|
||||
devicesString.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
View groupView = View.inflate(getContext(), R.layout.gpodnetauth_device_group, null);
|
||||
((TextView) groupView.findViewById(R.id.groupContents)).setText(devicesString.toString());
|
||||
groupView.findViewById(R.id.selectGroupButton).setOnClickListener(v -> createDevice(view, syncGroup));
|
||||
deviceGroups.addView(groupView);
|
||||
}
|
||||
}
|
||||
|
||||
private void createDevice(View view, List<String> group) {
|
||||
final EditText deviceName = view.findViewById(R.id.deviceName);
|
||||
final TextView txtvError = view.findViewById(R.id.deviceSelectError);
|
||||
final ProgressBar progBarCreateDevice = view.findViewById(R.id.progbarCreateDevice);
|
||||
final LinearLayout deviceGroups = view.findViewById(R.id.deviceGroups);
|
||||
final MaterialButton newGroupButton = view.findViewById(R.id.startNewGroupButton);
|
||||
|
||||
String deviceNameStr = deviceName.getText().toString();
|
||||
if (isDeviceInList(deviceNameStr)) {
|
||||
return;
|
||||
}
|
||||
deviceGroups.setVisibility(View.GONE);
|
||||
progBarCreateDevice.setVisibility(View.VISIBLE);
|
||||
txtvError.setVisibility(View.GONE);
|
||||
newGroupButton.setVisibility(View.GONE);
|
||||
deviceName.setEnabled(false);
|
||||
|
||||
Observable.fromCallable(() -> {
|
||||
String deviceId = generateDeviceId(deviceNameStr);
|
||||
service.configureDevice(deviceId, deviceNameStr, GpodnetDevice.DeviceType.MOBILE);
|
||||
|
||||
if (group != null) {
|
||||
List<String> newGroup = new ArrayList<>(group);
|
||||
newGroup.add(deviceId);
|
||||
service.linkDevices(newGroup);
|
||||
}
|
||||
return new GpodnetDevice(deviceId, deviceNameStr, GpodnetDevice.DeviceType.MOBILE.toString(), 0);
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(device -> {
|
||||
progBarCreateDevice.setVisibility(View.GONE);
|
||||
selectedDevice = device;
|
||||
advance();
|
||||
}, error -> {
|
||||
deviceName.setEnabled(true);
|
||||
newGroupButton.setVisibility(View.VISIBLE);
|
||||
deviceGroups.setVisibility(View.VISIBLE);
|
||||
progBarCreateDevice.setVisibility(View.GONE);
|
||||
txtvError.setText(error.getMessage());
|
||||
txtvError.setVisibility(View.VISIBLE);
|
||||
});
|
||||
}
|
||||
|
||||
private String generateDeviceName() {
|
||||
String baseName = getString(R.string.gpodnetauth_device_name_default, Build.MODEL);
|
||||
String name = baseName;
|
||||
int num = 1;
|
||||
while (isDeviceInList(name)) {
|
||||
name = baseName + " (" + num + ")";
|
||||
num++;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
private String generateDeviceId(String name) {
|
||||
// devices names must be of a certain form:
|
||||
// https://gpoddernet.readthedocs.org/en/latest/api/reference/general.html#devices
|
||||
return FileNameGenerator.generateFileName(name).replaceAll("\\W", "_").toLowerCase(Locale.US);
|
||||
}
|
||||
|
||||
private boolean isDeviceInList(String name) {
|
||||
if (devices == null) {
|
||||
return false;
|
||||
}
|
||||
String id = generateDeviceId(name);
|
||||
for (GpodnetDevice device : devices) {
|
||||
if (device.getId().equals(id) || device.getCaption().equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private GpodnetDevice findDevice(String id) {
|
||||
if (devices == null) {
|
||||
return null;
|
||||
}
|
||||
for (GpodnetDevice device : devices) {
|
||||
if (device.getId().equals(id)) {
|
||||
return device;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void setupFinishView(View view) {
|
||||
final Button sync = view.findViewById(R.id.butSyncNow);
|
||||
|
||||
sync.setOnClickListener(v -> {
|
||||
dismiss();
|
||||
SyncService.sync(getContext());
|
||||
});
|
||||
}
|
||||
|
||||
private void writeLoginCredentials() {
|
||||
GpodnetPreferences.setUsername(username);
|
||||
GpodnetPreferences.setPassword(password);
|
||||
GpodnetPreferences.setDeviceID(selectedDevice.getId());
|
||||
}
|
||||
|
||||
private void advance() {
|
||||
if (currentStep < STEP_FINISH) {
|
||||
|
||||
View view = viewFlipper.getChildAt(currentStep + 1);
|
||||
if (currentStep == STEP_DEFAULT) {
|
||||
setupHostView(view);
|
||||
} else if (currentStep == STEP_HOSTNAME) {
|
||||
setupLoginView(view);
|
||||
} else if (currentStep == STEP_LOGIN) {
|
||||
if (username == null || password == null) {
|
||||
throw new IllegalStateException("Username and password must not be null here");
|
||||
} else {
|
||||
setupDeviceView(view);
|
||||
}
|
||||
} else if (currentStep == STEP_DEVICE) {
|
||||
if (selectedDevice == null) {
|
||||
throw new IllegalStateException("Device must not be null here");
|
||||
} else {
|
||||
writeLoginCredentials();
|
||||
setupFinishView(view);
|
||||
}
|
||||
}
|
||||
if (currentStep != STEP_DEFAULT) {
|
||||
viewFlipper.showNext();
|
||||
}
|
||||
currentStep++;
|
||||
} else {
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean usernameHasUnwantedChars(String username) {
|
||||
Pattern special = Pattern.compile("[!@#$%&*()+=|<>?{}\\[\\]~]");
|
||||
Matcher containsUnwantedChars = special.matcher(username);
|
||||
return containsUnwantedChars.find();
|
||||
}
|
||||
}
|
|
@ -14,19 +14,16 @@ import de.danoeh.antennapod.core.event.SyncServiceEvent;
|
|||
import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
|
||||
import de.danoeh.antennapod.core.sync.SyncService;
|
||||
import de.danoeh.antennapod.dialog.AuthenticationDialog;
|
||||
import de.danoeh.antennapod.dialog.GpodnetSetHostnameDialog;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
|
||||
public class GpodderPreferencesFragment extends PreferenceFragmentCompat {
|
||||
private static final String PREF_GPODNET_LOGIN = "pref_gpodnet_authenticate";
|
||||
private static final String PREF_GPODNET_SETLOGIN_INFORMATION = "pref_gpodnet_setlogin_information";
|
||||
private static final String PREF_GPODNET_SYNC = "pref_gpodnet_sync";
|
||||
private static final String PREF_GPODNET_FORCE_FULL_SYNC = "pref_gpodnet_force_full_sync";
|
||||
private static final String PREF_GPODNET_LOGOUT = "pref_gpodnet_logout";
|
||||
private static final String PREF_GPODNET_HOSTNAME = "pref_gpodnet_hostname";
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
|
@ -51,6 +48,7 @@ public class GpodderPreferencesFragment extends PreferenceFragmentCompat {
|
|||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
||||
public void syncStatusChanged(SyncServiceEvent event) {
|
||||
updateGpodnetPreferenceScreen();
|
||||
if (!GpodnetPreferences.loggedIn()) {
|
||||
return;
|
||||
}
|
||||
|
@ -66,6 +64,10 @@ public class GpodderPreferencesFragment extends PreferenceFragmentCompat {
|
|||
private void setupGpodderScreen() {
|
||||
final Activity activity = getActivity();
|
||||
|
||||
findPreference(PREF_GPODNET_LOGIN).setOnPreferenceClickListener(preference -> {
|
||||
new GpodderAuthenticationFragment().show(getChildFragmentManager(), GpodderAuthenticationFragment.TAG);
|
||||
return true;
|
||||
});
|
||||
findPreference(PREF_GPODNET_SETLOGIN_INFORMATION)
|
||||
.setOnPreferenceClickListener(preference -> {
|
||||
AuthenticationDialog dialog = new AuthenticationDialog(activity,
|
||||
|
@ -94,11 +96,6 @@ public class GpodderPreferencesFragment extends PreferenceFragmentCompat {
|
|||
updateGpodnetPreferenceScreen();
|
||||
return true;
|
||||
});
|
||||
findPreference(PREF_GPODNET_HOSTNAME).setOnPreferenceClickListener(preference -> {
|
||||
GpodnetSetHostnameDialog.createDialog(activity).setOnDismissListener(
|
||||
dialog -> updateGpodnetPreferenceScreen());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void updateGpodnetPreferenceScreen() {
|
||||
|
@ -119,7 +116,6 @@ public class GpodderPreferencesFragment extends PreferenceFragmentCompat {
|
|||
} else {
|
||||
findPreference(PREF_GPODNET_LOGOUT).setSummary(null);
|
||||
}
|
||||
findPreference(PREF_GPODNET_HOSTNAME).setSummary(GpodnetPreferences.getHostname());
|
||||
}
|
||||
|
||||
private void updateLastGpodnetSyncReport(boolean successful, long lastTime) {
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<ViewFlipper
|
||||
android:id="@+id/viewflipper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
</ScrollView>
|
|
@ -1,96 +1,97 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/gpodder_icon" />
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@id/txtvDescription"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/gpodnetauth_login_descr"
|
||||
android:layout_below="@id/icon"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textColor="?android:attr/textColorPrimary"/>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etxtUsername"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/username_label"
|
||||
android:layout_below="@id/txtvDescription"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:cursorVisible="true"
|
||||
android:maxLines="1"
|
||||
android:inputType="text"
|
||||
android:imeOptions="actionNext|flagNoFullscreen"
|
||||
android:nextFocusForward="@id/etxtPassword"/>
|
||||
<ImageView
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:src="@drawable/gpodder_icon"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etxtPassword"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/password_label"
|
||||
android:layout_below="@id/etxtUsername"
|
||||
android:inputType="textPassword"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:cursorVisible="true"
|
||||
android:imeOptions="actionGo|flagNoFullscreen"
|
||||
android:imeActionLabel="@string/gpodnetauth_login_butLabel"/>
|
||||
<TextView
|
||||
android:id="@+id/createAccountButton"
|
||||
android:layout_width="0dp"
|
||||
android:textAlignment="textEnd"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:textColor="?colorAccent"
|
||||
android:layout_weight="1"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:text="@string/create_account"/>
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/butLogin"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/etxtPassword"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:text="@string/gpodnetauth_login_butLabel"/>
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvError"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/etxtPassword"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_toLeftOf="@id/butLogin"
|
||||
android:layout_toStartOf="@id/butLogin"
|
||||
android:textColor="@color/download_failed_red"
|
||||
android:textSize="@dimen/text_size_small"
|
||||
android:maxLines="2"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:layout_margin="16dp"
|
||||
tools:text="Error message"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/etxtUsername"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/username_label"
|
||||
android:lines="1"
|
||||
android:imeOptions="actionNext|flagNoFullscreen"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progBarLogin"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:layout_alignTop="@+id/butLogin"
|
||||
android:layout_toLeftOf="@+id/butLogin"
|
||||
android:layout_toStartOf="@+id/butLogin"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/gpodnetauth_login_register"
|
||||
android:autoLink="web"
|
||||
android:layout_below="@id/butLogin"/>
|
||||
</RelativeLayout>
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/etxtPassword"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/password_label"
|
||||
android:inputType="textPassword"
|
||||
android:lines="1"
|
||||
android:imeOptions="actionNext|flagNoFullscreen"
|
||||
android:imeActionLabel="@string/gpodnetauth_login_butLabel"/>
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="end|center_vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/credentialsError"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/download_failed_red"
|
||||
android:textSize="@dimen/text_size_small"
|
||||
android:maxLines="2"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
tools:text="Error message"
|
||||
tools:background="@android:color/holo_green_dark"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progBarLogin"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:layout_gravity="right"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/butLogin"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/gpodnetauth_login_butLabel"/>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
|
@ -1,114 +1,62 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp">
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/deviceName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/gpodnetauth_device_name"
|
||||
android:lines="1"
|
||||
android:imeOptions="actionNext|flagNoFullscreen"/>
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/gpodnetauth_device_title"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginBottom="16dp"
|
||||
style="@style/AntennaPod.TextView.Heading"/>
|
||||
style="@style/AntennaPod.TextView.Heading"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/gpodnetauth_sync_groups"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvDescription"
|
||||
android:id="@+id/deviceSelectError"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/gpodnetauth_device_descr"
|
||||
android:layout_below="@id/txtvTitle"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textColor="?android:attr/textColorPrimary"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etxtCaption"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/gpodnetauth_device_caption"
|
||||
android:layout_below="@id/txtvDescription"
|
||||
android:imeOptions="flagNoFullscreen"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvDeviceID"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/gpodnetauth_device_deviceID"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:layout_below="@id/etxtCaption"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etxtDeviceID"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/txtvDeviceID"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:imeOptions="flagNoFullscreen"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/butCreateNewDevice"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_below="@id/etxtDeviceID"
|
||||
android:text="@string/gpodnetauth_device_butCreateNewDevice"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvError"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@id/etxtDeviceID"
|
||||
android:layout_toLeftOf="@id/butCreateNewDevice"
|
||||
android:layout_toStartOf="@id/butCreateNewDevice"
|
||||
android:textColor="@color/download_failed_red"
|
||||
android:textSize="@dimen/text_size_small"
|
||||
android:visibility="gone"
|
||||
tools:text="Error message"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/deviceGroups"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/startNewGroupButton"
|
||||
android:text="@string/gpodnetauth_sync_group_new"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="?attr/materialButtonOutlinedStyle"
|
||||
android:layout_gravity="right"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progbarCreateDevice"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignTop="@id/butCreateNewDevice"
|
||||
android:layout_toLeftOf="@id/butCreateNewDevice"
|
||||
android:layout_toStartOf="@id/butCreateNewDevice"
|
||||
android:textColor="@color/download_failed_red"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:visibility="gone"
|
||||
/>
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvChooseExistingDevice"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/gpodnetauth_device_chooseExistingDevice"
|
||||
android:layout_below="@id/butCreateNewDevice"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:layout_marginTop="32dp"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/butChooseExistingDevice"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/gpodnetauth_device_butChoose"
|
||||
android:layout_below="@+id/spinnerChooseDevice"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinnerChooseDevice"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/txtvChooseExistingDevice"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="8dp">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:strokeWidth="2dp"
|
||||
app:strokeColor="?attr/currently_playing_background">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp">
|
||||
<TextView
|
||||
android:id="@+id/groupContents"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/selectGroupButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="right"
|
||||
style="?attr/borderlessButtonStyle"
|
||||
android:text="@string/gpodnetauth_sync_group_select"/>
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
</FrameLayout>
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:clipToPadding="false">
|
||||
<ViewFlipper
|
||||
android:id="@+id/viewflipper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inAnimation="@anim/slide_right_in"
|
||||
android:outAnimation="@anim/slide_left_out">
|
||||
|
||||
<include layout="@layout/gpodnetauth_host" />
|
||||
<include layout="@layout/gpodnetauth_credentials" />
|
||||
<include layout="@layout/gpodnetauth_device" />
|
||||
<include layout="@layout/gpodnetauth_finish" />
|
||||
|
||||
</ViewFlipper>
|
||||
</ScrollView>
|
|
@ -1,46 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp">
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:src="@drawable/gpodder_icon" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/icon"
|
||||
android:text="@string/gpodnetauth_finish_title"
|
||||
style="@style/AntennaPod.TextView.Heading"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvDescription"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/gpodnetauth_finish_descr"
|
||||
android:layout_below="@id/txtvTitle"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/butSyncNow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/txtvDescription"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/gpodnetauth_finish_butsyncnow"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/butGoMainscreen"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/butSyncNow"
|
||||
android:text="@string/gpodnetauth_finish_butgomainscreen"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,50 @@
|
|||
<?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="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/serverRadioGroup"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<RadioButton
|
||||
android:id="@+id/officialServerRadio"
|
||||
android:text="@string/gpodnetauth_server_official"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="true"/>
|
||||
<RadioButton
|
||||
android:id="@+id/customServerRadio"
|
||||
android:text="@string/gpodnetauth_server_custom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
</RadioGroup>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/serverUrlTextInput"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/serverUrlText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/gpodnetauth_host"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:lines="1"
|
||||
android:imeOptions="actionNext|flagNoFullscreen" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/chooseHostButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="right|end"
|
||||
android:text="@string/gpodnetauth_select_server"/>
|
||||
|
||||
</LinearLayout>
|
|
@ -1,13 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<PreferenceScreen
|
||||
<Preference
|
||||
android:key="pref_gpodnet_description"
|
||||
android:icon="@drawable/gpodder_icon"
|
||||
android:summary="@string/gpodnet_description"/>
|
||||
<Preference
|
||||
android:key="pref_gpodnet_authenticate"
|
||||
android:title="@string/pref_gpodnet_authenticate_title"
|
||||
android:summary="@string/pref_gpodnet_authenticate_sum">
|
||||
<intent android:action=".activity.gpoddernet.GpodnetAuthenticationActivity"/>
|
||||
</PreferenceScreen>
|
||||
android:summary="@string/pref_gpodnet_authenticate_sum"/>
|
||||
<Preference
|
||||
android:key="pref_gpodnet_setlogin_information"
|
||||
android:title="@string/pref_gpodnet_setlogin_information_title"
|
||||
|
@ -23,8 +24,5 @@
|
|||
<Preference
|
||||
android:key="pref_gpodnet_logout"
|
||||
android:title="@string/pref_gpodnet_logout_title"/>
|
||||
<Preference
|
||||
android:key="pref_gpodnet_hostname"
|
||||
android:title="@string/pref_gpodnet_sethostname_title"/>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
|
|
@ -2,6 +2,7 @@ package de.danoeh.antennapod.core.sync.gpoddernet;
|
|||
|
||||
import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
import de.danoeh.antennapod.core.BuildConfig;
|
||||
import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
|
||||
import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetDevice;
|
||||
import de.danoeh.antennapod.core.sync.model.EpisodeAction;
|
||||
|
@ -36,6 +37,7 @@ import java.net.URL;
|
|||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
@ -47,6 +49,7 @@ public class GpodnetService implements ISyncService {
|
|||
public static final String TAG = "GpodnetService";
|
||||
public static final String DEFAULT_BASE_HOST = "gpodder.net";
|
||||
private static final String BASE_SCHEME = "https";
|
||||
private static final int PORT = 443;
|
||||
private static final int UPLOAD_BULK_SIZE = 30;
|
||||
private static final MediaType TEXT = MediaType.parse("plain/text; charset=utf-8");
|
||||
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
|
||||
|
@ -71,7 +74,8 @@ public class GpodnetService implements ISyncService {
|
|||
public List<GpodnetTag> getTopTags(int count) throws GpodnetServiceException {
|
||||
URL url;
|
||||
try {
|
||||
url = new URI(BASE_SCHEME, baseHost, String.format(Locale.US, "/api/2/tags/%d.json", count), null).toURL();
|
||||
url = new URI(BASE_SCHEME, null, baseHost, PORT,
|
||||
String.format(Locale.US, "/api/2/tags/%d.json", count), null, null).toURL();
|
||||
} catch (MalformedURLException | URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
throw new GpodnetServiceException(e);
|
||||
|
@ -104,8 +108,8 @@ public class GpodnetService implements ISyncService {
|
|||
public List<GpodnetPodcast> getPodcastsForTag(@NonNull GpodnetTag tag, int count)
|
||||
throws GpodnetServiceException {
|
||||
try {
|
||||
URL url = new URI(BASE_SCHEME, baseHost, String.format(Locale.US,
|
||||
"/api/2/tag/%s/%d.json", tag.getTag(), count), null).toURL();
|
||||
URL url = new URI(BASE_SCHEME, null, baseHost, PORT,
|
||||
String.format(Locale.US, "/api/2/tag/%s/%d.json", tag.getTag(), count), null, null).toURL();
|
||||
Request.Builder request = new Request.Builder().url(url);
|
||||
String response = executeRequest(request);
|
||||
|
||||
|
@ -130,7 +134,8 @@ public class GpodnetService implements ISyncService {
|
|||
}
|
||||
|
||||
try {
|
||||
URL url = new URI(BASE_SCHEME, baseHost, String.format(Locale.US, "/toplist/%d.json", count), null).toURL();
|
||||
URL url = new URI(BASE_SCHEME, null, baseHost, PORT,
|
||||
String.format(Locale.US, "/toplist/%d.json", count), null, null).toURL();
|
||||
Request.Builder request = new Request.Builder().url(url);
|
||||
String response = executeRequest(request);
|
||||
|
||||
|
@ -161,8 +166,8 @@ public class GpodnetService implements ISyncService {
|
|||
}
|
||||
|
||||
try {
|
||||
URL url = new URI(BASE_SCHEME, baseHost,
|
||||
String.format(Locale.US, "/suggestions/%d.json", count), null).toURL();
|
||||
URL url = new URI(BASE_SCHEME, null, baseHost, PORT,
|
||||
String.format(Locale.US, "/suggestions/%d.json", count), null, null).toURL();
|
||||
Request.Builder request = new Request.Builder().url(url);
|
||||
String response = executeRequest(request);
|
||||
|
||||
|
@ -187,7 +192,7 @@ public class GpodnetService implements ISyncService {
|
|||
.format(Locale.US, "q=%s&scale_logo=%d", query, scaledLogoSize) : String
|
||||
.format("q=%s", query);
|
||||
try {
|
||||
URL url = new URI(BASE_SCHEME, null, baseHost, -1, "/search.json",
|
||||
URL url = new URI(BASE_SCHEME, null, baseHost, PORT, "/search.json",
|
||||
parameters, null).toURL();
|
||||
Request.Builder request = new Request.Builder().url(url);
|
||||
String response = executeRequest(request);
|
||||
|
@ -214,7 +219,8 @@ public class GpodnetService implements ISyncService {
|
|||
public List<GpodnetDevice> getDevices() throws GpodnetServiceException {
|
||||
requireLoggedIn();
|
||||
try {
|
||||
URL url = new URI(BASE_SCHEME, baseHost, String.format("/api/2/devices/%s.json", username), null).toURL();
|
||||
URL url = new URI(BASE_SCHEME, null, baseHost, PORT,
|
||||
String.format("/api/2/devices/%s.json", username), null, null).toURL();
|
||||
Request.Builder request = new Request.Builder().url(url);
|
||||
String response = executeRequest(request);
|
||||
JSONArray devicesArray = new JSONArray(response);
|
||||
|
@ -225,6 +231,45 @@ public class GpodnetService implements ISyncService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns synchronization status of devices.
|
||||
* <p/>
|
||||
* This method requires authentication.
|
||||
*
|
||||
* @throws GpodnetServiceAuthenticationException If there is an authentication error.
|
||||
*/
|
||||
public List<List<String>> getSynchronizedDevices() throws GpodnetServiceException {
|
||||
requireLoggedIn();
|
||||
try {
|
||||
URL url = new URI(BASE_SCHEME, null, baseHost, PORT,
|
||||
String.format("/api/2/sync-devices/%s.json", username), null, null).toURL();
|
||||
Request.Builder request = new Request.Builder().url(url);
|
||||
String response = executeRequest(request);
|
||||
JSONObject syncStatus = new JSONObject(response);
|
||||
List<List<String>> result = new ArrayList<>();
|
||||
|
||||
JSONArray synchronizedDevices = syncStatus.getJSONArray("synchronized");
|
||||
for (int i = 0; i < synchronizedDevices.length(); i++) {
|
||||
JSONArray groupDevices = synchronizedDevices.getJSONArray(i);
|
||||
List<String> group = new ArrayList<>();
|
||||
for (int j = 0; j < groupDevices.length(); j++) {
|
||||
group.add(groupDevices.getString(j));
|
||||
}
|
||||
result.add(group);
|
||||
}
|
||||
|
||||
JSONArray notSynchronizedDevices = syncStatus.getJSONArray("not-synchronized");
|
||||
for (int i = 0; i < notSynchronizedDevices.length(); i++) {
|
||||
result.add(Collections.singletonList(notSynchronizedDevices.getString(i)));
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (JSONException | MalformedURLException | URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
throw new GpodnetServiceException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the device of a given user.
|
||||
* <p/>
|
||||
|
@ -237,8 +282,8 @@ public class GpodnetService implements ISyncService {
|
|||
throws GpodnetServiceException {
|
||||
requireLoggedIn();
|
||||
try {
|
||||
URL url = new URI(BASE_SCHEME, baseHost, String.format(
|
||||
"/api/2/devices/%s/%s.json", username, deviceId), null).toURL();
|
||||
URL url = new URI(BASE_SCHEME, null, baseHost, PORT,
|
||||
String.format("/api/2/devices/%s/%s.json", username, deviceId), null, null).toURL();
|
||||
String content;
|
||||
if (caption != null || type != null) {
|
||||
JSONObject jsonContent = new JSONObject();
|
||||
|
@ -261,6 +306,39 @@ public class GpodnetService implements ISyncService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Links devices for synchronization.
|
||||
* <p/>
|
||||
* This method requires authentication.
|
||||
*
|
||||
* @throws GpodnetServiceAuthenticationException If there is an authentication error.
|
||||
*/
|
||||
public void linkDevices(@NonNull List<String> deviceIds) throws GpodnetServiceException {
|
||||
requireLoggedIn();
|
||||
try {
|
||||
final URL url = new URI(BASE_SCHEME, null, baseHost, PORT,
|
||||
String.format("/api/2/sync-devices/%s.json", username), null, null).toURL();
|
||||
JSONObject jsonContent = new JSONObject();
|
||||
JSONArray group = new JSONArray();
|
||||
for (String deviceId : deviceIds) {
|
||||
group.put(deviceId);
|
||||
}
|
||||
|
||||
JSONArray synchronizedGroups = new JSONArray();
|
||||
synchronizedGroups.put(group);
|
||||
jsonContent.put("synchronize", synchronizedGroups);
|
||||
jsonContent.put("stop-synchronize", new JSONArray());
|
||||
|
||||
Log.d("aaaa", jsonContent.toString());
|
||||
RequestBody body = RequestBody.create(JSON, jsonContent.toString());
|
||||
Request.Builder request = new Request.Builder().post(body).url(url);
|
||||
executeRequest(request);
|
||||
} catch (JSONException | MalformedURLException | URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
throw new GpodnetServiceException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the subscriptions of a specific device.
|
||||
* <p/>
|
||||
|
@ -273,8 +351,8 @@ public class GpodnetService implements ISyncService {
|
|||
public String getSubscriptionsOfDevice(@NonNull String deviceId) throws GpodnetServiceException {
|
||||
requireLoggedIn();
|
||||
try {
|
||||
URL url = new URI(BASE_SCHEME, baseHost, String.format(
|
||||
"/subscriptions/%s/%s.opml", username, deviceId), null).toURL();
|
||||
URL url = new URI(BASE_SCHEME, null, baseHost, PORT,
|
||||
String.format("/subscriptions/%s/%s.opml", username, deviceId), null, null).toURL();
|
||||
Request.Builder request = new Request.Builder().url(url);
|
||||
return executeRequest(request);
|
||||
} catch (MalformedURLException | URISyntaxException e) {
|
||||
|
@ -295,7 +373,8 @@ public class GpodnetService implements ISyncService {
|
|||
public String getSubscriptionsOfUser() throws GpodnetServiceException {
|
||||
requireLoggedIn();
|
||||
try {
|
||||
URL url = new URI(BASE_SCHEME, baseHost, String.format("/subscriptions/%s.opml", username), null).toURL();
|
||||
URL url = new URI(BASE_SCHEME, null, baseHost, PORT,
|
||||
String.format("/subscriptions/%s.opml", username), null, null).toURL();
|
||||
Request.Builder request = new Request.Builder().url(url);
|
||||
return executeRequest(request);
|
||||
} catch (MalformedURLException | URISyntaxException e) {
|
||||
|
@ -319,8 +398,8 @@ public class GpodnetService implements ISyncService {
|
|||
throws GpodnetServiceException {
|
||||
requireLoggedIn();
|
||||
try {
|
||||
URL url = new URI(BASE_SCHEME, baseHost, String.format(
|
||||
"/subscriptions/%s/%s.txt", username, deviceId), null).toURL();
|
||||
URL url = new URI(BASE_SCHEME, null, baseHost, PORT,
|
||||
String.format("/subscriptions/%s/%s.txt", username, deviceId), null, null).toURL();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (String s : subscriptions) {
|
||||
builder.append(s);
|
||||
|
@ -353,8 +432,8 @@ public class GpodnetService implements ISyncService {
|
|||
@NonNull Collection<String> removed) throws GpodnetServiceException {
|
||||
requireLoggedIn();
|
||||
try {
|
||||
URL url = new URI(BASE_SCHEME, baseHost, String.format(
|
||||
"/api/2/subscriptions/%s/%s.json", username, deviceId), null).toURL();
|
||||
URL url = new URI(BASE_SCHEME, null, baseHost, PORT,
|
||||
String.format("/api/2/subscriptions/%s/%s.json", username, deviceId), null, null).toURL();
|
||||
|
||||
final JSONObject requestObject = new JSONObject();
|
||||
requestObject.put("add", new JSONArray(added));
|
||||
|
@ -389,8 +468,7 @@ public class GpodnetService implements ISyncService {
|
|||
String params = String.format(Locale.US, "since=%d", timestamp);
|
||||
String path = String.format("/api/2/subscriptions/%s/%s.json", username, deviceId);
|
||||
try {
|
||||
URL url = new URI(BASE_SCHEME, null, baseHost, -1, path, params,
|
||||
null).toURL();
|
||||
URL url = new URI(BASE_SCHEME, null, baseHost, PORT, path, params, null).toURL();
|
||||
Request.Builder request = new Request.Builder().url(url);
|
||||
|
||||
String response = executeRequest(request);
|
||||
|
@ -432,8 +510,8 @@ public class GpodnetService implements ISyncService {
|
|||
throws SyncServiceException {
|
||||
try {
|
||||
Log.d(TAG, "Uploading partial actions " + from + " to " + to + " of " + episodeActions.size());
|
||||
URL url = new URI(BASE_SCHEME, baseHost, String.format(
|
||||
"/api/2/episodes/%s.json", username), null).toURL();
|
||||
URL url = new URI(BASE_SCHEME, null, baseHost, PORT,
|
||||
String.format("/api/2/episodes/%s.json", username), null, null).toURL();
|
||||
|
||||
final JSONArray list = new JSONArray();
|
||||
for (int i = from; i < to; i++) {
|
||||
|
@ -471,7 +549,7 @@ public class GpodnetService implements ISyncService {
|
|||
String params = String.format(Locale.US, "since=%d", timestamp);
|
||||
String path = String.format("/api/2/episodes/%s.json", username);
|
||||
try {
|
||||
URL url = new URI(BASE_SCHEME, null, baseHost, -1, path, params, null).toURL();
|
||||
URL url = new URI(BASE_SCHEME, null, baseHost, PORT, path, params, null).toURL();
|
||||
Request.Builder request = new Request.Builder().url(url);
|
||||
|
||||
String response = executeRequest(request);
|
||||
|
@ -497,7 +575,8 @@ public class GpodnetService implements ISyncService {
|
|||
public void authenticate(@NonNull String username, @NonNull String password) throws GpodnetServiceException {
|
||||
URL url;
|
||||
try {
|
||||
url = new URI(BASE_SCHEME, baseHost, String.format("/api/2/auth/%s/login.json", username), null).toURL();
|
||||
url = new URI(BASE_SCHEME, null, baseHost, PORT,
|
||||
String.format("/api/2/auth/%s/login.json", username), null, null).toURL();
|
||||
} catch (MalformedURLException | URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
throw new GpodnetServiceException(e);
|
||||
|
@ -567,6 +646,13 @@ public class GpodnetService implements ISyncService {
|
|||
if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
|
||||
throw new GpodnetServiceAuthenticationException("Wrong username or password");
|
||||
} else {
|
||||
if (BuildConfig.DEBUG) {
|
||||
try {
|
||||
Log.d(TAG, response.body().string());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
throw new GpodnetServiceBadStatusCodeException("Bad response code: " + responseCode, responseCode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -468,8 +468,6 @@
|
|||
<string name="pref_fast_forward_sum">Customize the number of seconds to jump forward when the fast forward button is clicked</string>
|
||||
<string name="pref_rewind">Rewind Skip Time</string>
|
||||
<string name="pref_rewind_sum">Customize the number of seconds to jump backwards when the rewind button is clicked</string>
|
||||
<string name="pref_gpodnet_sethostname_title">Set hostname</string>
|
||||
<string name="pref_gpodnet_sethostname_use_default_host">Use default host</string>
|
||||
<string name="pref_expandNotify_title">High Notification priority</string>
|
||||
<string name="pref_expandNotify_sum">This usually expands the notification to show playback buttons.</string>
|
||||
<string name="pref_persistNotify_title">Persistent Playback Controls</string>
|
||||
|
@ -631,23 +629,24 @@
|
|||
<string name="gpodnet_suggestions_header">SUGGESTIONS</string>
|
||||
<string name="gpodnet_search_hint">Search gpodder.net</string>
|
||||
<string name="gpodnetauth_login_title">Login</string>
|
||||
<string name="gpodnetauth_login_descr">Welcome to the gpodder.net login process. First, type in your login information:</string>
|
||||
<string name="gpodnetauth_login_butLabel">Login</string>
|
||||
<string name="gpodnetauth_login_register">If you do not have an account yet, you can create one here:\nhttps://gpodder.net/register/</string>
|
||||
<string name="create_account">Create account</string>
|
||||
<string name="username_label">Username</string>
|
||||
<string name="password_label">Password</string>
|
||||
<string name="gpodnetauth_device_title">Device Selection</string>
|
||||
<string name="gpodnet_description">Gpodder.net is an open-source podcast synchronization service that is independent of the AntennaPod project.</string>
|
||||
<string name="gpodnetauth_server_official">Official gpodder.net server</string>
|
||||
<string name="gpodnetauth_server_custom">Custom server</string>
|
||||
<string name="gpodnetauth_host">Hostname</string>
|
||||
<string name="gpodnetauth_select_server">Select server</string>
|
||||
<string name="gpodnetauth_device_descr">Create a new device to use for your gpodder.net account or choose an existing one:</string>
|
||||
<string name="gpodnetauth_device_deviceID">Device ID:\u0020</string>
|
||||
<string name="gpodnetauth_device_caption">Caption</string>
|
||||
<string name="gpodnetauth_device_butCreateNewDevice">Create new device</string>
|
||||
<string name="gpodnetauth_device_chooseExistingDevice">Choose existing device:</string>
|
||||
<string name="gpodnetauth_device_errorEmpty">Device ID must not be empty</string>
|
||||
<string name="gpodnetauth_device_errorAlreadyUsed">Device ID already in use</string>
|
||||
<string name="gpodnetauth_device_name">Device name</string>
|
||||
<string name="gpodnetauth_device_name_default">AntennaPod on %1$s</string>
|
||||
<string name="gpodnetauth_device_caption_errorEmpty">Caption must not be empty</string>
|
||||
<string name="gpodnetauth_sync_groups">Synchronization groups</string>
|
||||
<string name="gpodnetauth_sync_group_select">Select</string>
|
||||
<string name="gpodnetauth_sync_group_new">Use new group</string>
|
||||
|
||||
<string name="gpodnetauth_device_butChoose">Choose</string>
|
||||
<string name="gpodnetauth_finish_title">Login successful!</string>
|
||||
<string name="gpodnetauth_finish_descr">Congratulations! Your gpodder.net account is now linked with your device. AntennaPod will from now on automatically sync subscriptions on your device with your gpodder.net account.</string>
|
||||
<string name="gpodnetauth_finish_butsyncnow">Start sync now</string>
|
||||
<string name="gpodnetauth_finish_butgomainscreen">Go to main screen</string>
|
||||
|
|
Loading…
Reference in New Issue