Added licenses screen
This commit is contained in:
parent
b401c5b64b
commit
d9e122f6d2
|
@ -0,0 +1,111 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<libraries>
|
||||
<library
|
||||
name="AntennaPod"
|
||||
author="The AntennaPod team"
|
||||
website="https://github.com/AntennaPod/AntennaPod/"
|
||||
license="MIT"
|
||||
licenseText="LICENSE.txt" />
|
||||
<library
|
||||
name="AntennaPod-AudioPlayer"
|
||||
author="The AntennaPod team"
|
||||
website="https://github.com/AntennaPod/AntennaPod-AudioPlayer/"
|
||||
license="Apache 2.0"
|
||||
licenseText="LICENSE_APACHE-2.0.txt" />
|
||||
<library
|
||||
name="Apache Commons"
|
||||
author="The Apache Software Foundation"
|
||||
website="http://commons.apache.org/"
|
||||
license="Apache 2.0"
|
||||
licenseText="LICENSE_APACHE-2.0.txt" />
|
||||
<library
|
||||
name="EventBus"
|
||||
author="greenrobot"
|
||||
website="https://github.com/greenrobot/EventBus"
|
||||
license="Apache 2.0"
|
||||
licenseText="LICENSE_APACHE-2.0.txt" />
|
||||
<library
|
||||
name="ExoPlayer"
|
||||
author="Google"
|
||||
website="https://github.com/google/ExoPlayer"
|
||||
license="Apache 2.0"
|
||||
licenseText="LICENSE_APACHE-2.0.txt" />
|
||||
<library
|
||||
name="Floating Action Button Speed Dial"
|
||||
author="Roberto Leinardi"
|
||||
website="https://github.com/leinardi/FloatingActionButtonSpeedDial"
|
||||
license="Apache 2.0"
|
||||
licenseText="LICENSE_APACHE-2.0.txt" />
|
||||
<library
|
||||
name="Glide"
|
||||
author="bumptech"
|
||||
website="https://github.com/bumptech/glide/"
|
||||
license="Simplified BSD"
|
||||
licenseText="LICENSE_GLIDE.txt" />
|
||||
<library
|
||||
name="Iconify"
|
||||
author="Joan Zapata"
|
||||
website="https://github.com/JoanZapata/android-iconify"
|
||||
license="Apache 2.0"
|
||||
licenseText="LICENSE_ANDROID_ICONIFY.txt" />
|
||||
<library
|
||||
name="jsoup"
|
||||
author="Jonathan Hedley"
|
||||
website="http://jsoup.org/"
|
||||
license="MIT"
|
||||
licenseText="LICENSE_JSOUP.txt" />
|
||||
<library
|
||||
name="Material Design Icons"
|
||||
author="Google"
|
||||
website="https://github.com/google/material-design-icons"
|
||||
license="Attribution-ShareAlike 4.0 International"
|
||||
licenseText="LICENSE_MATERIAL_DESIGN_ICONS.txt" />
|
||||
<library
|
||||
name="Material Design Icons"
|
||||
author="Templarian"
|
||||
website="https://github.com/Templarian/MaterialDesign"
|
||||
license="SIL Open Font, Version 1.1"
|
||||
licenseText="LICENSE_SIL.txt" />
|
||||
<library
|
||||
name="OkHttp"
|
||||
author="Square"
|
||||
website="https://github.com/square/okhttp"
|
||||
license="Apache 2.0"
|
||||
licenseText="LICENSE_OKHTTP.txt" />
|
||||
<library
|
||||
name="Okio"
|
||||
author="Square"
|
||||
website="https://github.com/square/okio"
|
||||
license="Apache 2.0"
|
||||
licenseText="LICENSE_APACHE-2.0.txt" />
|
||||
<library
|
||||
name="Presto Client"
|
||||
author="aocate"
|
||||
website="http://www.aocate.com/presto/"
|
||||
license="Apache 2.0"
|
||||
licenseText="LICENSE_PRESTO.txt" />
|
||||
<library
|
||||
name="RecyclerView-FlexibleDivider"
|
||||
author="yqritc"
|
||||
website="https://github.com/yqritc/RecyclerView-FlexibleDivider"
|
||||
license="Apache 2.0"
|
||||
licenseText="LICENSE_APACHE-2.0.txt" />
|
||||
<library
|
||||
name="RxAndroid"
|
||||
author="ReactiveX"
|
||||
website="https://github.com/ReactiveX/RxAndroid"
|
||||
license="Apache 2.0"
|
||||
licenseText="LICENSE_APACHE-2.0.txt" />
|
||||
<library
|
||||
name="StackBlur"
|
||||
author="Enrique López Mañas"
|
||||
website="https://github.com/kikoso/android-stackblur"
|
||||
license="Apache 2.0"
|
||||
licenseText="LICENSE_APACHE-2.0.txt" />
|
||||
<library
|
||||
name="Triangle Label View"
|
||||
author="Shota Saito"
|
||||
website="https://github.com/shts/TriangleLabelView"
|
||||
license="Apache 2.0"
|
||||
licenseText="LICENSE_TRIANGLE_LABEL_VIEW.txt" />
|
||||
</libraries>
|
|
@ -11,19 +11,19 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
|||
import com.bumptech.glide.request.RequestOptions;
|
||||
import de.danoeh.antennapod.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Displays a list of items that have a subtitle and an icon.
|
||||
*/
|
||||
public class SimpleIconListAdapter extends ArrayAdapter<SimpleIconListAdapter.ListItem> {
|
||||
public class SimpleIconListAdapter<T extends SimpleIconListAdapter.ListItem> extends ArrayAdapter<T> {
|
||||
private final Context context;
|
||||
private final ArrayList<ListItem> developers;
|
||||
private final List<T> listItems;
|
||||
|
||||
public SimpleIconListAdapter(Context context, ArrayList<ListItem> developers) {
|
||||
super(context, R.layout.simple_icon_list_item, developers);
|
||||
public SimpleIconListAdapter(Context context, List<T> listItems) {
|
||||
super(context, R.layout.simple_icon_list_item, listItems);
|
||||
this.context = context;
|
||||
this.developers = developers;
|
||||
this.listItems = listItems;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -32,7 +32,7 @@ public class SimpleIconListAdapter extends ArrayAdapter<SimpleIconListAdapter.Li
|
|||
view = View.inflate(context, R.layout.simple_icon_list_item, null);
|
||||
}
|
||||
|
||||
ListItem item = developers.get(position);
|
||||
ListItem item = listItems.get(position);
|
||||
((TextView) view.findViewById(R.id.title)).setText(item.title);
|
||||
((TextView) view.findViewById(R.id.subtitle)).setText(item.subtitle);
|
||||
Glide.with(context)
|
||||
|
@ -46,9 +46,9 @@ public class SimpleIconListAdapter extends ArrayAdapter<SimpleIconListAdapter.Li
|
|||
}
|
||||
|
||||
public static class ListItem {
|
||||
final String title;
|
||||
final String subtitle;
|
||||
final String imageUrl;
|
||||
public final String title;
|
||||
public final String subtitle;
|
||||
public final String imageUrl;
|
||||
|
||||
public ListItem(String title, String subtitle, String imageUrl) {
|
||||
this.title = title;
|
||||
|
|
|
@ -43,7 +43,7 @@ public class AboutDevelopersFragment extends ListFragment {
|
|||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
developers -> setListAdapter(new SimpleIconListAdapter(getContext(), developers)),
|
||||
developers -> setListAdapter(new SimpleIconListAdapter<>(getContext(), developers)),
|
||||
error -> Toast.makeText(getContext(), "Error while loading developers", Toast.LENGTH_LONG).show()
|
||||
);
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.google.android.material.snackbar.Snackbar;
|
|||
import de.danoeh.antennapod.BuildConfig;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.PreferenceActivity;
|
||||
import de.danoeh.antennapod.core.util.IntentUtils;
|
||||
|
||||
public class AboutFragment extends PreferenceFragmentCompat {
|
||||
|
||||
|
@ -36,6 +37,15 @@ public class AboutFragment extends PreferenceFragmentCompat {
|
|||
.addToBackStack(getString(R.string.translators)).commit();
|
||||
return true;
|
||||
});
|
||||
findPreference("about_privacy_policy").setOnPreferenceClickListener((preference) -> {
|
||||
IntentUtils.openInBrowser(getContext(), "https://antennapod.org/privacy.html");
|
||||
return true;
|
||||
});
|
||||
findPreference("about_licenses").setOnPreferenceClickListener((preference) -> {
|
||||
getFragmentManager().beginTransaction().replace(R.id.content, new AboutLicensesFragment())
|
||||
.addToBackStack(getString(R.string.translators)).commit();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
package de.danoeh.antennapod.fragment.preferences;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.ListFragment;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.PreferenceActivity;
|
||||
import de.danoeh.antennapod.adapter.SimpleIconListAdapter;
|
||||
import de.danoeh.antennapod.core.util.IntentUtils;
|
||||
import io.reactivex.Single;
|
||||
import io.reactivex.SingleOnSubscribe;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class AboutLicensesFragment extends ListFragment {
|
||||
private Disposable licensesLoader;
|
||||
private final ArrayList<LicenseItem> licenses = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
getListView().setDivider(null);
|
||||
|
||||
licensesLoader = Single.create((SingleOnSubscribe<ArrayList<LicenseItem>>) emitter -> {
|
||||
licenses.clear();
|
||||
InputStream stream = getContext().getAssets().open("licenses.xml");
|
||||
DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
NodeList libraryList = docBuilder.parse(stream).getElementsByTagName("library");
|
||||
for (int i = 0; i < libraryList.getLength(); i++) {
|
||||
NamedNodeMap lib = libraryList.item(i).getAttributes();
|
||||
licenses.add(new LicenseItem(
|
||||
lib.getNamedItem("name").getTextContent(),
|
||||
String.format("By %s, %s license",
|
||||
lib.getNamedItem("author").getTextContent(),
|
||||
lib.getNamedItem("license").getTextContent()),
|
||||
null,
|
||||
lib.getNamedItem("website").getTextContent(),
|
||||
lib.getNamedItem("licenseText").getTextContent()));
|
||||
}
|
||||
emitter.onSuccess(licenses);
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
developers -> setListAdapter(new SimpleIconListAdapter<LicenseItem>(getContext(), developers)),
|
||||
error -> Toast.makeText(getContext(), "Error while loading licenses", Toast.LENGTH_LONG).show()
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
private static class LicenseItem extends SimpleIconListAdapter.ListItem {
|
||||
final String licenseUrl;
|
||||
final String licenseTextFile;
|
||||
|
||||
LicenseItem(String title, String subtitle, String imageUrl, String licenseUrl, String licenseTextFile) {
|
||||
super(title, subtitle, imageUrl);
|
||||
this.licenseUrl = licenseUrl;
|
||||
this.licenseTextFile = licenseTextFile;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListItemClick(@NonNull ListView l, @NonNull View v, int position, long id) {
|
||||
super.onListItemClick(l, v, position, id);
|
||||
|
||||
LicenseItem item = licenses.get(position);
|
||||
CharSequence[] items = {"View website", "View license"};
|
||||
new AlertDialog.Builder(getContext())
|
||||
.setTitle(item.title)
|
||||
.setItems(items, (dialog, which) -> {
|
||||
if (which == 0) {
|
||||
IntentUtils.openInBrowser(getContext(), item.licenseUrl);
|
||||
} else if (which == 1) {
|
||||
showLicenseText(item.licenseTextFile);
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
|
||||
private void showLicenseText(String licenseTextFile) {
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(
|
||||
getContext().getAssets().open(licenseTextFile)));
|
||||
StringBuilder licenseText = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
licenseText.append(line).append("\n");
|
||||
}
|
||||
|
||||
new AlertDialog.Builder(getContext())
|
||||
.setMessage(licenseText)
|
||||
.show();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
if (licensesLoader != null) {
|
||||
licensesLoader.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
((PreferenceActivity) getActivity()).getSupportActionBar().setTitle(R.string.licenses);
|
||||
}
|
||||
}
|
|
@ -42,7 +42,7 @@ public class AboutTranslatorsFragment extends ListFragment {
|
|||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
translators -> setListAdapter(new SimpleIconListAdapter(getContext(), translators)),
|
||||
translators -> setListAdapter(new SimpleIconListAdapter<>(getContext(), translators)),
|
||||
error -> Toast.makeText(getContext(), "Error while loading translators", Toast.LENGTH_LONG).show()
|
||||
);
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
android:title="@string/translators"/>
|
||||
<Preference
|
||||
android:key="about_privacy_policy"
|
||||
android:icon="?attr/action_about"
|
||||
android:icon="?attr/ic_questionmark"
|
||||
android:summary="https://antennapod.org/privacy.html"
|
||||
android:title="@string/privacy_policy"/>
|
||||
<Preference
|
||||
|
|
Loading…
Reference in New Issue