<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.openintents.safe" \r
- android:versionCode="11" android:versionName="1.2.2">\r
+ android:versionName="1.2.3" android:versionCode="12">\r
<!-- History:
- 1.2.2 [11]: 2009-10-29
+ 1.2.3 [12]: 2009-11-12\r
+ 1.2.2 [11]: 2009-10-29\r
1.2.1 [10]: 2009-10-23\r
1.2.0 [9]: 2009-08-22\r
1.1.1 [8]: 2009-05-30\r
<uses-permission android:name="org.openintents.safe.ACCESS_INTENTS" />
<uses-permission android:name="org.openintents.safe.ACCESS_SERVICE" />
-<uses-sdk android:minSdkVersion="3"></uses-sdk>
+<uses-sdk android:targetSdkVersion="4" android:minSdkVersion="3"></uses-sdk>
+<supports-screens android:normalScreens="true" android:smallScreens="true" android:largeScreens="true"></supports-screens>
</manifest>
# "build.properties", and override values to adapt the script to your
# project structure.
+# Indicates whether an apk should be generated for each density.
+split.density=false
# Project target.
-target=android-3
-# apk configurations. This property allows creation of APK files with limited
-# resources. For example, if your application contains many locales and
-# you wish to release multiple smaller apks instead of a large one, you can
-# define configuration to create apks with limited language sets.
-# Format is a comma separated list of configuration names. For each
-# configuration, a property will declare the resource configurations to
-# include. Example:
-# apk-configurations=european,northamerica
-# apk-config-european=en,fr,it,de,es
-# apk-config-northamerica=en,es
+target=android-4
apk-configurations=
To obtain the current release, visit\r
http://www.openintents.org\r
\r
+---------------------------------------------------------\r
+release: 1.2.3\r
+date: 2009-11-12\r
+- add counts to Category List\r
+- support small, normal, large screens\r
+\r
---------------------------------------------------------\r
release: 1.2.2\r
date: 2009-10-29\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+* $Id$
+*
+* Copyright 2009 OpenIntents.org
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ <TextView
+ android:id="@+id/rowCount"
+ android:text="0"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:gravity="center_vertical"
+ android:paddingLeft="6dip"
+ android:paddingRight="10dip"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:layout_alignParentRight="true"
+ />
+
+ <TextView
+ android:id="@+id/rowName"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:gravity="center_vertical"
+ android:paddingLeft="6dip"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:layout_alignParentLeft="@+id/rowCount"
+ />
+</RelativeLayout>
\ No newline at end of file
public boolean nameNeedsDecrypt;
public String plainName;
public boolean plainNameNeedsEncrypt=true;
+ int count=0;
+
+ public String getName() {
+ return name;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public CategoryEntry () {
+ name = "";
+ }
+
+ public CategoryEntry (String _name) {
+ name = _name;
+ }
+
+ public CategoryEntry (String _name, int _count) {
+ name = _name;
+ count = _count;
+ }
+
+ @Override
+ public String toString() {
+ return name + " " + count;
+ }
+
}
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Toast;
private static String masterKey;
private List<CategoryEntry> rows=null;
+ private CategoryListItemAdapter catAdapter;
private Intent restartTimerIntent=null;
private int lastPosition=0;
*/
private void fillData() {
if (debug) Log.d(TAG,"fillData()");
- List<String> categoryNames=Passwords.getCategoryNames();
rows=Passwords.getCategoryEntries();
if (debug) Log.d(TAG,"fillData: rows="+rows.size());
- ArrayAdapter<String> entries =
- new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,
- categoryNames);
- setListAdapter(entries);
+ catAdapter =
+ new CategoryListItemAdapter(this, R.layout.cat_row,
+ rows);
+ setListAdapter(catAdapter);
}
setSelection(lastPosition);
}
}
+ if (requestCode==REQUEST_OPEN_CATEGORY) {
+ // update in case passwords were added/deleted and caused the counts to update
+ catAdapter.notifyDataSetChanged();
+ }
}
private void prePopulate() {
--- /dev/null
+/* $Id$
+ *
+ * Copyright 2009 OpenIntents.org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.openintents.safe;
+
+import java.util.List;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+/**
+ * @author Randy McEoin
+ *
+ * Many thanks to Professional Android Application Development by Reto Meier
+ * from which this adapter is based upon.
+ */
+public class CategoryListItemAdapter extends ArrayAdapter<CategoryEntry> {
+
+ private static boolean debug = false;
+ private static final String TAG = "CategoryListItemAdapter";
+
+ int resource;
+
+ public CategoryListItemAdapter(Context _context, int _resource,
+ List<CategoryEntry> _items) {
+ super(_context, _resource, _items);
+ resource = _resource;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ LinearLayout categoryListView;
+
+ CategoryEntry item = getItem(position);
+
+ String name = item.plainName;
+ int count = item.count;
+
+ if (convertView == null) {
+ categoryListView = new LinearLayout(getContext());
+ String inflater = Context.LAYOUT_INFLATER_SERVICE;
+ LayoutInflater vi;
+ vi = (LayoutInflater)getContext().getSystemService(inflater);
+ vi.inflate(resource, categoryListView, true);
+ } else {
+ categoryListView = (LinearLayout) convertView;
+ }
+
+ TextView nameView = (TextView)categoryListView.findViewById(R.id.rowName);
+ TextView countView = (TextView)categoryListView.findViewById(R.id.rowCount);
+
+ if (debug) Log.d(TAG, "count="+count);
+ nameView.setText(name);
+ countView.setText(Integer.toString(count));
+
+ return categoryListView;
+ }
+}
+
return row;
}
+ public int getCategoryCount(long Id) {
+ int count = 0;
+ try {
+ Cursor c =
+ db.rawQuery("SELECT count(*) FROM "+TABLE_PASSWORDS+" WHERE category=" + Id, null);
+ if (c.getCount() > 0) {
+ c.moveToFirst();
+ count = c.getInt(0);
+ }
+ c.close();
+ } catch (SQLException e)
+ {
+ Log.d(TAG,"SQLite exception: " + e.getLocalizedMessage());
+ }
+ return count;
+ }
+
/**
*
* @param Id
package org.openintents.safe;
+import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
+import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
catEntry.nameNeedsDecrypt=false;
categoryEntries.put(id, catEntry);
}
+ catEntry.count=dbHelper.getCategoryCount(id);
return catEntry;
}
return catEntry.id;
}
+ public static void updateCategoryCount(long id) {
+ CategoryEntry catEntry=categoryEntries.get(id);
+ if (catEntry==null) {
+ return;
+ }
+ catEntry.count=dbHelper.getCategoryCount(id);
+ }
+
public static void deleteCategoryEntry(long id) {
if (debug) Log.d(TAG,"deleteCategoryEntry("+id+")");
dbHelper.deleteCategory(id);
}
passEntry.needsEncrypt=false;
}
+ // Format the current time.
+ Date date = new Date();
+ DateFormat df = DateFormat.getDateTimeInstance(DateFormat.DEFAULT,DateFormat.LONG);
+ passEntry.lastEdited=df.format(date);
+
if (passEntry.id==0) {
passEntry.id=dbHelper.addPassword(passEntry);
+ updateCategoryCount(passEntry.category);
} else {
dbHelper.updatePassword(passEntry.id, passEntry);
}
public static void deletePassEntry(long id) {
if (debug) Log.d(TAG,"deletePassEntry("+id+")");
+ PassEntry passEntry=getPassEntry(id, false, false);
+ if (passEntry==null) {
+ return;
+ }
+ long categoryId=passEntry.category;
dbHelper.deletePassword(id);
passEntries.remove(id);
+ updateCategoryCount(categoryId);
}
public static void updatePassCategory(long passId, long categoryId) {
import android.os.CountDownTimer;
public class ServiceDispatchImpl extends Service {
- private static boolean debug = true;
+ private static boolean debug = false;
private static String TAG = "ServiceDispatchIMPL";
public static CryptoHelper ch; // TODO Peli: Could clean this up by moving it into a singleton? Or at least a separate static class?
private String salt;