/******************************************************************************
* Copyright (C) 2012, 2013, 2014, 2015, 2016
* Younghyung Cho. <yhcting77@gmail.com>
* All rights reserved.
*
* This file is part of NetMBuddy
*
* This program is licensed under the FreeBSD license
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation
* are those of the authors and should not be interpreted as representing
* official policies, either expressed or implied, of the FreeBSD Project.
*****************************************************************************/
package free.yhc.netmbuddy.utils;
import java.text.DateFormat;
import java.util.Date;
import java.util.LinkedList;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import free.yhc.abaselib.AppEnv;
import free.yhc.baselib.Logger;
import free.yhc.baselib.async.Task;
import free.yhc.abaselib.util.AUtil;
import free.yhc.abaselib.ux.DialogTask;
import free.yhc.netmbuddy.Err;
import free.yhc.netmbuddy.R;
import free.yhc.netmbuddy.db.ColPlaylist;
import free.yhc.netmbuddy.db.ColVideo;
import free.yhc.netmbuddy.db.DB;
import free.yhc.netmbuddy.db.DB.Bookmark;
import free.yhc.netmbuddy.core.PolicyConstant;
import free.yhc.netmbuddy.core.YTPlayer;
import free.yhc.netmbuddy.db.DMVideo;
import free.yhc.netmbuddy.scmp.SCmp;
import free.yhc.netmbuddy.task.YTHackTask;
public class UxUtil extends free.yhc.abaselib.util.UxUtil {
private static final boolean DBG = Logger.DBG_DEFAULT;
private static final Logger P = Logger.create(free.yhc.netmbuddy.utils.UxUtil.class, Logger.LOGLV_DEFAULT);
public static final long PLID_INVALID = DB.INVALID_PLAYLIST_ID;
// Special playlist id that represents that this is unknown non-user playlist.
public static final long PLID_UNKNOWN = PLID_INVALID - 1;
public static final long PLID_RECENT_PLAYED = PLID_INVALID - 2;
public static final long PLID_SEARCHED = PLID_INVALID - 3;
// NOTE
// To save time for decoding image, pre-decoded bitmap is uses for unknown thumbnail image.
private static final Bitmap sBmIcUnknownImage
= BitmapFactory.decodeResource(AppEnv.getAppContext().getResources(), R.drawable.ic_unknown_image);
public interface EditTextAction {
void prepare(Dialog dialog, EditText edit);
void onOk(Dialog dialog, EditText edit);
}
public interface OnPlaylistSelected {
void onUserMenu(int pos, Object tag);
void onPlaylist(long plid, Object tag);
}
public interface OnMenuSelected {
void onSelected(int pos, int menuTitle);
}
public interface OnPostExecuteListener {
void onPostExecute(Err result, Object tag);
}
// ========================================================================
//
// Functions
//
// ========================================================================
// ------------------------------------------------------------------------
//
// Dialog
//
// ------------------------------------------------------------------------
public static AlertDialog
buildConfirmDialog(@NonNull final Context context,
@NonNull final CharSequence title,
@NonNull final CharSequence description,
@NonNull final ConfirmAction action) {
return free.yhc.abaselib.util.UxUtil.buildConfirmDialog(
context,
title,
description,
R.drawable.ic_info,
AUtil.getResText(R.string.yes),
AUtil.getResText(R.string.no),
action);
}
public static AlertDialog
buildConfirmDialog(@NonNull final Context context,
final int title,
final int description,
@NonNull final ConfirmAction action) {
return buildConfirmDialog(context,
context.getResources().getText(title),
context.getResources().getText(description),
action);
}
private static AlertDialog
createEditTextDialog(Context context, View layout, CharSequence title) {
// Create "Enter Url" dialog
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setView(layout);
final AlertDialog dialog = builder.create();
dialog.setTitle(title);
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
return dialog;
}
@SuppressWarnings("unused")
private static AlertDialog
createEditTextDialog(Context context, View layout, int title) {
return createEditTextDialog(context, layout, context.getResources().getText(title));
}
public static AlertDialog
buildOneLineEditTextDialog(final Context context,
final CharSequence title,
final CharSequence initText,
final CharSequence hintText,
final EditTextAction action) {
// Create "Enter Url" dialog
View layout = AUtil.inflateLayout(R.layout.edittext_dialog);
final AlertDialog dialog = createEditTextDialog(context, layout, title);
// Set action for dialog.
final EditText edit = (EditText)layout.findViewById(R.id.edit);
if (null != initText
&& initText.length() > 0) {
edit.setText(initText);
edit.setSelection(initText.length());
}
if (null != hintText
&& hintText.length() > 0)
edit.setHint(hintText);
edit.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean
onKey(View v, int keyCode, KeyEvent event) {
// If the event is a key-down event on the "enter" button
if ((KeyEvent.ACTION_DOWN == event.getAction()) && (KeyEvent.KEYCODE_ENTER == keyCode)) {
dialog.dismiss();
if (!edit.getText().toString().isEmpty())
action.onOk(dialog, ((EditText)v));
return true;
}
return false;
}
});
action.prepare(dialog, edit);
dialog.setButton(AlertDialog.BUTTON_POSITIVE,
context.getResources().getText(R.string.ok),
new DialogInterface.OnClickListener() {
@Override
public void
onClick(DialogInterface dia, int which) {
dialog.dismiss();
if (!edit.getText().toString().isEmpty())
action.onOk(dialog, edit);
}
});
dialog.setButton(AlertDialog.BUTTON_NEGATIVE,
context.getResources().getText(R.string.cancel),
new DialogInterface.OnClickListener() {
@Override
public void
onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
return dialog;
}
public static AlertDialog
buildOneLineEditTextDialog(Context context,
CharSequence title,
EditTextAction action) {
return buildOneLineEditTextDialog(context,
title,
"",
"",
action);
}
public static AlertDialog
buildOneLineEditTextDialog(Context context,
int title,
EditTextAction action) {
return buildOneLineEditTextDialog(context,
context.getResources().getText(title),
action);
}
public static AlertDialog
buildOneLineEditTextDialog(Context context,
int title,
CharSequence initText,
EditTextAction action) {
return buildOneLineEditTextDialog(context,
context.getResources().getText(title),
initText,
"",
action);
}
@SuppressWarnings("unused")
public static AlertDialog
buildOneLineEditTextDialog(Context context,
CharSequence title,
int initText,
EditTextAction action) {
return buildOneLineEditTextDialog(context,
title,
context.getResources().getText(initText),
"",
action);
}
public static AlertDialog
buildOneLineEditTextDialogWithHint(Context context,
CharSequence title,
int hintText,
EditTextAction action) {
return buildOneLineEditTextDialog(context,
title,
"",
context.getResources().getText(hintText),
action);
}
public static AlertDialog
buildPopupMenuDialog(final Activity activity,
final OnMenuSelected action,
final int diagTitle,
final int[] menuTitles) {
final CharSequence[] items = new CharSequence[menuTitles.length];
for (int i = 0; i < menuTitles.length; i++)
items[i] = activity.getResources().getText(menuTitles[i]);
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
if (diagTitle >= 0)
builder.setTitle(diagTitle);
builder.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void
onClick(DialogInterface dialog, int item) {
action.onSelected(item, menuTitles[item]);
}
});
return builder.create();
}
public static AlertDialog
buildSelectPlaylistDialog(final DB db,
final Context context,
final int diagTitle,
final String[] userMenuStrings,
final OnPlaylistSelected action,
long plidExcluded,
final Object tag) {
final String[] userMenus = (null == userMenuStrings)? new String[0]: userMenuStrings;
// Create menu list
final Cursor c = db.queryPlaylist(new ColPlaylist[] { ColPlaylist.ID,
ColPlaylist.TITLE });
final int iTitle = c.getColumnIndex(ColPlaylist.TITLE.getName());
final int iId = c.getColumnIndex(ColPlaylist.ID.getName());
LinkedList<String> menul = new LinkedList<>();
LinkedList<Long> idl = new LinkedList<>();
for (int i = 0; i < userMenus.length; i++) {
menul.add(userMenus[i]);
idl.add((long)i);
}
// Add slot for 'new list' menu
menul.add(context.getResources().getText(R.string.new_playlist).toString());
idl.add((long)userMenus.length); // dummy value
if (c.moveToFirst()) {
do {
if (plidExcluded != c.getLong(iId)) {
menul.add(c.getString(iTitle));
idl.add(c.getLong(iId));
}
} while (c.moveToNext());
}
c.close();
final String[] menus = menul.toArray(new String[menul.size()]);
final long[] ids = Util.convertArrayLongTolong(idl.toArray(new Long[idl.size()]));
AlertDialog.Builder bldr = new AlertDialog.Builder(context);
if (diagTitle > 0)
bldr.setTitle(diagTitle);
ArrayAdapter<String> adapter
= new ArrayAdapter<>(context, android.R.layout.select_dialog_item, menus);
bldr.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
public void
onClick(DialogInterface dialog, int which) {
P.bug(which >= 0);
dialog.dismiss();
if (userMenus.length > which) {
// User menu is selected.
action.onUserMenu(which, tag);
} else if (userMenus.length == which) {
// Need to get new playlist name.
free.yhc.netmbuddy.utils.UxUtil.EditTextAction edAction = new free.yhc.netmbuddy.utils.UxUtil.EditTextAction() {
@Override
public void
prepare(Dialog dialog, EditText edit) {
}
@Override
public void
onOk(Dialog dialog, EditText edit) {
String title = edit.getText().toString();
if (db.containsPlaylist(title)) {
showTextToast(R.string.msg_existing_playlist);
return;
}
long plid = db.insertPlaylist(title);
if (plid < 0) {
showTextToast(R.string.err_db_unknown);
return;
}
action.onPlaylist(plid, tag);
}
};
free.yhc.netmbuddy.utils.UxUtil.buildOneLineEditTextDialog(context, R.string.enter_playlist_title, edAction)
.show();
} else
action.onPlaylist(ids[which], tag);
}
});
return bldr.create();
}
/**
* This function is a kind of HACK - actually FULL OF HACK - to save memory used by thumbnail.
* Very dangerous and difficult at maintenance.
* But, I failed to find any better way to save memory for thumbnail display.
*
* NOTE
* If exception like "Exception : try to used recycled bitmap ..." is shown up,
* read and understand what this function does with highest priority!
*/
public static void
setThumbnailImageView(ImageView v, byte[] imgdata) {
// NOTE
// Why Bitmap instance is created even if R.drawable.ic_unknown_image?
// ImageView has BitmapDrawable to draw it's canvas, and every input-drawable
// - resource, uri etc - is converted to BitmapDrawable eventually.
// But, ImageView.setImageResource() doesn't update drawable if current image resource
// is same with new one - See "ImageView.java for details"
// In this case, ImageView may try to use recycled BitmapDrawable.
// To avoid this, Bitmap instance is used in all cases.
Bitmap thumbnailBm;
if (null != imgdata && imgdata.length > 0)
thumbnailBm = BitmapFactory.decodeByteArray(imgdata, 0, imgdata.length);
else
thumbnailBm = sBmIcUnknownImage;
// This assumes that Drawable of ImageView is set only by this function.
// => Setting drawable directly through ImageView interface may lead to exception
// (Exception : try to used recycled bitmap)
// Recycle old Bitmap
Drawable drawable = v.getDrawable();
if (drawable instanceof BitmapDrawable) { // to make sure.
BitmapDrawable bmd = (BitmapDrawable)drawable;
Bitmap bitmap = bmd.getBitmap();
if (bitmap != sBmIcUnknownImage)
bitmap.recycle();
}
// change to new one.
v.setImageBitmap(thumbnailBm);
}
public static void
playAsVideo(Context context, String ytvid) {
YTPlayer.get().stopVideos();
Intent i = new Intent(Intent.ACTION_VIEW,
Uri.parse(YTHackTask.getYtVideoPageUrl(ytvid)));
try {
context.startActivity(i);
} catch (ActivityNotFoundException e) {
showTextToast(R.string.msg_fail_find_app);
}
}
public static boolean
isUserPlaylist(long plid) {
return plid >= 0;
}
public static void
doDeleteVideos(@NonNull final Activity activity,
final Object user,
final OnPostExecuteListener listener,
final long plid,
@NonNull final long[] mids) {
Task<Void> t = new Task<Void>() {
@Override
protected Void
doAsync() {
DB db = DB.get();
db.beginTransaction();
try {
for (long mid : mids) {
if (isUserPlaylist(plid))
db.deleteVideoFrom(plid, mid);
else
db.deleteVideoFromAllPlaylist(mid);
}
db.setTransactionSuccessful();
if (null != listener)
listener.onPostExecute(Err.NO_ERR, user);
} finally {
db.endTransaction();
}
return null;
}
};
DialogTask.Builder<DialogTask.Builder> b
= new DialogTask.Builder<>(activity, t);
b.setCancelButtonText(R.string.cancel)
.setMessage(R.string.deleting);
if (!b.create().start())
P.bug();
}
public static void
deleteVideos(@NonNull final Activity activity,
final Object user, // passed to callback
final OnPostExecuteListener listener,
final long plid,
@NonNull final long[] vids) {
ConfirmAction action
= new ConfirmAction() {
@Override
public void
onPositive(@NonNull Dialog dialog) {
doDeleteVideos(activity, user, listener, plid, vids);
}
@Override
public void
onNegative(@NonNull Dialog dialog) { }
};
buildConfirmDialog(activity,
R.string.delete,
isUserPlaylist(plid)? R.string.msg_delete_musics
: R.string.msg_delete_musics_completely,
action)
.show();
}
public static void
doAddVideosTo(@NonNull final Activity activity,
final Object user,
final OnPostExecuteListener listener,
final long dstPlid,
final long srcPlid,
@NonNull final long[] vids,
final boolean move) {
Task<Void> t = new Task<Void>() {
@Override
protected Void
doAsync() {
Err err = Err.NO_ERR;
DB db = DB.get();
db.beginTransaction();
try {
for (long mid : vids) {
DB.Err dbErr = db.insertVideoToPlaylist(dstPlid, mid);
if (DB.Err.NO_ERR != dbErr) {
// Error Case
if (DB.Err.DUPLICATED != dbErr
|| 1 == vids.length && !move)
err = Err.map(dbErr);
// From here : DB_DUPLICATED Case.
} else {
// "Insertion is OK"
// OR "DB_DUPLICATED but [ 'move == true' or "mids.length > 1" ]
if (move) {
if (free.yhc.netmbuddy.utils.UxUtil.isUserPlaylist(srcPlid))
db.deleteVideoFrom(srcPlid, mid);
else
db.deleteVideoExcept(dstPlid, mid);
}
}
db.setTransactionSuccessful();
}
} finally {
db.endTransaction();
}
final Err result = err;
AppEnv.getUiHandler().post(new Runnable() {
@Override
public void run() {
listener.onPostExecute(result, user);
}
});
return null;
}
};
DialogTask.Builder<DialogTask.Builder> b
= new DialogTask.Builder<>(activity, t);
b.setCancelButtonText(R.string.cancel)
.setMessage(move? R.string.moving: R.string.adding);
if (!b.create().start())
P.bug();
}
public static void
addVideosTo(final Activity activity,
final Object tag,
final OnPostExecuteListener listener,
final long plid,
final long[] vids,
final boolean move) {
final long srcPlid = free.yhc.netmbuddy.utils.UxUtil.isUserPlaylist(plid)? plid: DB.INVALID_PLAYLIST_ID;
free.yhc.netmbuddy.utils.UxUtil.OnPlaylistSelected action = new free.yhc.netmbuddy.utils.UxUtil.OnPlaylistSelected() {
@Override
public void
onPlaylist(long plid, Object user) {
doAddVideosTo(activity, user, listener, plid, srcPlid, vids, move);
}
@Override
public void
onUserMenu(int pos, Object user) {}
};
// exclude current playlist
free.yhc.netmbuddy.utils.UxUtil.buildSelectPlaylistDialog(DB.get(),
activity,
move? R.string.move_to: R.string.add_to,
null,
action,
srcPlid,
tag)
.show();
}
public static void
showVideoDetailInfo(final Activity activity, final long vid) {
Task<Void> t = new Task<Void>() {
private void
postExecute(DMVideo dmv, String[] pls) {
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
String channel = AUtil.getResString(R.string.channel) + " : ";
if (Util.isValidValue(dmv.channelTitle))
channel += dmv.channelTitle;
else
channel += AUtil.getResString(R.string.unknown);
String strTimePlayed;
if (0 == dmv.extra.timePlayed)
strTimePlayed = AUtil.getResString(R.string.not_played_yet);
else
strTimePlayed = df.format(new Date(dmv.extra.timePlayed));
DB.Bookmark[] bookmarks;
if (null == dmv.bookmarks)
// Unexpected error is ignored.
bookmarks = new DB.Bookmark[0];
else
bookmarks = DB.Bookmark.decode(dmv.bookmarks);
String playbackTm = AUtil.getResString(R.string.playback_time) + " : " + dmv.playtime
+ AUtil.getResString(R.string.seconds);
String volume = AUtil.getResString(R.string.volume) + " : " + dmv.volume + " / 100";
String timeAdded = AUtil.getResString(R.string.time_added) + " : " + dmv.extra.timeAdd;
String timePlayed = AUtil.getResString(R.string.time_last_played) + " : " + strTimePlayed;
String ytvid = AUtil.getResString(R.string.youtube_id) + " : " + dmv.ytvid;
String msg = dmv.title + "\n\n"
+ ytvid + "\n"
+ channel + "\n"
+ playbackTm + "\n"
+ volume + "\n"
+ timeAdded + "\n"
+ timePlayed + "\n";
if (bookmarks.length > 0) {
msg += "[ " + AUtil.getResString(R.string.bookmarks) + " ]\n";
for (DB.Bookmark bm : bookmarks)
msg += " <" + Util.secsToMinSecText(bm.pos / 1000) + "> " + bm.name + "\n";
}
msg += "\n[ " + AUtil.getResString(R.string.playlist) + " ]\n";
for (String title : pls)
msg += "* " + title + "\n";
createAlertDialog(activity,
0,
AUtil.getResString(R.string.detail_info),
msg)
.show();
}
@Override
protected Void
doAsync() {
final DB db = DB.get();
final DMVideo dmv = db.getVideoInfo(vid, DMVideo.sDBProjectionExtraWithoutThumbnail);
long[] plids = db.getPlaylistsContainVideo(vid);
final String[] pls = new String[plids.length];
for (int i = 0; i < plids.length; i++)
pls[i] = (String)db.getPlaylistInfo(plids[i], ColPlaylist.TITLE);
AppEnv.getUiHandler().post(new Runnable() {
@Override
public void run() {
postExecute(dmv, pls);
}
});
return null;
}
};
DialogTask.Builder<DialogTask.Builder> b
= new DialogTask.Builder<>(activity, t);
b.setCancelButtonText(R.string.cancel);
b.setMessage(R.string.loading);
if (!b.create().start())
P.bug();
}
// ----------------------------------------------------------------------------------------------------------------
// For bookmark
// ----------------------------------------------------------------------------------------------------------------
public static void
showBookmarkDialog(final Activity activity, final String ytvid, String title) {
ListView lv = (ListView)AUtil.inflateLayout(R.layout.bookmark_dialog);
final DB db = DB.get();
DB.Bookmark[] bms = db.getBookmarks(ytvid);
if (0 == bms.length) {
showTextToast(R.string.msg_empty_bookmarks);
return;
}
AlertDialog.Builder bldr = new AlertDialog.Builder(activity);
bldr.setTitle("[" + AUtil.getResString(R.string.bookmarks) + "]\n" + title);
bldr.setView(lv);
final AlertDialog diag = bldr.create();
BookmarkListAdapter.OnItemAction action = new BookmarkListAdapter.OnItemAction() {
@Override
public void
onDelete(BookmarkListAdapter adapter, int pos, Bookmark bm) {
db.deleteBookmark(ytvid, bm.name, bm.pos);
adapter.removeItem(pos);
adapter.notifyDataSetChanged();
if (0 == adapter.getCount())
diag.dismiss();
}
};
final BookmarkListAdapter adapter = new BookmarkListAdapter(activity,
bms,
action);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void
onItemClick(AdapterView<?> parent, View view, int pos, long id) {
DB.Bookmark bm = (DB.Bookmark)adapter.getItem(pos);
YTPlayer mp = YTPlayer.get();
String activeYtvid = mp.getActiveVideoYtId();
if (ytvid.equals(activeYtvid))
mp.playerSeekTo(bm.pos);
else
showTextToast(R.string.msg_fail_seek_to_bookmark);
diag.dismiss();
}
});
diag.show();
}
// ----------------------------------------------------------------------------------------------------------------
// For searching similar titles
// ----------------------------------------------------------------------------------------------------------------
public static void
showSimilarTitlesDialog(final Activity activity, final String title) {
Task<Void> t = new Task<Void>() {
private void
postExecute(final LinkedList<Long> vidl) {
if (0 == vidl.size()) {
showTextToast(R.string.msg_no_similar_titles);
return;
}
ListView lv = (ListView)AUtil.inflateLayout(R.layout.similar_title_dialog);
AlertDialog.Builder bldr = new AlertDialog.Builder(activity);
bldr.setTitle("[" + AUtil.getResString(R.string.search_similar_titles) + "]\n" + title);
bldr.setView(lv);
final AlertDialog diag = bldr.create();
final SimilarTitlesListAdapter adapter
= new SimilarTitlesListAdapter(
activity,
Util.convertArrayLongTolong(vidl.toArray(new Long[vidl.size()])));
lv.setAdapter(adapter);
diag.show();
}
@Override
protected Void
doAsync() throws InterruptedException {
final LinkedList<Long> vidl = new LinkedList<>();
float similarityThreshold = Util.getPrefTitleSimilarityThreshold();
SCmp scmp = new SCmp();
scmp.setCmpParameter(title, true, null);
try (Cursor c = DB.get().queryVideos(
new ColVideo[] { ColVideo.ID,
ColVideo.TITLE },
null,
false)) {
final int COLI_ID = 0;
final int COLI_TITLE = 1;
if (!c.moveToFirst())
return null;
int maxCnt = c.getCount();
long progcnt = 0;
publishProgressInit(maxCnt);
publishProgress(progcnt);
do {
if (DBG) {
String title = c.getString(COLI_TITLE);
P.v("Calculating similarity : " + title);
float sim = scmp.similarity(title);
P.v(" " + sim);
}
if (similarityThreshold < scmp.similarity(c.getString(COLI_TITLE))) {
vidl.addLast(c.getLong(COLI_ID));
if (vidl.size() >= PolicyConstant.MAX_SIMILAR_TITLES_RESULT)
return null;
}
publishProgress(++progcnt);
if (isCancel())
throw new InterruptedException();
} while (c.moveToNext());
}
AppEnv.getUiHandler().post(new Runnable() {
@Override
public void run() {
postExecute(vidl);
}
});
return null;
}
};
DialogTask.Builder<DialogTask.Builder> b
= new DialogTask.Builder<>(activity, t);
b.setStyle(DialogTask.Style.PROGRESS);
b.setCancelButtonText(R.string.cancel);
b.setMessage(R.string.searching);
if (!b.create().start())
P.bug();
}
}