You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
427 lines
12 KiB
427 lines
12 KiB
10 years ago
|
package acr.browser.lightning;
|
||
|
|
||
9 years ago
|
import java.io.BufferedInputStream;
|
||
|
import java.io.File;
|
||
|
import java.io.FileInputStream;
|
||
|
import java.io.FileOutputStream;
|
||
|
import java.io.FilenameFilter;
|
||
|
import java.io.IOException;
|
||
|
import java.io.InputStream;
|
||
|
import java.io.UnsupportedEncodingException;
|
||
|
import java.net.HttpURLConnection;
|
||
|
import java.net.URL;
|
||
|
import java.net.URLEncoder;
|
||
|
import java.util.ArrayList;
|
||
|
import java.util.List;
|
||
|
import java.util.Locale;
|
||
|
|
||
|
import org.xmlpull.v1.XmlPullParser;
|
||
|
import org.xmlpull.v1.XmlPullParserFactory;
|
||
|
|
||
9 years ago
|
import android.annotation.SuppressLint;
|
||
10 years ago
|
import android.app.Activity;
|
||
|
import android.content.Context;
|
||
9 years ago
|
import android.content.res.Resources.Theme;
|
||
10 years ago
|
import android.graphics.Color;
|
||
|
import android.net.ConnectivityManager;
|
||
|
import android.net.NetworkInfo;
|
||
|
import android.os.AsyncTask;
|
||
9 years ago
|
import android.os.Build;
|
||
10 years ago
|
import android.view.LayoutInflater;
|
||
|
import android.view.View;
|
||
|
import android.view.ViewGroup;
|
||
9 years ago
|
import android.widget.BaseAdapter;
|
||
|
import android.widget.Filter;
|
||
|
import android.widget.Filterable;
|
||
|
import android.widget.ImageView;
|
||
|
import android.widget.TextView;
|
||
10 years ago
|
|
||
|
public class SearchAdapter extends BaseAdapter implements Filterable {
|
||
|
|
||
|
private List<HistoryItem> mHistory;
|
||
|
private List<HistoryItem> mBookmarks;
|
||
|
private List<HistoryItem> mSuggestions;
|
||
|
private List<HistoryItem> mFilteredList;
|
||
|
private List<HistoryItem> mAllBookmarks;
|
||
9 years ago
|
private HistoryDatabase mDatabaseHandler;
|
||
10 years ago
|
private Context mContext;
|
||
9 years ago
|
private boolean mUseGoogle = true;
|
||
9 years ago
|
private boolean mIsExecuting = false;
|
||
9 years ago
|
private boolean mDarkTheme;
|
||
9 years ago
|
private boolean mIncognito;
|
||
10 years ago
|
private BookmarkManager mBookmarkManager;
|
||
9 years ago
|
private static final String ENCODING = "ISO-8859-1";
|
||
9 years ago
|
private static final long INTERVAL_DAY = 86400000;
|
||
9 years ago
|
private String mSearchSubtitle;
|
||
9 years ago
|
private static final int API = Build.VERSION.SDK_INT;
|
||
|
private Theme mTheme;
|
||
9 years ago
|
private SearchFilter mFilter;
|
||
10 years ago
|
|
||
9 years ago
|
public SearchAdapter(Context context, boolean dark, boolean incognito) {
|
||
|
mDatabaseHandler = HistoryDatabase.getInstance(context.getApplicationContext());
|
||
9 years ago
|
mTheme = context.getTheme();
|
||
10 years ago
|
mFilteredList = new ArrayList<HistoryItem>();
|
||
|
mHistory = new ArrayList<HistoryItem>();
|
||
|
mBookmarks = new ArrayList<HistoryItem>();
|
||
|
mSuggestions = new ArrayList<HistoryItem>();
|
||
9 years ago
|
mBookmarkManager = BookmarkManager.getInstance(context.getApplicationContext());
|
||
10 years ago
|
mAllBookmarks = mBookmarkManager.getBookmarks(true);
|
||
9 years ago
|
mUseGoogle = PreferenceManager.getInstance().getGoogleSearchSuggestionsEnabled();
|
||
10 years ago
|
mContext = context;
|
||
9 years ago
|
mSearchSubtitle = mContext.getString(R.string.suggestion);
|
||
9 years ago
|
mDarkTheme = dark || incognito;
|
||
|
mIncognito = incognito;
|
||
9 years ago
|
Thread delete = new Thread(new Runnable() {
|
||
|
|
||
|
@Override
|
||
|
public void run() {
|
||
|
deleteOldCacheFiles(mContext);
|
||
|
}
|
||
|
|
||
|
});
|
||
|
delete.start();
|
||
|
}
|
||
|
|
||
|
private void deleteOldCacheFiles(Context context) {
|
||
|
File dir = new File(context.getCacheDir().toString());
|
||
|
String[] fileList = dir.list(new NameFilter());
|
||
|
long earliestTimeAllowed = System.currentTimeMillis() - INTERVAL_DAY;
|
||
|
for (String fileName : fileList) {
|
||
|
File file = new File(dir.getPath() + fileName);
|
||
|
if (earliestTimeAllowed > file.lastModified()) {
|
||
|
file.delete();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private class NameFilter implements FilenameFilter {
|
||
|
|
||
|
private static final String ext = ".sgg";
|
||
|
|
||
|
@Override
|
||
|
public boolean accept(File dir, String filename) {
|
||
|
return filename.endsWith(ext);
|
||
|
}
|
||
|
|
||
10 years ago
|
}
|
||
|
|
||
|
public void refreshPreferences() {
|
||
9 years ago
|
mUseGoogle = PreferenceManager.getInstance().getGoogleSearchSuggestionsEnabled();
|
||
10 years ago
|
if (!mUseGoogle && mSuggestions != null) {
|
||
|
mSuggestions.clear();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void refreshBookmarks() {
|
||
10 years ago
|
mAllBookmarks = mBookmarkManager.getBookmarks(true);
|
||
10 years ago
|
}
|
||
|
|
||
|
@Override
|
||
|
public int getCount() {
|
||
|
if (mFilteredList != null) {
|
||
|
return mFilteredList.size();
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public Object getItem(int position) {
|
||
|
return mFilteredList.get(position);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public long getItemId(int position) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
9 years ago
|
@SuppressWarnings("deprecation")
|
||
|
@SuppressLint("NewApi")
|
||
10 years ago
|
@Override
|
||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||
|
View row = convertView;
|
||
|
SuggestionHolder holder = null;
|
||
|
|
||
|
if (row == null) {
|
||
|
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
|
||
10 years ago
|
row = inflater.inflate(R.layout.two_line_autocomplete, parent, false);
|
||
10 years ago
|
|
||
|
holder = new SuggestionHolder();
|
||
|
holder.mTitle = (TextView) row.findViewById(R.id.title);
|
||
|
holder.mUrl = (TextView) row.findViewById(R.id.url);
|
||
|
holder.mImage = (ImageView) row.findViewById(R.id.suggestionIcon);
|
||
|
row.setTag(holder);
|
||
|
} else {
|
||
|
holder = (SuggestionHolder) row.getTag();
|
||
|
}
|
||
|
|
||
|
HistoryItem web = mFilteredList.get(position);
|
||
|
holder.mTitle.setText(web.getTitle());
|
||
|
holder.mUrl.setText(web.getUrl());
|
||
|
|
||
|
int imageId = R.drawable.ic_bookmark;
|
||
|
switch (web.getImageId()) {
|
||
10 years ago
|
case R.drawable.ic_bookmark: {
|
||
9 years ago
|
if (!mDarkTheme) {
|
||
10 years ago
|
imageId = R.drawable.ic_bookmark;
|
||
|
} else {
|
||
|
holder.mTitle.setTextColor(Color.WHITE);
|
||
|
imageId = R.drawable.ic_bookmark_dark;
|
||
|
}
|
||
|
break;
|
||
10 years ago
|
}
|
||
10 years ago
|
case R.drawable.ic_search: {
|
||
9 years ago
|
if (!mDarkTheme) {
|
||
10 years ago
|
imageId = R.drawable.ic_search;
|
||
|
} else {
|
||
|
holder.mTitle.setTextColor(Color.WHITE);
|
||
|
imageId = R.drawable.ic_search_dark;
|
||
|
}
|
||
|
break;
|
||
10 years ago
|
}
|
||
10 years ago
|
case R.drawable.ic_history: {
|
||
9 years ago
|
if (!mDarkTheme) {
|
||
10 years ago
|
imageId = R.drawable.ic_history;
|
||
|
} else {
|
||
|
holder.mTitle.setTextColor(Color.WHITE);
|
||
|
imageId = R.drawable.ic_history_dark;
|
||
|
}
|
||
|
break;
|
||
10 years ago
|
}
|
||
|
}
|
||
|
|
||
9 years ago
|
if (API < Build.VERSION_CODES.LOLLIPOP) {
|
||
|
holder.mImage.setImageDrawable(mContext.getResources().getDrawable(imageId));
|
||
|
} else {
|
||
|
holder.mImage.setImageDrawable(mContext.getResources().getDrawable(imageId, mTheme));
|
||
|
}
|
||
10 years ago
|
|
||
|
return row;
|
||
|
}
|
||
|
|
||
|
public void setContents(List<HistoryItem> list) {
|
||
|
if (mFilteredList != null) {
|
||
|
mFilteredList.clear();
|
||
|
mFilteredList.addAll(list);
|
||
9 years ago
|
} else {
|
||
|
mFilteredList = list;
|
||
10 years ago
|
}
|
||
9 years ago
|
notifyDataSetChanged();
|
||
10 years ago
|
}
|
||
|
|
||
|
@Override
|
||
|
public Filter getFilter() {
|
||
9 years ago
|
if (mFilter == null) {
|
||
|
mFilter = new SearchFilter();
|
||
|
}
|
||
|
return mFilter;
|
||
10 years ago
|
}
|
||
|
|
||
|
public class SearchFilter extends Filter {
|
||
|
|
||
|
@Override
|
||
|
protected FilterResults performFiltering(CharSequence constraint) {
|
||
|
FilterResults results = new FilterResults();
|
||
9 years ago
|
if (constraint == null || constraint.toString() == null) {
|
||
10 years ago
|
return results;
|
||
|
}
|
||
10 years ago
|
String query = constraint.toString().toLowerCase(Locale.getDefault());
|
||
9 years ago
|
if (mUseGoogle && !mIncognito && !mIsExecuting) {
|
||
10 years ago
|
new RetrieveSearchSuggestions().execute(query);
|
||
|
}
|
||
|
|
||
|
int counter = 0;
|
||
|
mBookmarks = new ArrayList<HistoryItem>();
|
||
|
for (int n = 0; n < mAllBookmarks.size(); n++) {
|
||
|
if (counter >= 5) {
|
||
|
break;
|
||
|
}
|
||
10 years ago
|
if (mAllBookmarks.get(n).getTitle().toLowerCase(Locale.getDefault())
|
||
|
.startsWith(query)) {
|
||
10 years ago
|
mBookmarks.add(mAllBookmarks.get(n));
|
||
|
counter++;
|
||
10 years ago
|
} else if (mAllBookmarks.get(n).getUrl().contains(query)) {
|
||
|
mBookmarks.add(mAllBookmarks.get(n));
|
||
|
counter++;
|
||
10 years ago
|
}
|
||
|
|
||
|
}
|
||
9 years ago
|
if (mDatabaseHandler == null) {
|
||
9 years ago
|
mDatabaseHandler = HistoryDatabase.getInstance(mContext.getApplicationContext());
|
||
10 years ago
|
}
|
||
10 years ago
|
mHistory = mDatabaseHandler.findItemsContaining(constraint.toString());
|
||
9 years ago
|
|
||
9 years ago
|
results.count = 1;
|
||
10 years ago
|
return results;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public CharSequence convertResultToString(Object resultValue) {
|
||
|
return ((HistoryItem) resultValue).getUrl();
|
||
|
}
|
||
|
|
||
|
@Override
|
||
10 years ago
|
protected void publishResults(CharSequence constraint, FilterResults results) {
|
||
9 years ago
|
mFilteredList = getSuggestions();
|
||
9 years ago
|
notifyDataSetChanged();
|
||
10 years ago
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
private class SuggestionHolder {
|
||
|
ImageView mImage;
|
||
|
TextView mTitle;
|
||
|
TextView mUrl;
|
||
|
}
|
||
|
|
||
10 years ago
|
private class RetrieveSearchSuggestions extends AsyncTask<String, Void, List<HistoryItem>> {
|
||
10 years ago
|
|
||
9 years ago
|
private XmlPullParserFactory mFactory;
|
||
|
private XmlPullParser mXpp;
|
||
9 years ago
|
|
||
10 years ago
|
@Override
|
||
|
protected List<HistoryItem> doInBackground(String... arg0) {
|
||
9 years ago
|
mIsExecuting = true;
|
||
9 years ago
|
|
||
10 years ago
|
List<HistoryItem> filter = new ArrayList<HistoryItem>();
|
||
|
String query = arg0[0];
|
||
|
try {
|
||
|
query = query.replace(" ", "+");
|
||
9 years ago
|
URLEncoder.encode(query, ENCODING);
|
||
10 years ago
|
} catch (UnsupportedEncodingException e) {
|
||
|
e.printStackTrace();
|
||
|
}
|
||
9 years ago
|
File cache = downloadSuggestionsForQuery(query);
|
||
|
if (!cache.exists()) {
|
||
|
return filter;
|
||
|
}
|
||
|
InputStream fileInput = null;
|
||
10 years ago
|
try {
|
||
9 years ago
|
fileInput = new BufferedInputStream(new FileInputStream(cache));
|
||
9 years ago
|
if (mFactory == null) {
|
||
|
mFactory = XmlPullParserFactory.newInstance();
|
||
|
mFactory.setNamespaceAware(true);
|
||
|
}
|
||
|
if (mXpp == null) {
|
||
|
mXpp = mFactory.newPullParser();
|
||
|
}
|
||
9 years ago
|
mXpp.setInput(fileInput, ENCODING);
|
||
9 years ago
|
int eventType = mXpp.getEventType();
|
||
|
int counter = 0;
|
||
|
while (eventType != XmlPullParser.END_DOCUMENT) {
|
||
9 years ago
|
if (eventType == XmlPullParser.START_TAG && "suggestion".equals(mXpp.getName())) {
|
||
|
String suggestion = mXpp.getAttributeValue(null, "data");
|
||
|
filter.add(new HistoryItem(mSearchSubtitle + " \"" + suggestion + '"',
|
||
|
suggestion, R.drawable.ic_search));
|
||
|
counter++;
|
||
|
if (counter >= 5) {
|
||
|
break;
|
||
10 years ago
|
}
|
||
|
}
|
||
9 years ago
|
eventType = mXpp.next();
|
||
10 years ago
|
}
|
||
9 years ago
|
} catch (Exception e) {
|
||
9 years ago
|
return filter;
|
||
9 years ago
|
} finally {
|
||
9 years ago
|
if (fileInput != null) {
|
||
9 years ago
|
try {
|
||
9 years ago
|
fileInput.close();
|
||
9 years ago
|
} catch (IOException e) {
|
||
9 years ago
|
e.printStackTrace();
|
||
9 years ago
|
}
|
||
|
}
|
||
10 years ago
|
}
|
||
|
return filter;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected void onPostExecute(List<HistoryItem> result) {
|
||
9 years ago
|
mSuggestions = result;
|
||
|
mFilteredList = getSuggestions();
|
||
|
notifyDataSetChanged();
|
||
9 years ago
|
mIsExecuting = false;
|
||
10 years ago
|
}
|
||
|
|
||
|
}
|
||
|
|
||
9 years ago
|
private File downloadSuggestionsForQuery(String query) {
|
||
|
File cacheFile = new File(mContext.getCacheDir(), query.hashCode() + ".sgg");
|
||
|
if (System.currentTimeMillis() - INTERVAL_DAY < cacheFile.lastModified()) {
|
||
|
return cacheFile;
|
||
|
}
|
||
|
if (!isNetworkConnected(mContext)) {
|
||
|
return cacheFile;
|
||
|
}
|
||
|
try {
|
||
|
URL url = new URL("http://google.com/complete/search?q=" + query
|
||
|
+ "&output=toolbar&hl=en");
|
||
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||
|
connection.setDoInput(true);
|
||
|
connection.connect();
|
||
|
InputStream in = connection.getInputStream();
|
||
|
|
||
|
if (in != null) {
|
||
|
FileOutputStream fos = new FileOutputStream(cacheFile);
|
||
|
int buffer;
|
||
|
while ((buffer = in.read()) != -1) {
|
||
|
fos.write(buffer);
|
||
|
}
|
||
|
fos.flush();
|
||
|
fos.close();
|
||
|
}
|
||
|
cacheFile.setLastModified(System.currentTimeMillis());
|
||
|
} catch (Exception e) {
|
||
|
e.printStackTrace();
|
||
|
}
|
||
|
return cacheFile;
|
||
|
}
|
||
|
|
||
10 years ago
|
private boolean isNetworkConnected(Context context) {
|
||
|
NetworkInfo networkInfo = getActiveNetworkInfo(context);
|
||
|
return networkInfo != null && networkInfo.isConnected();
|
||
|
}
|
||
|
|
||
|
private NetworkInfo getActiveNetworkInfo(Context context) {
|
||
|
ConnectivityManager connectivity = (ConnectivityManager) context
|
||
|
.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||
|
if (connectivity == null) {
|
||
|
return null;
|
||
|
}
|
||
|
return connectivity.getActiveNetworkInfo();
|
||
|
}
|
||
|
|
||
|
public List<HistoryItem> getSuggestions() {
|
||
|
List<HistoryItem> filteredList = new ArrayList<HistoryItem>();
|
||
|
|
||
9 years ago
|
int suggestionsSize = (mSuggestions == null) ? 0 : mSuggestions.size();
|
||
|
int historySize = (mHistory == null) ? 0 : mHistory.size();
|
||
|
int bookmarkSize = (mBookmarks == null) ? 0 : mBookmarks.size();
|
||
10 years ago
|
|
||
9 years ago
|
int maxSuggestions = (bookmarkSize + historySize < 3) ? (5 - bookmarkSize - historySize)
|
||
|
: (bookmarkSize < 2) ? (4 - bookmarkSize) : (historySize < 1) ? 3 : 2;
|
||
|
int maxHistory = (suggestionsSize + bookmarkSize < 4) ? (5 - suggestionsSize - bookmarkSize)
|
||
|
: 1;
|
||
|
int maxBookmarks = (suggestionsSize + historySize < 3) ? (5 - suggestionsSize - historySize)
|
||
|
: 2;
|
||
10 years ago
|
|
||
9 years ago
|
if (!mUseGoogle || mIncognito) {
|
||
10 years ago
|
maxHistory++;
|
||
|
maxBookmarks++;
|
||
|
}
|
||
|
|
||
9 years ago
|
for (int n = 0; n < bookmarkSize && n < maxBookmarks; n++) {
|
||
10 years ago
|
filteredList.add(mBookmarks.get(n));
|
||
|
}
|
||
|
|
||
9 years ago
|
for (int n = 0; n < historySize && n < maxHistory; n++) {
|
||
10 years ago
|
filteredList.add(mHistory.get(n));
|
||
|
}
|
||
|
|
||
9 years ago
|
for (int n = 0; n < suggestionsSize && n < maxSuggestions; n++) {
|
||
10 years ago
|
filteredList.add(mSuggestions.get(n));
|
||
|
}
|
||
|
return filteredList;
|
||
|
}
|
||
9 years ago
|
|
||
10 years ago
|
}
|