mirror of
https://github.com/geometer/FBReaderJ.git
synced 2025-10-04 18:29:23 +02:00
AbstractNetworkLink: myIcon -> 'icon' field in urls map
This commit is contained in:
parent
ad05ea1664
commit
5d2a9b1e11
12 changed files with 59 additions and 62 deletions
|
@ -38,7 +38,7 @@ import org.geometerplus.zlibrary.core.network.ZLNetworkException;
|
|||
import org.geometerplus.zlibrary.ui.android.R;
|
||||
|
||||
import org.geometerplus.fbreader.network.*;
|
||||
import org.geometerplus.fbreader.network.opds.OPDSLinkReader;
|
||||
import org.geometerplus.fbreader.network.opds.OPDSCustomLink;
|
||||
|
||||
import org.geometerplus.android.util.UIUtil;
|
||||
|
||||
|
@ -245,8 +245,8 @@ public class AddCustomCatalogActivity extends Activity {
|
|||
}
|
||||
final HashMap<String,UrlInfo> infos = new HashMap<String,UrlInfo>();
|
||||
infos.put(INetworkLink.URL_MAIN, new UrlInfo(textUrl));
|
||||
myLink = OPDSLinkReader.createCustomLink(
|
||||
ICustomNetworkLink.INVALID_ID, siteName, null, null, null, infos
|
||||
myLink = new OPDSCustomLink(
|
||||
ICustomNetworkLink.INVALID_ID, siteName, null, null, infos
|
||||
);
|
||||
|
||||
final Runnable loadInfoRunnable = new Runnable() {
|
||||
|
@ -255,7 +255,7 @@ public class AddCustomCatalogActivity extends Activity {
|
|||
public void run() {
|
||||
try {
|
||||
myError = null;
|
||||
myLink.reloadInfo();
|
||||
myLink.reloadInfo(false);
|
||||
} catch (ZLNetworkException e) {
|
||||
myError = e.getMessage();
|
||||
}
|
||||
|
|
|
@ -40,14 +40,13 @@ import org.geometerplus.zlibrary.ui.android.R;
|
|||
import org.geometerplus.android.util.UIUtil;
|
||||
|
||||
import org.geometerplus.fbreader.network.*;
|
||||
import org.geometerplus.fbreader.network.opds.OPDSLinkReader;
|
||||
import org.geometerplus.fbreader.network.opds.OPDSCustomLink;
|
||||
|
||||
public class NetworkLibraryActivity extends NetworkBaseActivity {
|
||||
static final String ADD_CATALOG = "android.fbreader.action.ADD_CATALOG";
|
||||
|
||||
private static final String ADD_CATALOG_TITLE_KEY = "title";
|
||||
private static final String ADD_CATALOG_SUMMARY_KEY = "summary";
|
||||
private static final String ADD_CATALOG_ICON_KEY = "icon";
|
||||
private static final String ADD_CATALOG_ID_KEY = "id";
|
||||
private static final String ADD_CATALOG_URLS_MAP_KEY = "urls";
|
||||
|
||||
|
@ -57,7 +56,6 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
|
|||
intent
|
||||
.putExtra(ADD_CATALOG_TITLE_KEY, link.getTitle())
|
||||
.putExtra(ADD_CATALOG_SUMMARY_KEY, link.getSummary())
|
||||
.putExtra(ADD_CATALOG_ICON_KEY, link.getIcon())
|
||||
.putExtra(ADD_CATALOG_ID_KEY, link.getId())
|
||||
.putExtra(ADD_CATALOG_URLS_MAP_KEY, link.urlInfoMap());
|
||||
}
|
||||
|
@ -67,12 +65,12 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
|
|||
if (uri == null || !intent.hasExtra(ADD_CATALOG_ID_KEY)) {
|
||||
return null;
|
||||
}
|
||||
return OPDSLinkReader.createCustomLink(
|
||||
|
||||
return new OPDSCustomLink(
|
||||
intent.getIntExtra(ADD_CATALOG_ID_KEY, ICustomNetworkLink.INVALID_ID),
|
||||
uri.getHost(),
|
||||
intent.getStringExtra(ADD_CATALOG_TITLE_KEY),
|
||||
intent.getStringExtra(ADD_CATALOG_SUMMARY_KEY),
|
||||
intent.getStringExtra(ADD_CATALOG_ICON_KEY),
|
||||
(HashMap<String,UrlInfo>)intent.getSerializableExtra(ADD_CATALOG_URLS_MAP_KEY)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
|
|||
|
||||
private void migrate() {
|
||||
final int version = myDatabase.getVersion();
|
||||
final int currentCodeVersion = 2;
|
||||
final int currentCodeVersion = 3;
|
||||
if (version >= currentCodeVersion) {
|
||||
return;
|
||||
}
|
||||
|
@ -54,6 +54,8 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
|
|||
createTables();
|
||||
case 1:
|
||||
updateTables1();
|
||||
case 2:
|
||||
updateTables2();
|
||||
}
|
||||
myDatabase.setTransactionSuccessful();
|
||||
myDatabase.endTransaction();
|
||||
|
@ -74,14 +76,13 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
|
|||
|
||||
@Override
|
||||
protected void loadCustomLinks(ICustomLinksHandler handler) {
|
||||
final Cursor cursor = myDatabase.rawQuery("SELECT link_id,title,site_name,summary,icon FROM CustomLinks", null);
|
||||
final Cursor cursor = myDatabase.rawQuery("SELECT link_id,title,site_name,summary FROM Links", null);
|
||||
final HashMap<String,UrlInfo> linksMap = new HashMap<String,UrlInfo>();
|
||||
while (cursor.moveToNext()) {
|
||||
final int id = cursor.getInt(0);
|
||||
final String title = cursor.getString(1);
|
||||
final String siteName = cursor.getString(2);
|
||||
final String summary = cursor.getString(3);
|
||||
final String icon = cursor.getString(4);
|
||||
|
||||
linksMap.clear();
|
||||
final Cursor linksCursor = myDatabase.rawQuery("SELECT key,url,update_time FROM LinkUrls WHERE url NOT NULL AND link_id = " + id, null);
|
||||
|
@ -96,7 +97,7 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
|
|||
}
|
||||
linksCursor.close();
|
||||
|
||||
handler.handleCustomLinkData(id, siteName, title, summary, icon, linksMap);
|
||||
handler.handleCustomLinkData(id, siteName, title, summary, linksMap);
|
||||
}
|
||||
cursor.close();
|
||||
}
|
||||
|
@ -114,14 +115,14 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
|
|||
if (link.getId() == ICustomNetworkLink.INVALID_ID) {
|
||||
if (myInsertCustomLinkStatement == null) {
|
||||
myInsertCustomLinkStatement = myDatabase.compileStatement(
|
||||
"INSERT INTO CustomLinks (title,site_name,summary,icon) VALUES (?,?,?,?)"
|
||||
"INSERT INTO Links (title,site_name,summary) VALUES (?,?,?)"
|
||||
);
|
||||
}
|
||||
statement = myInsertCustomLinkStatement;
|
||||
} else {
|
||||
if (myUpdateCustomLinkStatement == null) {
|
||||
myUpdateCustomLinkStatement = myDatabase.compileStatement(
|
||||
"UPDATE CustomLinks SET title = ?, site_name = ?, summary =?, icon = ? "
|
||||
"UPDATE Links SET title = ?, site_name = ?, summary =? "
|
||||
+ "WHERE link_id = ?"
|
||||
);
|
||||
}
|
||||
|
@ -131,7 +132,6 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
|
|||
statement.bindString(1, link.getTitle());
|
||||
statement.bindString(2, link.getSiteName());
|
||||
SQLiteUtil.bindString(statement, 3, link.getSummary());
|
||||
SQLiteUtil.bindString(statement, 4, link.getIcon());
|
||||
|
||||
final long id;
|
||||
final HashMap<String,UrlInfo> linksMap = new HashMap<String,UrlInfo>();
|
||||
|
@ -214,7 +214,7 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
|
|||
|
||||
if (myDeleteCustomLinkStatement == null) {
|
||||
myDeleteCustomLinkStatement = myDatabase.compileStatement(
|
||||
"DELETE FROM CustomLinks WHERE link_id = ?"
|
||||
"DELETE FROM Links WHERE link_id = ?"
|
||||
);
|
||||
}
|
||||
myDeleteCustomLinkStatement.bindLong(1, id);
|
||||
|
@ -263,4 +263,23 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
|
|||
myDatabase.execSQL("INSERT INTO LinkUrls (key,link_id,url) SELECT key,link_id,url FROM CustomLinkUrls");
|
||||
myDatabase.execSQL("DROP TABLE CustomLinkUrls");
|
||||
}
|
||||
|
||||
private void updateTables2() {
|
||||
myDatabase.execSQL(
|
||||
"CREATE TABLE Links(" +
|
||||
"link_id INTEGER PRIMARY KEY," +
|
||||
"title TEXT NOT NULL," +
|
||||
"site_name TEXT NOT NULL," +
|
||||
"summary TEXT)");
|
||||
myDatabase.execSQL("INSERT INTO Links (link_id,title,site_name,summary) SELECT link_id,title,site_name,summary FROM CustomLinks");
|
||||
final Cursor cursor = myDatabase.rawQuery("SELECT link_id,icon FROM CustomLinks", null);
|
||||
while (cursor.moveToNext()) {
|
||||
final int id = cursor.getInt(0);
|
||||
final String url = cursor.getString(1);
|
||||
myDatabase.execSQL("INSERT INTO LinkUrls (key,link_id,url) VALUES " +
|
||||
"('icon'," + id + ",'" + url + "')");
|
||||
}
|
||||
cursor.close();
|
||||
myDatabase.execSQL("DROP TABLE CustomLinks");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ public abstract class AbstractNetworkLink implements INetworkLink {
|
|||
protected String mySiteName;
|
||||
protected String myTitle;
|
||||
protected String mySummary;
|
||||
protected String myIcon;
|
||||
protected final String myLanguage;
|
||||
protected final TreeMap<String,UrlInfo> myInfos;
|
||||
|
||||
|
@ -37,15 +36,13 @@ public abstract class AbstractNetworkLink implements INetworkLink {
|
|||
* @param siteName name of the corresponding website. Must be not <code>null</code>.
|
||||
* @param title title of the corresponding library item. Must be not <code>null</code>.
|
||||
* @param summary description of the corresponding library item. Can be <code>null</code>.
|
||||
* @param icon string contains link's icon data/url. Can be <code>null</code>.
|
||||
* @param language language of the catalog. If <code>null</code> we assume this catalog is multilanguage.
|
||||
* @param infos map contains URL infos with their identifiers; must always contain one URL with <code>URL_MAIN</code> identifier
|
||||
*/
|
||||
public AbstractNetworkLink(String siteName, String title, String summary, String icon, String language, Map<String,UrlInfo> infos) {
|
||||
public AbstractNetworkLink(String siteName, String title, String summary, String language, Map<String,UrlInfo> infos) {
|
||||
mySiteName = siteName;
|
||||
myTitle = title;
|
||||
mySummary = summary;
|
||||
myIcon = icon;
|
||||
myLanguage = language != null ? language : "multi";
|
||||
myInfos = new TreeMap<String,UrlInfo>(infos);
|
||||
}
|
||||
|
@ -63,7 +60,7 @@ public abstract class AbstractNetworkLink implements INetworkLink {
|
|||
}
|
||||
|
||||
public final String getIcon() {
|
||||
return myIcon;
|
||||
return getUrlInfo(URL_ICON).URL;
|
||||
}
|
||||
|
||||
public final String getLanguage() {
|
||||
|
@ -89,7 +86,7 @@ public abstract class AbstractNetworkLink implements INetworkLink {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
String icon = myIcon;
|
||||
String icon = getIcon();
|
||||
if (icon != null) {
|
||||
if (icon.length() > 64) {
|
||||
icon = icon.substring(0, 61) + "...";
|
||||
|
@ -118,7 +115,6 @@ public abstract class AbstractNetworkLink implements INetworkLink {
|
|||
if (!mySiteName.equals(lnk.mySiteName)
|
||||
|| !myTitle.equals(lnk.myTitle)
|
||||
|| !ZLMiscUtil.equals(mySummary, lnk.mySummary)
|
||||
|| !ZLMiscUtil.equals(myIcon, lnk.myIcon)
|
||||
|| !ZLMiscUtil.mapsEquals(myInfos, lnk.myInfos)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -32,13 +32,12 @@ public interface ICustomNetworkLink extends INetworkLink {
|
|||
void setSiteName(String name);
|
||||
void setTitle(String title);
|
||||
void setSummary(String summary);
|
||||
void setIcon(String icon);
|
||||
|
||||
HashMap<String,UrlInfo> urlInfoMap();
|
||||
void setUrl(String urlKey, String url);
|
||||
void removeUrl(String urlKey);
|
||||
|
||||
void reloadInfo() throws ZLNetworkException;
|
||||
void reloadInfo(boolean urlsOnly) throws ZLNetworkException;
|
||||
|
||||
// returns true if next methods have changed link's data:
|
||||
// setSiteName, setTitle, setSummary, setIcon, setLink, removeLink
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationMan
|
|||
public interface INetworkLink {
|
||||
String URL_MAIN = "main";
|
||||
String URL_SEARCH = "search";
|
||||
String URL_ICON = "icon";
|
||||
String URL_SIGN_IN = "signIn";
|
||||
String URL_SIGN_OUT = "signOut";
|
||||
String URL_SIGN_UP = "signUp";
|
||||
|
|
|
@ -35,7 +35,7 @@ public abstract class NetworkDatabase {
|
|||
protected abstract void executeAsATransaction(Runnable actions);
|
||||
|
||||
public interface ICustomLinksHandler {
|
||||
void handleCustomLinkData(int id, String siteName, String title, String summary, String icon, Map<String,UrlInfo> infos);
|
||||
void handleCustomLinkData(int id, String siteName, String title, String summary, Map<String,UrlInfo> infos);
|
||||
}
|
||||
|
||||
protected abstract void loadCustomLinks(ICustomLinksHandler handler);
|
||||
|
|
|
@ -31,9 +31,9 @@ import org.geometerplus.zlibrary.core.language.ZLLanguageUtil;
|
|||
|
||||
import org.geometerplus.fbreader.tree.FBTree;
|
||||
import org.geometerplus.fbreader.network.tree.*;
|
||||
import org.geometerplus.fbreader.network.opds.OPDSCustomLink;
|
||||
import org.geometerplus.fbreader.network.opds.OPDSLinkReader;
|
||||
|
||||
|
||||
public class NetworkLibrary {
|
||||
private static NetworkLibrary ourInstance;
|
||||
|
||||
|
@ -179,12 +179,12 @@ public class NetworkLibrary {
|
|||
db.loadCustomLinks(
|
||||
new NetworkDatabase.ICustomLinksHandler() {
|
||||
public void handleCustomLinkData(int id, String siteName,
|
||||
String title, String summary, String icon, Map<String,UrlInfo> infos) {
|
||||
String title, String summary, Map<String,UrlInfo> infos) {
|
||||
if (title != null &&
|
||||
siteName != null &&
|
||||
infos.get(INetworkLink.URL_MAIN) != null) {
|
||||
final ICustomNetworkLink link = OPDSLinkReader.createCustomLink(
|
||||
id, siteName, title, summary, icon, infos
|
||||
final ICustomNetworkLink link = new OPDSCustomLink(
|
||||
id, siteName, title, summary, infos
|
||||
);
|
||||
addLinkInternal(link);
|
||||
}
|
||||
|
|
|
@ -34,13 +34,13 @@ import org.geometerplus.fbreader.network.INetworkLink;
|
|||
import org.geometerplus.fbreader.network.NetworkException;
|
||||
import org.geometerplus.fbreader.network.UrlInfo;
|
||||
|
||||
class OPDSCustomLink extends OPDSNetworkLink implements ICustomNetworkLink {
|
||||
public class OPDSCustomLink extends OPDSNetworkLink implements ICustomNetworkLink {
|
||||
private int myId;
|
||||
|
||||
private boolean myHasChanges;
|
||||
|
||||
OPDSCustomLink(int id, String siteName, String title, String summary, String icon, Map<String,UrlInfo> infos) {
|
||||
super(siteName, title, summary, icon, null, infos, false);
|
||||
public OPDSCustomLink(int id, String siteName, String title, String summary, Map<String,UrlInfo> infos) {
|
||||
super(siteName, title, summary, null, infos, false);
|
||||
myId = id;
|
||||
}
|
||||
|
||||
|
@ -60,11 +60,6 @@ class OPDSCustomLink extends OPDSNetworkLink implements ICustomNetworkLink {
|
|||
myHasChanges = false;
|
||||
}
|
||||
|
||||
public final void setIcon(String icon) {
|
||||
myHasChanges = myHasChanges || !ZLMiscUtil.equals(myIcon, icon);
|
||||
myIcon = icon;
|
||||
}
|
||||
|
||||
public final void setSiteName(String name) {
|
||||
myHasChanges = myHasChanges || !ZLMiscUtil.equals(mySiteName, name);
|
||||
mySiteName = name;
|
||||
|
@ -90,8 +85,7 @@ class OPDSCustomLink extends OPDSNetworkLink implements ICustomNetworkLink {
|
|||
myHasChanges = myHasChanges || oldUrl != null;
|
||||
}
|
||||
|
||||
|
||||
public void reloadInfo() throws ZLNetworkException {
|
||||
public void reloadInfo(boolean urlsOnly) throws ZLNetworkException {
|
||||
final LinkedList<String> opensearchDescriptionURLs = new LinkedList<String>();
|
||||
final List<OpenSearchDescription> descriptions = Collections.synchronizedList(new LinkedList<OpenSearchDescription>());
|
||||
|
||||
|
@ -110,12 +104,8 @@ class OPDSCustomLink extends OPDSNetworkLink implements ICustomNetworkLink {
|
|||
throw new ZLNetworkException(NetworkException.ERROR_NO_REQUIRED_INFORMATION);
|
||||
}
|
||||
myTitle = info.Title;
|
||||
if (info.Icon != null) {
|
||||
myIcon = info.Icon;
|
||||
}
|
||||
if (info.Summary != null) {
|
||||
setUrl(URL_ICON, info.Icon);
|
||||
mySummary = info.Summary;
|
||||
}
|
||||
if (info.DirectOpenSearchDescription != null) {
|
||||
descriptions.add(info.DirectOpenSearchDescription);
|
||||
}
|
||||
|
@ -148,7 +138,8 @@ class OPDSCustomLink extends OPDSNetworkLink implements ICustomNetworkLink {
|
|||
if (!descriptions.isEmpty()) {
|
||||
// TODO: May be do not use '%s'??? Use Description instead??? (this needs to rewrite SEARCH engine logic a little)
|
||||
setUrl(URL_SEARCH, descriptions.get(0).makeQuery("%s"));
|
||||
System.err.println(descriptions.get(0).makeQuery("%s"));
|
||||
} else {
|
||||
setUrl(URL_SEARCH, null);
|
||||
}
|
||||
if (error != null) {
|
||||
throw error;
|
||||
|
|
|
@ -39,10 +39,6 @@ import org.geometerplus.fbreader.network.atom.ATOMUpdated;
|
|||
public class OPDSLinkReader {
|
||||
static final String CATALOGS_URL = "http://data.fbreader.org/catalogs/generic-1.2.xml";
|
||||
|
||||
public static ICustomNetworkLink createCustomLink(int id, String siteName, String title, String summary, String icon, Map<String,UrlInfo> infos) {
|
||||
return new OPDSCustomLink(id, siteName, title, summary, icon, infos);
|
||||
}
|
||||
|
||||
public static final int CACHE_LOAD = 0;
|
||||
public static final int CACHE_UPDATE = 1;
|
||||
public static final int CACHE_CLEAR = 2;
|
||||
|
|
|
@ -99,7 +99,6 @@ class OPDSLinkXMLReader extends OPDSXMLReader implements OPDSConstants, MimeType
|
|||
final String summary = entry.Content;
|
||||
final String language = entry.DCLanguage;
|
||||
|
||||
String icon = null;
|
||||
final HashMap<String,UrlInfo> infos = new HashMap<String,UrlInfo>();
|
||||
final HashMap<String,NetworkCatalogItem.Accessibility> urlConditions =
|
||||
new HashMap<String,NetworkCatalogItem.Accessibility>();
|
||||
|
@ -109,11 +108,12 @@ class OPDSLinkXMLReader extends OPDSXMLReader implements OPDSConstants, MimeType
|
|||
final String rel = link.getRel();
|
||||
if (rel == REL_IMAGE_THUMBNAIL || rel == REL_THUMBNAIL) {
|
||||
if (type == MIME_IMAGE_PNG || type == MIME_IMAGE_JPEG) {
|
||||
icon = href;
|
||||
infos.put(INetworkLink.URL_ICON, new UrlInfo(href));
|
||||
}
|
||||
} else if ((rel != null && rel.startsWith(REL_IMAGE_PREFIX)) || rel == REL_COVER) {
|
||||
if (icon == null && (type == MIME_IMAGE_PNG || type == MIME_IMAGE_JPEG)) {
|
||||
icon = href;
|
||||
if (infos.get(INetworkLink.URL_ICON) == null &&
|
||||
(type == MIME_IMAGE_PNG || type == MIME_IMAGE_JPEG)) {
|
||||
infos.put(INetworkLink.URL_ICON, new UrlInfo(href));
|
||||
}
|
||||
} else if (rel == null) {
|
||||
if (type == MIME_APP_ATOM) {
|
||||
|
@ -154,7 +154,7 @@ class OPDSLinkXMLReader extends OPDSXMLReader implements OPDSConstants, MimeType
|
|||
sslCertificate = null;
|
||||
}
|
||||
|
||||
INetworkLink result = link(siteName, title, summary, icon, language, infos, urlConditions, sslCertificate);
|
||||
INetworkLink result = link(siteName, title, summary, language, infos, urlConditions, sslCertificate);
|
||||
if (result != null) {
|
||||
myListener.onNewLink(result);
|
||||
}
|
||||
|
@ -165,7 +165,6 @@ class OPDSLinkXMLReader extends OPDSXMLReader implements OPDSConstants, MimeType
|
|||
String siteName,
|
||||
String title,
|
||||
String summary,
|
||||
String icon,
|
||||
String language,
|
||||
Map<String,UrlInfo> infos,
|
||||
HashMap<String,NetworkCatalogItem.Accessibility> urlConditions,
|
||||
|
@ -179,7 +178,6 @@ class OPDSLinkXMLReader extends OPDSXMLReader implements OPDSConstants, MimeType
|
|||
siteName,
|
||||
title,
|
||||
summary,
|
||||
icon,
|
||||
language,
|
||||
infos,
|
||||
myHasStableIdentifiers
|
||||
|
|
|
@ -48,9 +48,9 @@ public class OPDSNetworkLink extends AbstractNetworkLink {
|
|||
|
||||
private final boolean myHasStableIdentifiers;
|
||||
|
||||
OPDSNetworkLink(String siteName, String title, String summary, String icon, String language,
|
||||
OPDSNetworkLink(String siteName, String title, String summary, String language,
|
||||
Map<String,UrlInfo> infos, boolean hasStableIdentifiers) {
|
||||
super(siteName, title, summary, icon, language, infos);
|
||||
super(siteName, title, summary, language, infos);
|
||||
myHasStableIdentifiers = hasStableIdentifiers;
|
||||
myBooksInBasketOption = new ZLStringListOption(siteName, "Basket", null);
|
||||
}
|
||||
|
@ -127,7 +127,6 @@ public class OPDSNetworkLink extends AbstractNetworkLink {
|
|||
if (url == null) {
|
||||
return null;
|
||||
}
|
||||
System.err.println("URL = " + url);
|
||||
try {
|
||||
pattern = URLEncoder.encode(pattern, "utf-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue