try { String u = "https://..."; // Add your data ListnameValuePairs = new ArrayList (2); nameValuePairs.add(new BasicNameValuePair("id", "1")); // ... UrlEncodedFormEntity entity = new UrlEncodedFormEntity(nameValuePairs); URL url = new URL(u); HttpsURLConnection request = (HttpsURLConnection) url.openConnection(); request.setUseCaches(false); request.setDoOutput(true); request.setDoInput(true); request.setRequestMethod("POST"); OutputStream post = request.getOutputStream(); entity.writeTo(post); post.flush(); BufferedReader in = new BufferedReader(new InputStreamReader(request.getInputStream())); String inputLine, response = ""; while ((inputLine = in.readLine()) != null) { response += inputLine; } post.close(); in.close(); } catch (Exception e) { Log.e("Your app", "error", e); }
Showing posts with label java. Show all posts
Showing posts with label java. Show all posts
May 17, 2014
HttpsURLConnection POST example with NameValuePair and UrlEncodedFormEntity
May 16, 2014
javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
Dealing with the above mentioned Exception has sent me into a wild-goose chase for a quick fix.
Unfortunately the depth of this problem is much larger than I anticipated.A quick web search suggests that there is a problem with the SSL chain, therefore this would mean that there is a SSL configuration problem on the server, that it's not serving the certificates correctly, eg. in the correct order, or using a self-signed certificate in which case the server also acts as the Certificate Authority.
Some mentioned solutions were to implement your own SSL Client, with a Trust Manager that does absolutely nothing. This is VERY VERY BAD. Don't do it.
Other suggestions were to use your own Trust Keystore (when using self signed certificates, or using "untrusted CAs", like, for example, a university CA).
But if you're using a trusted CA this shouldn't be a problem, right?
For a SSL Server Test you can use Qualys' tool here:
https://www.ssllabs.com/ssltest/analyze.html?d=example.com
Using this test I found no errors on the domain, but there was a notice that the site only works in browsers with SNI support.
SNI (Server Name Indication) is kind of like a Virtual Host for SSL. Usually SSL certificates were issued for an IP address, but having multiple virtual hosts on the same server can cause problems like different browsers getting different SSL certificates from the same server.
You can test this if you have Android <= 2.3.7. Open the browser and navigate to the site. If you get a certificate warning, check the certificate.
So, obviously, if old browsers have this problems, there are going to be problems in the code too.
The answer here summarizes it. The best workaround seems to be to use another library, which supports SNI.
http://stackoverflow.com/questions/21956663/why-does-android-get-the-wrong-ssl-certificate-two-domains-one-server
The most likely cause for this problem is that the server uses Server Name Indication to choose which certificate to send. If the client doesn't support SNI, the server cannot choose which certificate to send during the SSL/TLS handshake (before any HTTP traffic is sent). SNI is required when you want to use multiple certificates on the same IP address and port, but not all clients support it (notoriously, IE on any version of Windows XP, and a number of mobile browsers).
You're also visibly using the Apache HTTP Client library (not HttpsURLConnection
, for which there can be SNI support with some Android versions. Support for SNI in the Apache HTTP Client library is quite recent, and certainly hasn't made it into the Android stack.You may find the workaround described in this article useful (although it seems only to work for Android 4.2+).
Another two options would be:
- to use a distinct IP address for each host (so as not to need SNI), if you're in control of server, or
- to use another HTTP Client library (e.g.
HttpsURLConnection
).
Other notes:
Installing the INTERMEDIATE certificate into Apache on Ubuntu/Debian systems
Credits: https://gist.github.com/mgedmin/7124635
- download https://www.startssl.com/certs/sub.class1.server.ca.pem (or you know, whatever)
- put this in your Apache config (e.g. inside a
directive):
SSLCertificateFile /etc/ssl/certs/subdomain.example.com.crt
SSLCertificateKeyFile /etc/ssl/private/subdomain.example.com.pem
SSLCertificateChainFile /etc/ssl/certs/startssl-class1-intermediate.crt
Mar 25, 2013
Java, PHP :: RSA Asymmetric Encryption
Information Security and Privacy was a pretty fun and interesting class I had in college, I learned quite a lot of interesting new stuff, but when it came down to it, in practice, I had some problems implementing encrypted communication between Android (Java) frontend and PHP backend because of a tiny little detail.
Algorithm of choice was RSA and the most important part is to use "RSA/ECB/PKCS1PADDING" algorithm when calling Cipher instance in Java, other stuff is pretty straightforward.
Imagine a scenario where Alice sends an encrypted message to Bob.
As you can see, Alice encrypts data with Bob's public key, and only Bob can decrypt it, because only he has his private key.
Here's the Java code (Warning, some Android elements ahead)
Algorithm of choice was RSA and the most important part is to use "RSA/ECB/PKCS1PADDING" algorithm when calling Cipher instance in Java, other stuff is pretty straightforward.
RSA works like this. |
As you can see, Alice encrypts data with Bob's public key, and only Bob can decrypt it, because only he has his private key.
Here's the Java code (Warning, some Android elements ahead)
public class Encryption { private static Key privKey; private static PublicKey pubKey; private static PublicKey servPub; private static String tag = "Encryption"; private static String[] alg = {"RSA","RSA/ECB/PKCS1PADDING"}; private static String hash = "SHA1";
private static String serverPubKeyB64 = ""; //Bob's public key here public static String encrypt(String data) { return b64(encrpyt(data.getBytes())); } public static byte[] encrpyt(byte[] data) { genKey(); try { Cipher c1 = Cipher.getInstance(alg[1]); c1.init(Cipher.ENCRYPT_MODE, getServPub()); return c1.doFinal(data); } catch(Exception e) { Log.e(tag, "encrpyt", e); } return new byte[0]; } public static void genKey() { if (privKey == null || pubKey == null) { Log.i(tag, "generating key"); try { KeyPairGenerator kpg = KeyPairGenerator.getInstance(alg[0]); kpg.initialize(1024); KeyPair kp = kpg.generateKeyPair(); privKey = kp.getPrivate(); pubKey = kp.getPublic(); } catch (Exception e) { Log.e(tag, "genKey", e); } } } public static PublicKey getServPub() { if(servPub == null) { try { byte[] encodedPublicKey = b64decode(serverPubKeyB64); KeyFactory keyFactory = KeyFactory.getInstance(alg[0]); X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey); PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); return publicKey; } catch(Exception e) { Log.e(tag, "getServPub", e); } } return servPub; } public static PublicKey getPubKey() { genKey(); return pubKey; } public static String getPubKeyB64() { PublicKey key = getPubKey(); if(key != null) { return b64(getPubKey().getEncoded()); } else { Log.e(tag, "getPubKeyB64 - key is null"); return ""; } } public static String b64(byte[] b) { return Base64.encodeToString(b, Base64.DEFAULT); } public static byte[] b64decode(String str) { return Base64.decode(str, Base64.DEFAULT); } public static String sha1(String data) { return sha1(data.getBytes()); } public static String sha1(byte[] data) { return formatString(sha1bytes(data)); } public static byte[] sha1bytes(byte[] data) { try { MessageDigest md = MessageDigest.getInstance(hash); return md.digest(data); } catch(Exception e) { Log.e(tag, "sha1", e); return new byte[0]; } } @SuppressLint("DefaultLocale") public static String formatString(byte[] data) { StringBuilder sb = new StringBuilder(); for (byte b : data) { sb.append(String.format("%02X", b)); } return sb.toString().toLowerCase(); } }And the PHP code:
class Encryption { public $pubkey = '...'; public $privkey; public function __construct() { $this->privkey = openssl_pkey_get_private(file_get_contents('....pem')); } public function encrypt($data) { if (openssl_public_encrypt($data, $encrypted, $this->pubkey)) $data = base64_encode($encrypted); else throw new Exception('Unable to encrypt data.'); return $data; } public function decrypt($data) { if (openssl_private_decrypt(base64_decode($data), $decrypted, $this->privkey)) $data = $decrypted; else $data = ''; return $data; } }
Sep 15, 2012
Java :: calculating approximate sunset and sunrise
Here's a class for calculating an approximate time of the sunset, sunrise and day length on a given date, on a given location (latitude coordinate). It takes into account leap years and daylight saving time offset.
It's accurate to about 20 minutes (compared to results from WolframAlpha).
Also, because the constructor Date(int year, int month, int day) is marked as deprecated, GregorianCalendar class is used instead.
View the project on GitHub.
It's accurate to about 20 minutes (compared to results from WolframAlpha).
Also, because the constructor Date(int year, int month, int day) is marked as deprecated, GregorianCalendar class is used instead.
View the project on GitHub.
import java.util.*; /* * Calculate sunset and sunrise on a given day on a given location * * GPL, MIT License * 2012, Žan Kafol, Ana Grum */ public class Analemma { // Maximum axial tilt is 23°26'15" public static double MAX_DECLINATION = 23 + 26/60 + 15/3600; /* * Test - print out sunset for all days in this year */ public static void main(String[] args) { Calendar calendar = Calendar.getInstance(); // our chosen latitude coordinate double latitude = 45.772792; // for each month for (int m = 0; m < 12; m++) { calendar.set(Calendar.MONTH, m); // for each day in that month for (int d = 1; d <= calendar.getActualMaximum(Calendar.DAY_OF_MONTH); d++) { System.out.println(sunset(latitude, calendar.get(Calendar.YEAR), m, d)); } } } /* * Returns a Date object representing the time and date of the sunset for * the given parameters. The formula takes into account the daylight saving * time offset. * * @param double latitude coordinate for calculating the sunset * @param int the year for calculating the sunset * @param int the month (0..January, 1..February, ...) for calculating the sunset * @param int the day of month for calculating the sunset * @return the time and date of the sunset * @see dayLength */ public static Date sunset(double latitude, int year, int month, int day) { double dayLength = dayLength(latitude, year, month, day); double hour = 12 + dayLength / 2 + daylightSaving(year, month, day); return getDate(year, month, day, hour); } /* * Returns a Date object representing the time and date of the sunrise for * the given parameters. The formula takes into account the daylight saving * time offset. * * @param double latitude coordinate for calculating the sunrise * @param int the year for calculating the sunrise * @param int the month (0..January, 1..February, ...) for calculating the sunrise * @param int the day of month for calculating the sunrise * @return the time and date of the sunrise * @see dayLength */ public static Date sunrise(double latitude, int year, int month, int day) { double dayLength = dayLength(latitude, year, month, day); double hour = 12 - dayLength / 2 + daylightSaving(year, month, day); return getDate(year, month, day, hour); } /* * Returns the length of a day for the given parameters in hours. The * formula takes into account leap years. * * @param double latitude coordinate for calculating the length of the day * @param int the year for calculating the length of the day * @param int the month (0..January, 1..February, ...) for calculating the length of the day * @param int the day of month for calculating the length of the day * @return the day length in fractional hours * @see GregorianCalendar */ public static double dayLength(double latitude, int year, int month, int day) { // Define the cardinal dates GregorianCalendar today = new GregorianCalendar(year, month, day), prevWinter = new GregorianCalendar(year - 1, Calendar.DECEMBER, 21), nextSpting = new GregorianCalendar(year + 1, Calendar.MARCH, 21), springStart = new GregorianCalendar(year, Calendar.MARCH, 21), summerStart = new GregorianCalendar(year, Calendar.JUNE, 21), autumnStart = new GregorianCalendar(year, Calendar.SEPTEMBER, 23), winterStart = new GregorianCalendar(year, Calendar.DECEMBER, 21); int season; // number of days in the season of the date int cardinal; // number of days passed since the start of the season boolean isWinter = false; boolean isAutumn = false; if (today.after(prevWinter) && today.before(springStart)) { season = daysBetween(prevWinter, springStart); cardinal = daysBetween(today, prevWinter); isWinter = true; } else if (today.equals(springStart) || today.after(springStart) && today.before(summerStart)) { season = daysBetween(springStart, summerStart); cardinal = daysBetween(today, springStart); } else if (today.equals(summerStart) || today.after(summerStart) && today.before(autumnStart)) { season = daysBetween(summerStart, autumnStart); cardinal = daysBetween(today, summerStart); } else if (today.equals(autumnStart) || today.after(autumnStart) && today.before(winterStart)) { season = daysBetween(autumnStart, winterStart); cardinal = daysBetween(today, autumnStart); isAutumn = true; } else { season = daysBetween(winterStart, nextSpting); cardinal = daysBetween(today, winterStart); isWinter = true; } // Calculate the Sun's declination double declination = (cardinal * MAX_DECLINATION / season); // During a solstice, the maximum axial tilt to the Sun is 23°26'15" // During an equinox, the axial tilt to the Sun is 0° if (today.after(summerStart) && today.before(autumnStart) || today.before(springStart) || today.after(winterStart)) { declination = MAX_DECLINATION - declination; } // Summer and winter solstice if (declination == 0 && !(today.equals(springStart) || today.equals(autumnStart))) { declination = MAX_DECLINATION; } // Use a negative declination between the summer's and next winter solstice if (isWinter || isAutumn) { declination *= -1; } // Calculate the day lenght from latitude and declination double cos_t = -Math.tan(Math.toRadians(latitude)) * Math.tan(Math.toRadians(declination)); double t = Math.toDegrees(Math.acos(cos_t)); double dayLength = 2 * t * 24 / 360; return dayLength; } /* * Returns the number of days passed between two dates * * @param GregorianCalendar first date * @param GregorianCalendar second date * @return days passed * @see GregorianCalendar */ public static int daysBetween(GregorianCalendar d1, GregorianCalendar d2) { double millis = Math.abs(d1.getTimeInMillis() - d2.getTimeInMillis()); return (int) (millis / (1000 * 3600 * 24)); } /* * Returns 1 if the date is in daylight time or 0 if not * * @param int year of the date * @param int month of the date * @param int day of the month of the date * @return 1 for true, 0 for false * @see TimeZone */ public static int daylightSaving(int year, int month, int day) { return TimeZone.getDefault().inDaylightTime(getDate(year, month, day, 12, 0)) ? 1 : 0; } /* * Returns the Date object. This method is used as a replacement for the * deprecated constructor Date(year, month, day) * * @param int year of the date * @param int month of the date * @param int day of the month of the date * @return the Date object for the given parameters * @see Date */ public static Date getDate(int year, int month, int day) { return new Date(new GregorianCalendar(year, month, day).getTimeInMillis()); } /* * Returns the Date object. This method is used as a replacement for the * deprecated constructor Date(year, month, day, hour, minute) * * @param int year of the date * @param int month of the date * @param int day of the month of the date * @param int hour of day * @param int minute of hour * @return the Date object for the given parameters * @see Date */ public static Date getDate(int year, int month, int day, int hour, int min) { return new Date(new GregorianCalendar(year, month, day, hour, min).getTimeInMillis()); } /* * Returns the Date object. This method is used as a replacement for the * deprecated constructor Date(year, month, day, hour, minute, second) * * @param int year of the date * @param int month of the date * @param int day of the month of the date * @param int hour of day as double * @return the Date object for the given parameters * @see Date */ public static Date getDate(int year, int month, int day, double hour) { double min = (hour - Math.floor(hour)) * 60; double sec = (min - Math.floor(min)) * 60; return new Date(new GregorianCalendar(year, month, day, (int) hour, (int) min, (int) sec).getTimeInMillis()); } }
Nov 19, 2011
Android :: wrong image / data in ListView rows
Android's ListView reuses list items when they aren't need anymore. For this reason, you need to make sure all views that should change, will actually get changed. Your problem is that if you don't find a drawable for the current list item, you don't empty nor hide the ImageView. You should do thumb.setImageDrawable(null) in that case, or thumb.setVisibility(View.GONE).- From stackoverflow
Example code:
@Override public View getView(int pos, View v, ViewGroup parent) { TimetableViewHolder timetableHolder; if (v == null) { LayoutInflater vi = ((Activity)context).getLayoutInflater(); v = vi.inflate(R.layout.timetable_item, parent, false); timetableHolder = new TimetableViewHolder(); timetableHolder.rel = (TextView) v.findViewById(R.id.rel); timetableHolder.time = (TextView) v.findViewById(R.id.time); timetableHolder.icon = (ImageView) v.findViewById(R.id.icon); v.setTag(timetableHolder); } else { timetableHolder = (TimetableViewHolder) v.getTag(); } TimetableItem item = items.get(pos); if(item != null) { timetableHolder.rel.setText(item.rel); timetableHolder.time.setText(item.time); if(item.url.equals("ERROR")) { timetableHolder.icon.setImageResource(android.R.drawable.ic_menu_close_clear_cancel); } else if(item.url.equals("PRESTOP")) { timetableHolder.icon.setImageResource(android.R.drawable.ic_menu_directions); } else { // THIS IS IMPORTANT timetableHolder.icon.setImageResource(android.R.drawable.ic_dialog_info); } } return v; }
Android :: google maps (MapView) hacks, tricks, workarounds
MapView isn't very developer friendly now is it?
Here are some hacks I've had to work with:
1) When tapping on the overlay, the app crashes if you're trying to display the dialog.
Unable to add window -- token null is not for an application
Yes, this is due to context. Especially if you're trying to do this in a seperate thread or AsyncTask.
Turns out the context you need to pass to your dialog is mapView.getContext();
AlertDialog.Builder dialog = new AlertDialog.Builder(mapView.getContext());
2) Displaying only the overlays which are within map bounds
Oh yeah, several problems here. You've probably come across at least one of these:
You could also run something in a UI thread like this:
runOnUiThread(new Runnable() {
@Override
public void run() {
//do stuff here
}
});
Here are some hacks I've had to work with:
1) When tapping on the overlay, the app crashes if you're trying to display the dialog.
Unable to add window -- token null is not for an application
Yes, this is due to context. Especially if you're trying to do this in a seperate thread or AsyncTask.
Turns out the context you need to pass to your dialog is mapView.getContext();
AlertDialog.Builder dialog = new AlertDialog.Builder(mapView.getContext());
2) Displaying only the overlays which are within map bounds
Oh yeah, several problems here. You've probably come across at least one of these:
- Wrong map bounds in onCreate (0, 360000000),
Yeah, in onCreate those haven't been calculated yet. onStart doesn't help either. Try this:
Runnable waitForMapTimeTask = new Runnable() {
public void run() {
if(mapView.getLatitudeSpan()==0||mapView.getLongitudeSpan()== 360000000) {
mapView.postDelayed(this, 100);
} else {
redrawMarkers(); // draw here
}
}
};
mapView.postDelayed(waitForMapTimeTask, 100);
You create a new thread and wait until you get the right bounds. Recursively call it again.
- Map bounds ???
Don't worry, it's simple.
public Rect getMapBounds() {
return new Rect(
mapView.getMapCenter().getLongitudeE6() - mapView.getLongitudeSpan()/2,
mapView.getMapCenter().getLatitudeE6() - mapView.getLatitudeSpan()/2,
mapView.getMapCenter().getLongitudeE6() + mapView.getLongitudeSpan()/2,
mapView.getMapCenter().getLatitudeE6() + mapView.getLatitudeSpan()/2
);
}
...
if(!s.drawn && rect.contains(point.getLongitudeE6(), point.getLatitudeE6())) {
- Yeah, okay, but what about panning / zooming?
Well, there are no methods, like onPan or onZoom, but some people found their way around this problem. There is no perfect solution, you'll see.
Check these links out:
- http://stackoverflow.com/questions/2328650/how-can-i-detect-if-an-android-mapview-has-been-panned-or-zoomed
- http://bricolsoftconsulting.com/2011/10/31/extending-mapview-to-add-a-change-event/
- http://stackoverflow.com/questions/3567420/how-to-catch-that-map-panning-and-zoom-are-really-finished
- Zoom in on double tap?
Click here: http://dev.kafol.net/2011/11/how-hard-is-it-to-make-simple-zoom-in.html. - Overlays don't get drawn immediately!
Try this:
mapView.postInvalidate();
or this:
mapView.invalidate();
But keep in mind, that invalidate() needs to be called from an UI! If you're trying to get it working from a thread, use postInvalidate()! - MapView java.util.ConcurrentModificationException when adding new overlays
Not sure if I solved this one, but it seems to work now. I read somewhere that this could happen if you add overlays in a non UI thread. I moved the
Nope, sorry, this one was my bad. I was doing some crazy async sorting and all hell broke loose.
itemizedOverlay.populateNow();
mapOverlays.add(itemizedOverlay);
mapView.postInvalidate();
From doInBackground to onPostExecute in AsyncTask.
You could also run something in a UI thread like this:
runOnUiThread(new Runnable() {
@Override
public void run() {
//do stuff here
}
});
Nov 18, 2011
Android :: google maps on double tap zoom in
How hard is it to make a simple zoom in call on double tap in MapView in Android?
Not very.
How hard is it to get the information on how to do it?
Very.
Here's what you probably didn't know:
You need to extend the MapView and use this extended class in the Android XML layout file.
In the extended class you instantiate the gesture detector and set on double tap listener.
In the Map Activity you implement OnGestureListener and OnDoubleTapListener.
Example:
Not very.
How hard is it to get the information on how to do it?
Very.
Here's what you probably didn't know:
You need to extend the MapView and use this extended class in the Android XML layout file.
In the extended class you instantiate the gesture detector and set on double tap listener.
In the Map Activity you implement OnGestureListener and OnDoubleTapListener.
Example:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center_horizontal" > <net.kafol.vlaki.ExtMapView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/mapview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" android:enabled="true" android:apiKey="" /> </RelativeLayout>
package net.kafol.vlaki; import android.content.Context; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.GestureDetector.OnDoubleTapListener; import android.view.MotionEvent; import android.view.GestureDetector.OnGestureListener; import com.google.android.maps.MapView; public class ExtMapView extends MapView { private Context context; private GestureDetector gestureDetector; public ExtMapView(Context c, AttributeSet attrs) { super(c, attrs); context = c; gestureDetector = new GestureDetector((OnGestureListener) context); gestureDetector.setOnDoubleTapListener((OnDoubleTapListener) context); } public boolean onTouchEvent(MotionEvent ev) { if (this.gestureDetector.onTouchEvent(ev)) return true; else return super.onTouchEvent(ev); } }
public class Map extends MapActivity implements OnGestureListener, OnDoubleTapListener { ... @Override public boolean onDoubleTap(MotionEvent e) { int x = (int)e.getX(), y = (int)e.getY();; Projection p = mapView.getProjection(); mapView.getController().animateTo(p.fromPixels(x, y)); // zoom in to a point you tapped mapView.getController().zoomIn(); return true; }
Android : Checkbox ListView - (un) check all
This recycling of views in android is pretty insane. Pain to work with.
So the problem is how to check all check boxes in a list view, if a list view only contains the visible items.
Iterating through the adapter or array of holders was pretty unreliable, some checkboxes weren't affected.
What I did was actually add an attribute to the data object and iterate through this object array (the same way it get's added in the adapter)-
Here are some functions:
Full code here: http://pastebin.com/8NMbHqRV
The code still has some bugs related to SharedPreferences and SharedPreferences.Editor, but at least it checks and unchecks all checkboxes.
So the problem is how to check all check boxes in a list view, if a list view only contains the visible items.
Iterating through the adapter or array of holders was pretty unreliable, some checkboxes weren't affected.
What I did was actually add an attribute to the data object and iterate through this object array (the same way it get's added in the adapter)-
Here are some functions:
public void toggleCheck(Boolean val) { for(Station s : stations.list) { s.checked = val; editor.putBoolean("PF_"+s.getID(), val); } for(int i=0 ; i < lv.getChildCount() ; i++) { CheckBox cb = (CheckBox) lv.getChildAt(i).findViewById(R.id.cb); cb.setChecked(val); } editor.apply(); } private class StationCBViewHolder { public CheckBox cb; public Station s; } private class StationListAdapter extends ArrayAdapter{ private ArrayList items; private Context context; public StationListAdapter(Context context, int tvResId, ArrayList items) { super(context, tvResId, items); this.items = items; this.context = context; } @Override public View getView(int pos, View v, ViewGroup parent) { final StationCBViewHolder holder; final Station item = items.get(pos); if (v == null) { LayoutInflater vi = ((Activity)context).getLayoutInflater(); v = vi.inflate(R.layout.stationcheckboxitem, parent, false); holder = new StationCBViewHolder(); holder.cb = (CheckBox) v.findViewById(R.id.cb); holder.s = item; item.checked = prefs.getBoolean("PF_"+item.getID(),true); //holder.cb.setTag(holder); holder.cb.setTag(item); holder.cb.setChecked(item.checked); holder.cb.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton v, boolean isChecked) { Station s = (Station) v.getTag(); editor.putBoolean("PF_"+s.getID(), isChecked); editor.apply(); } }); v.setTag(holder); } else { holder = (StationCBViewHolder) v.getTag(); } holder.cb.setText(item.toString()); holder.cb.setChecked(item.checked); return v; } }
Full code here: http://pastebin.com/8NMbHqRV
The code still has some bugs related to SharedPreferences and SharedPreferences.Editor, but at least it checks and unchecks all checkboxes.
Apr 14, 2009
Java:: Coin Change Problem - dynamic programming - memoization - recursion
Problem:
We have a series of coins, eg. 1, 3, 5 and we're trying to find the least possible number coins to sum up to a value, eg. 11
The smallest possible solution is 3 coins (5+5+1, 5+3+3).
Solution: The Greedy algorithm only works in special cases, but we're trying to find the ultimate, smallest and fast solution.
The goal is to check all possibilities, which can take a lot of time, if we don't use memoization. The solution below is a recursive function with two arguments:
Solution: The Greedy algorithm only works in special cases, but we're trying to find the ultimate, smallest and fast solution.
The goal is to check all possibilities, which can take a lot of time, if we don't use memoization. The solution below is a recursive function with two arguments:
- int[] k - table of coins (1, 3, 5) ordered ascending
- int val - the value we wish to solve
public static Hashtable<Integer, Integer> solved = new Hashtable<Integer, Integer>(); public static int kovanci(int[] k, int val) { // we've reached the end of recursion - a leaf // if the value is less than zero it means that the current combination is not solvable // if the value is zero, it means it is solvable if (val <= 0) return val; // for as many coins try to decrease the value for the coin value // and try to solve the smaller problem int min = -1; //default: if it's not solvable for (int i = k.length - 1; i >= 0; i--) { // if the coin k[i] exists in the solution, it means the solution is // solutions(value - coin_value) + 1 // eg. we have coins: 1, 3, 5 and the value is 11 // if the coin 5 exists in the solution, try to solve the problem for value 11-5 = 6 // the solution is smaller_solution + 1 int newVal = val - k[i]; int r; // dynamic programming - memoization // if we already have the minimum for the new value, fetch it (with time complexity O(1)), // so that we don't recursively re-solve the problem and waste time if (solved.get(newVal) != null) { //solution = smaller_sollution + 1 r = solved.get(newVal) + 1; } else { //try to solve the smaller problem r = kovanci(k, newVal); //if the solution is valid, the new solution is smaller_solution + 1 if (r >= 0) r++; //else, keep the negative value - it means that it's not valid //eg: coins 3, 5, value 11 is not solvable, the solution is -1 } // from all of the solutions, get the minimum value // and skip invalid solutions ( less than zero ) if ((r > 0) && (min == -1 || r < min)) { min = r; } } // dynamic programming - memoization // once we do get the smallest possible solution, save it for later use // it saves A LOT of time and useless work, that's already been done solved.put(val, min); return min; }
Sep 19, 2008
Java :: Working with matrixes
I had an assignment in college to build a Java program that would calculate matrix expressions. Examples for this were:
Expression: A = [ [ 1 2 ] [ 3 4 ] ] saves matrix 1 2 3 4 to variable A. Expression: B = A * A calculates the matrix A*A and saves the result in variable B Expression: B - [ [ 9 8 ] [ 7 6 ] ] calculates matrix B - matrix 9 8 7 6 and prints the resultHere's the class:
import java.util.*; import java.io.*; public class Matrike { //v hashmap se bodo shranjevale spremenljivke in njihove vrednosti static Map<String,String> vars = new HashMap<String,String>(); static boolean debug=false; //param debug za podrobnejsi izpis static boolean gotSyntaxError; //ne izpisi rezultata, ce je napaka /**************************************************************************************** M A I N (done) ****************************************************************************************/ public static void main(String[] args) { String niz = null; boolean ok=false; if(args.length>0)debug=args[0].equals("debug"); //debug=true/false BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); do { System.out.printf(": "); ok = false; try { niz = br.readLine(); ok = true; } catch(IOException ioe) { System.out.printf("! Input error\n"); ok = false; } if(ok && niz.length() > 0) { analiza(niz); //ce je vse ok in ni prazn string, zacni procesirat } } while (!niz.equals("exit")); //exit = komanda za izhod System.out.println("* Bye"); } /**************************************************************************************** P R O C E S I R A N J E K O M A N D E (done) ****************************************************************************************/ //analiza inputa - shrani spremenljivke, poslje izraz v funkcijo za racunanje public static void analiza(String niz) { StringBuffer varBuffer = new StringBuffer(); StringBuffer valBuffer = new StringBuffer(); String val=null; //desna stran enacaja String var=null; //spremenljivka gotSyntaxError=false; ///////////////////////////////////////////////////////////////////////////////////////// //[komande] izpisi vse spremenljivke if(niz.equals("vars")||niz.equals("var")||niz.equals("variables")){ printVars(); return; } if(niz.equals("clean")||niz.equals("clear")){ vars.clear(); System.out.println("* Cleaning up variables"); return; } ///////////////////////////////////////////////////////////////////////////////////////// //iskanje negativnih stevil, da se ne bo mesalo z operatorjem minus boolean foundOklepaj=false; StringBuffer nizReplace = new StringBuffer(); for(int i=0;i<niz.length();i++) { if(niz.charAt(i)=='[')foundOklepaj=true; //ce je negativna cifra znotraj matrike if(niz.charAt(i)==']')foundOklepaj=false; if((niz.charAt(i)=='-')&&foundOklepaj) { nizReplace.append('_'); //bo znak za minus zamenjalo s _ } else { nizReplace.append(niz.charAt(i)); } } niz=nizReplace.toString(); ///////////////////////////////////////////////////////////////////////////////////////// //shrani izraz za racunanje, ce je najden enacaj je ta za enacajem int eqLoc=0; for(int i=0;i<niz.length();i++)if(niz.charAt(i)=='=')eqLoc=i+1; //+1, enacaja ne shrani for(int i=eqLoc;i<niz.length();i++)valBuffer.append(niz.charAt(i)); val=valBuffer.toString(); ///////////////////////////////////////////////////////////////////////////////////////// //ce so v izrazu operatorji, je treba izraz poracunat in popravit spremenjivko val int nOperations=0; for(int i=0;i<niz.length();i++) if(niz.charAt(i)=='+'||niz.charAt(i)=='*'||niz.charAt(i)=='-') nOperations++; if(nOperations>0) { //ali je treba racunat? ///////POSLJI V KALKULATOR val = calcMatrix(val,nOperations); //treba je racunat, calcMatrix bo vrnila nov rezultat ///////---------- if((val != null) && (!gotSyntaxError)) { //izpise pa ga tule, ne calcMatrix, pa izpisi ce ni kasn error if(isScalar(val)) { //ce je matrika enodimenzionalna, je skalar - pretvori StringBuffer toScalar = new StringBuffer(); for(int i=0;i<val.length();i++) if( (val.charAt(i)!=' ') && (val.charAt(i)!='[') && (val.charAt(i)!=']') ) toScalar.append(val.charAt(i)); val=toScalar.toString(); } //TUKAJ JE GLAVNI IZPIS REZULTATA !!! System.out.printf("> %s\n",val); //---- } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //shrani spremenljivke for(int i=0;i<niz.length();i++) { if(niz.charAt(i)=='=') { for(int j=0;j<i;j++)varBuffer.append(niz.charAt(j)); var=varBuffer.toString(); vars.put(var.replaceAll(" ",""),val); } } } /**************************************************************************************** R A C U N A N J E I Z R A Z A M A T R I K (done) ****************************************************************************************/ public static String calcMatrix(String matrix,int nOperations) { /* kalkulator deluje na isti princip kot racuni.c - naredi dve tabeli: - tabela operandov - tabela operatorjev Nato se sprehajamo po tabeli operatorjev po prioriteti in racunamo po dva elementa hkrati. Rezultat napisemo v indeks prvega elementa, drugi element zbrisemo in zmanjsamo tabelo za 1 in pomaknemo v levo. Tabela je tridimenzionalna - prvi indeks je indeks operandov, druga dva indeksa sta 2D tabela matrike */ int[][][] izraz = new int[nOperations+1][][]; char[] operatorji = new char[nOperations]; String result=null; int a=0; //shrani operatorje for(int i=0;i<matrix.length();i++) if(matrix.charAt(i)=='+'||matrix.charAt(i)=='*'||matrix.charAt(i)=='-') { operatorji[a]=matrix.charAt(i); a++; } //shrani operande (matrike) v tabelo a=0; String tmp=null; //StringTokenizer st = new StringTokenizer(matrix,"+-*"); //razbij po operatorjih String tokens[] = matrix.split("\\+|\\-|\\*"); //while (st.hasMoreTokens()) { for(int i=0;i<tokens.length;i++) { //tmp=st.nextToken(); tmp=tokens[i]; //poglej ce je tmp spremenljivka in jo zamenjaj z matriko tmp=varToMatrix(tmp); //poglej ce je tmp skalar in ga zamenjaj v 1x1 matriko ;-) if(isNumber(tmp)) { tmp=tmp.replaceAll(" ",""); StringBuffer skalar = new StringBuffer(); skalar.append("[["); try { skalar.append(Integer.parseInt(tmp)); } catch(NumberFormatException e) { System.out.printf("! Syntax error: scalar is not a number\n"); gotSyntaxError=true; return null; } skalar.append("]]"); tmp=skalar.toString(); } /*Y**************************************************************************************/ //poracunaj dimenzije tabele int y=getMatrixDimensionY(tmp); /*X*************************************************************************************/ int x=getMatrixDimensionX(tmp); /***************************************************************************************/ int counter=0; //to je sam za cekiranje try { //StringTokenizer stCount = new StringTokenizer(tmp," ]["); String numberTokens[]=tmp.split(" |\\[|\\]"); //while(stCount.hasMoreTokens()){ for(int w=0;w<numberTokens.length;w++) { if((numberTokens[w]!=null) && (!numberTokens[w].equals(""))) counter++; //stCount.nextToken(); } } catch(NullPointerException e) { System.out.println("! Syntax error: empty variable, clean up with 'vars'"); gotSyntaxError=true; return null; } if(debug)System.out.printf("calcMatrix? x=%d,y=%d\n",x,y); /***************************************************************************************/ //ce je x ali y negativen, ali nista kolicnika je struktura matrike nepravilna if(x==0||y==0) { System.out.printf("! Syntax error: no numbers in the matrix\n"); gotSyntaxError=true; return null; } if(x<0||y<0||counter%y!=0){ System.out.printf("! Syntax error: invalid matrix dimension\n"); gotSyntaxError=true; return null; } if((x>1)&&(counter%x!=0)) { System.out.printf("! Syntax error: missing number in the matrix\n"); gotSyntaxError=true; return null; } //pretvori string v tabelo integerjev izraz[a] = new int[x][y]; izraz[a]=matrixToTable(tmp,x,y); a++; } //////////////////////////////////////////////////////////////////////////////////////////////////// //TABELA JE SHRANJENA, zacni racunat int lenOperatorji=operatorji.length; int lenIzraz=izraz.length; String rezultat=null; /***** ISCI OPERATORJE IN POPRAVLJAJ TABELO ! *****/ for(int op=1;op<4;op++) { char f; switch(op) { default: case 1:f='*'; break; case 2:f='-'; break; case 3:f='+'; break; } int stejop=0; for(int i=0;i<lenOperatorji;i++) if(operatorji[i]==f)stejop++; while(stejop>0) { for(int i=0;i<lenOperatorji;i++) { //break => if(operatorji[i]==f) { if((isScalar(tableToMatrix(izraz[i])) || isScalar(tableToMatrix(izraz[i+1]))) && (f=='*')) { //ali je operacija s skalarjem //pozor: ta funkcija je definirana samo za mnozenje s skalarjem (ali ce sta oba skalarja), v drugem primeru se bo obravnavalo kot operacijo med dvema matrikama rezultat=doMatrixMath(izraz[i],izraz[i+1],'s'); int x=getMatrixDimensionX(rezultat); int y=getMatrixDimensionY(rezultat); if(x>0||y>0) izraz[i]=matrixToTable(rezultat,x,y); if(debug)System.out.printf("calcMatrix/ (Scalar) Set %s\n",rezultat); } else { //drugace... rezultat=doMatrixMath(izraz[i],izraz[i+1],f); if(debug)System.out.printf("calcMatrix/ Got %c\n",f); int x=getMatrixDimensionX(rezultat); int y=getMatrixDimensionY(rezultat); if(x>0||y>0) izraz[i]=matrixToTable(rezultat,x,y); if(debug)System.out.printf("calcMatrix/ Set %s\n",rezultat); } ////////////Popravi tabelo for(int j=i;j<lenOperatorji;j++) if(j+1<lenOperatorji)operatorji[j]=operatorji[j+1]; //kle! lenOperatorji--; //se operande for(int j=i+1;j<lenIzraz;j++) if(j+1<lenIzraz)izraz[j]=izraz[j+1]; lenIzraz--; ////////ok stejop--; break; // <= break } } } } result=tableToMatrix(izraz[0]); if(debug)System.out.printf("calcMatrix$ %s\n",result); return result; } /**************************************************************************************** METODA ZA DIMENZIJE MATRIKE ZA 2D TABELO (done) ****************************************************************************************/ public static int getMatrixDimensionX(String matrix) { int f=-1,g=-1,x=-1; if(matrix!=null) { for(int i=0;i<matrix.length();i++)if(matrix.charAt(i)=='[')f++; //x dimenzija tabele = N("[")-1 for(int i=0;i<matrix.length();i++)if(matrix.charAt(i)==']')g++; if(g==f)x=g; } return x; } public static int getMatrixDimensionY(String matrix) { int y=-1; int counter=0; if(matrix==null||matrix.equals("")||matrix.equals(null)) { if(debug)System.out.println("! Syntax error: null parameter (getMatrixDimension)"); gotSyntaxError=true; return -1; } String tmp=matrix; if(tmp==null||tmp.equals("")||tmp.equals(null)) { if(debug)System.out.println("! Syntax error: null parameter (getMatrixDimensionY)"); gotSyntaxError=true; return -1; } if(debug)System.out.printf("getMatrixDimensionY# %s\n",tmp); if(tmp!=null) { if(debug)System.out.printf("getMatrixDimensionY# Tokenizing ...\n"); //StringTokenizer stCount = new StringTokenizer(tmp," ]["); String numberTokens[]=tmp.split(" |\\[|\\]"); //while(stCount.hasMoreTokens()){ for(int w=0;w<numberTokens.length;w++) { if((numberTokens[w]!=null) && (!numberTokens[w].equals(""))) counter++; //stCount.nextToken(); } } y=counter/getMatrixDimensionX(tmp); //y dimenzija tabele = N(stevilk)/x return y; } /**************************************************************************************** METODA ZA RACUNANJE DVEH MATRIK ****************************************************************************************/ public static String doMatrixMath(int[][] p1,int[][] p2,char f) { String result=null; if(p1==null||p2==null) { System.out.println("! Syntax error: parameter missing, nothing to do"); gotSyntaxError=true; return null; } int x1=p1.length; int x2=p2.length; int y1=p1[0].length; int y2=p2[0].length; switch(f) { // MNOZENJE S SKALARJEM case 's': int scalar=0; result=tableToMatrix(p1); if(isScalar(tableToMatrix(p1))) { scalar=p1[0][0]; //doloci skalar for(int i=0;i<p2.length;i++) for(int j=0;j<p2[i].length;j++) p2[i][j]*=scalar; //in pomnozi s drugim parametrom result=tableToMatrix(p2); } else { //ravno obratno scalar=p2[0][0]; for(int i=0;i<p1.length;i++) for(int j=0;j<p1[i].length;j++) p1[i][j]*=scalar; result=tableToMatrix(p1); } break; // PLUS in MINUS case '+': case '-': //vsota in razlika matrik je definirana samo za matrike enakih dimenzij //vir: http://en.wikipedia.org/wiki/Matrix_%28mathematics%29#Sum if(x1!=x2||y1!=y2) { System.out.println("! Syntax error: matrices do not have the same dimension"); gotSyntaxError=true; return null; } for(int x=0;x<x1;x++) { for(int y=0;y<y1;y++) { switch(f) { default: case '+': p1[x][y]+=p2[x][y]; break; case '-': p1[x][y]-=p2[x][y]; break; } } } result=tableToMatrix(p1); break; //KRAT case '*': default: //mnozenje matrik je definirano za matrike, katere stevilo stolpcev ene matrike je enako stevilu vrstic druge //vir: http://en.wikipedia.org/wiki/Matrix_multiplication#Ordinary_matrix_product int dx=0; //x dimenzija matrike produkta int dy=0; //y dimenzija matrike produkta int max=0; //sirsa dimenzija if(x1>=x2) { //p1 je daljsi v stolpcih ali pa sta p1 in p2 kvadrat dx=x2; dy=y1; max=x1; } else { //p2 je daljsi v stolpcih dx=x1; dy=y2; max=x2; } if(debug)System.out.printf("doMatrixMath: %d %d %d %d\n",x1,y2,x2,y1); if((x1!=x2||y1!=y2)&&(x1!=y2||x2!=y1)) { System.out.println("! Syntax error: matrices do not have the opposite or same dimension"); gotSyntaxError=true; return null; } if(debug)System.out.printf("doMatrixMath-Multiplication:\ndx = %d\ndy = %d\nmax = %d\n",dx,dy,max); int[][] p = new int[dx][dy]; //dimenzije matrike produkta for(int xp=0;xp<dx;xp++) { for(int yp=0;yp<dy;yp++) { p[xp][yp]=0; for(int x=0;x<max;x++) { if(debug)System.out.printf("p[%d][%d] += p1[%d][%d](%d) * p2[%d][%d](%d)\n", xp,yp,xp,x,p1[xp][x],x,yp,p2[x][yp]); if(x1>=x2) p[xp][yp]+=p2[xp][x]*p1[x][yp]; else p[xp][yp]+=p1[xp][x]*p2[x][yp]; } } } result=tableToMatrix(p); break; } return result; } /**************************************************************************************** PRETVORBA MATRIKE IZ STRING V 2D TABELO INTEGER (done) ****************************************************************************************/ public static int[][] matrixToTable(String matrix,int x,int y) { int[][] result = new int[x][y]; int[] nums = new int[x*y]; //shrani stevilke v 1D tabelo int counter=0; //StringTokenizer st = new StringTokenizer(matrix," ]["); String tokens[]=matrix.split(" |\\[|\\]"); //while (st.hasMoreTokens()) { for(int w=0;w<tokens.length;w++) { try { //String tmp=st.nextToken(); //////// String tmp = tokens[w]; if((tokens[w]==null) || (tokens[w].equals(""))) continue; /////// tmp=tmp.replaceAll("_","-"); try { nums[counter]=Integer.parseInt(tmp); } catch(ArrayIndexOutOfBoundsException e) { System.out.printf("! Syntax error: unknown matrix array error\n"); gotSyntaxError=true; return null; } if(debug)System.out.printf("matrixToTable+ %d\n",nums[counter]); counter++; } catch(NumberFormatException nfe) { System.out.printf("! Syntax error: element in matrix is not a number\n"); gotSyntaxError=true; //not a number return null; } } //zapis v 2D tabelo counter=0; for(int i=0;i<x;i++) { for(int j=0;j<y;j++) { result[i][j]=nums[counter]; if(debug)System.out.printf("matrixToTable- {%d,%d} %d\n",i,j,nums[counter]); counter++; } } //vrni rezultat if(debug)System.out.printf("matrixToTable@ %s\n",tableToMatrix(result)); return result; } /**************************************************************************************** PRETVORBA 2D TABELE V STRING MATRIKE ([[1 2][3 4]]) (done) ****************************************************************************************/ public static String tableToMatrix(int[][] tab) { StringBuffer matrix = new StringBuffer(); String result=null; if(tab==null) { if(debug)System.out.println("! Syntax error: null parameter (tableToMatrix)"); gotSyntaxError=true; return null; } matrix.append("[ "); for(int x=0;x<tab.length;x++) { matrix.append("[ "); for(int y=0;y<tab[x].length;y++) { matrix.append(tab[x][y]+" "); } matrix.append("] "); } matrix.append("]"); //Lep izpis, primer: [ [ 2 3 ] [ 4 5 ] ] result=matrix.toString(); if(debug)System.out.printf("tableToMatrix: %s\n",result); return result; } /**************************************************************************************** IZPIS SPREMENLJIVK(done) ****************************************************************************************/ public static void printVars() { Set set = vars.entrySet(); List<String> clean = new ArrayList<String>(); Iterator i = set.iterator(); String var,val; System.out.println("* Listing variables"); while(i.hasNext()) { //sprehodi se po mapSetu Map.Entry entry = (Map.Entry) i.next(); var = (String) entry.getKey(); val = (String) entry.getValue(); try { val = val.replaceAll("_","-"); //zajebi cel svet in izpisi pravilne minuse System.out.printf("# %s = %s\n",var,val); } catch(NullPointerException e) { System.out.printf("! Empty variable '%s' removed\n",var); clean.add(var); /* shrani seznam spremenljivk za izbris */ } } /* pocisti prazne sprmenljivke */ Iterator j=clean.iterator(); while(j.hasNext())vars.remove(j.next()); /* konec */ System.out.println("* End of list"); } /**************************************************************************************** VRACANJE VREDNOSTI SPREMENLJIVKE (done) ****************************************************************************************/ public static String varToMatrix(String tmp) { String result = tmp; //ce spremenljivka ne obstaja, vrni isti string StringBuffer buffer = new StringBuffer(); for(int i=0;i<tmp.length();i++) if(tmp.charAt(i)!=' ') buffer.append(tmp.charAt(i)); String chkEq = buffer.toString(); //v chkEq se nahaja spremenljivka if(debug)System.out.printf("varToMatrix# chkEq(%s)\n",chkEq); Set set = vars.entrySet(); Iterator i = set.iterator(); String var,val; while(i.hasNext()) { Map.Entry entry = (Map.Entry) i.next(); var = (String) entry.getKey(); val = (String) entry.getValue(); if(var.equals(chkEq)) result=val; } if(debug)System.out.printf("varToMatrix# %s\n",result); return result; } /**************************************************************************************** METODA ZA PREVERJANJE CE JE PARAMETER STEVILKA (done) ****************************************************************************************/ public static boolean isNumber(String tmp) { boolean result = false; if(tmp!=null)tmp=tmp.replaceAll(" ",""); else return false; try { Integer.parseInt(tmp); result = true; } catch(NumberFormatException nfe) {} return result; } /**************************************************************************************** METODA ZA PREVERJANJE CE JE MATRIKA 1d - SKALAR (done) ****************************************************************************************/ public static boolean isScalar(String tmp) { boolean result=false; if((getMatrixDimensionX(tmp)==1) && (getMatrixDimensionY(tmp)==1)) result=true; return result; } }
Subscribe to:
Posts (Atom)