Added licenses screen

This commit is contained in:
ByteHamster 2019-11-09 00:57:44 +01:00
parent b401c5b64b
commit d9e122f6d2
7 changed files with 260 additions and 13 deletions

View File

@ -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>

View File

@ -11,19 +11,19 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.RequestOptions; import com.bumptech.glide.request.RequestOptions;
import de.danoeh.antennapod.R; 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. * 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 Context context;
private final ArrayList<ListItem> developers; private final List<T> listItems;
public SimpleIconListAdapter(Context context, ArrayList<ListItem> developers) { public SimpleIconListAdapter(Context context, List<T> listItems) {
super(context, R.layout.simple_icon_list_item, developers); super(context, R.layout.simple_icon_list_item, listItems);
this.context = context; this.context = context;
this.developers = developers; this.listItems = listItems;
} }
@Override @Override
@ -32,7 +32,7 @@ public class SimpleIconListAdapter extends ArrayAdapter<SimpleIconListAdapter.Li
view = View.inflate(context, R.layout.simple_icon_list_item, null); 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.title)).setText(item.title);
((TextView) view.findViewById(R.id.subtitle)).setText(item.subtitle); ((TextView) view.findViewById(R.id.subtitle)).setText(item.subtitle);
Glide.with(context) Glide.with(context)
@ -46,9 +46,9 @@ public class SimpleIconListAdapter extends ArrayAdapter<SimpleIconListAdapter.Li
} }
public static class ListItem { public static class ListItem {
final String title; public final String title;
final String subtitle; public final String subtitle;
final String imageUrl; public final String imageUrl;
public ListItem(String title, String subtitle, String imageUrl) { public ListItem(String title, String subtitle, String imageUrl) {
this.title = title; this.title = title;

View File

@ -43,7 +43,7 @@ public class AboutDevelopersFragment extends ListFragment {
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe( .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() error -> Toast.makeText(getContext(), "Error while loading developers", Toast.LENGTH_LONG).show()
); );

View File

@ -9,6 +9,7 @@ import com.google.android.material.snackbar.Snackbar;
import de.danoeh.antennapod.BuildConfig; import de.danoeh.antennapod.BuildConfig;
import de.danoeh.antennapod.R; import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.PreferenceActivity; import de.danoeh.antennapod.activity.PreferenceActivity;
import de.danoeh.antennapod.core.util.IntentUtils;
public class AboutFragment extends PreferenceFragmentCompat { public class AboutFragment extends PreferenceFragmentCompat {
@ -36,6 +37,15 @@ public class AboutFragment extends PreferenceFragmentCompat {
.addToBackStack(getString(R.string.translators)).commit(); .addToBackStack(getString(R.string.translators)).commit();
return true; 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 @Override

View File

@ -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);
}
}

View File

@ -42,7 +42,7 @@ public class AboutTranslatorsFragment extends ListFragment {
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe( .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() error -> Toast.makeText(getContext(), "Error while loading translators", Toast.LENGTH_LONG).show()
); );

View File

@ -21,7 +21,7 @@
android:title="@string/translators"/> android:title="@string/translators"/>
<Preference <Preference
android:key="about_privacy_policy" android:key="about_privacy_policy"
android:icon="?attr/action_about" android:icon="?attr/ic_questionmark"
android:summary="https://antennapod.org/privacy.html" android:summary="https://antennapod.org/privacy.html"
android:title="@string/privacy_policy"/> android:title="@string/privacy_policy"/>
<Preference <Preference