Dec 13, 2012

Android developer settings (debug mode) in 4.2 Jelly Bean

With the recent update of the Android OS Jelly Bean to 4.2, the developer settings were nowhere to be found.

It turns out that this stupid move was deliberate and the developer settings screen is now hidden,
To get it back you need to do a kind of easter-egg hack - you go to "Settings" > "About phone" and literally tap the "Build number" 7 (seven!!) times, to get the developer settings back.


Way to go Google,
I guess you think all your users are stupid.

Thanks for that.


BTW:
Try tapping the other things on the list. Don't faint from the excitement.

Oct 6, 2012

Android Facebook SDK login error #1118578

The error is caused because the activity has set the launch mode to singleInstance.

From StackOverflow where I posted the question:


Everything was working fine, until I wanted to check what happens if the user clicks the Login with Facebook button with no internet connection available.
A toast showed up saying:
Login failed. Please contact the maker of this app and ask them to report issue #1118578 to Facebook.
In the logcat I have:
D/Facebook-authorize(2824): Login canceled by user.
I tried to get rid of this toast and display my own error message in the onCancel() method - but I can't find a way to disable that toast. When I enabled WiFi again, single sign on didn't work anymore!
What could be the cause of this?
    private void fbLogin() {
    facebook.authorize(this, new String[] { "email" }, new DialogListener() {
        @Override
        public void onComplete(Bundle values) {
            app.save("fb_token", facebook.getAccessToken());
            app.save("fb_expire", facebook.getAccessExpires());
            mAsyncRunner.request("me", new meRequestListener());
        }
        @Override
        public void onFacebookError(FacebookError error) {}
        @Override
        public void onError(DialogError e) {}
        @Override
        public void onCancel() {}
    });
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    facebook.authorizeCallback(requestCode, resultCode, data);
}
EDIT:
To answer my own question, removing android:launchMode="singleInstance" From the manifest in the  resolved the #1118578 issue.
However, I do need the android:launchMode="singleInstance" for the twitter OAuth login, as the browser passes the data back to the activity via new Intent. If I do not provideandroid:launchMode="singleInstance" in the manifest, a new activity is launched and it does not recieve the OAuth verifier.
Is there any way around this, to use Facebook and Twitter login in the same activity? The only solution I think of is to use a dummy activity for Twitter4j with singleInstance.


See original thread here:
http://stackoverflow.com/questions/12759261/android-facebook-sdk-login-error-1118578

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.


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());
 }
}

Aug 9, 2012

PHP :: session expires after inactivity

If you're getting frustrated why the session expires after 30 minutes, 1 hour of inactivity, you've probably already looked into the problem.

There are a few reasons why the session expires, so let's look at how session actually works.

On the server-side, PHP (usually / by default) stores session variables into files, usually in the /tmp folder.
The script sends a session cookie to the client, which expires after the session closes. At each request, the client sends the PHP session ID cookie back to the server, which uses this ID to access the session variables in the filesystem.
Now, so far we can understand that when the user closes the browser, the session cookie is removed and there is no way of accessing the session variables. The client has closed the session.

A setting in the php.ini file defines how long the session cookie should remain valid.


session.cookie_lifetime = 0

Setting the session.cookie_lifetime to 0 means that the session cookie is valid until the browser is closed. Setting it to something larger than 0 means that it remains valid for so many number of seconds.


Sometimes, however, the user is logged out of the session even though the browser has not been closed and the session cookie still exists. In this case, the server closed the session, meaning it deleted the files containing the session variables. This process is called garbage collection. Garbage collector in PHP deletes old session files that have a timestamp of last access time longer than the defined limit. The setting in php.ini for it is defined in seconds:

session.gc_maxlifetime = 1440

Session files older than 24 minutes [of inactivity] will be deleted. Changing the value to something like 1 week or a month can cause the session to be seemingly permanent. Some browsers have the option to never delete or reset session cookies even after browser restart (in chrome: continue where I left off), so you can achieve permanent sessions without implementing your own system to automatically restart the session via cookies or other types of local storage.

Apr 18, 2012

Windows 7 SSD Tips

The list may be updated.


  • You probably already know this:
    Install large programs on the HDD instead of the SSD drive.
  • Disabling hibernation saves you X GBs on the SSD drive, where X is the size of your RAM.
    Run cmd as administrator.
    Type in:  powercfg -h off
  • Move Documents, Movies, Pictures, Music folder on the HDD drive.
    Moving these directories is easy. Just right-click on them, click Properties, click Location and click Move.
  • Move AppData folder - this is the folder where your installed programs store temporary and/or your local data which is used by those programs. It can grow really large in size.
    There is no simple procedure to do this, so this option is not really preferred.
  • Move the whole Users folder.
    LifeHacker has an article about it. Again, not a really simple solution.

Apr 17, 2012

Windows 7 File permission problem after reinstallation


Run command line as administrator

For Folders or Directories (will perform action recursively):

takeown /f directory_name /r /d y
icacls directory_name /grant administrators:F /t


Replace file_name or directory_name with actual file name or folder name, with path when applicable. The first command will take ownership of the file or folder specified, and the second command will grant full control permissions to administrators user group. Note that when using command for folders, to command will run recursively. To prevent the task been perform recursively, remove the “/r” and “/t” switch.


Source: http://forum.thewindowsclub.com/windows-tips-tutorials-articles/18379-how-take-ownership-full-control-permissions-files-folders-windows.html

Apr 14, 2012

Google Maps API Key for Android (Eclipse, Windows)

There are two main types of keystores in Eclipse - one is for debugging (a keystore with no password) and the other one is when you create a new one yourself, with a password.

To make Google Maps work on your Android app, you need to enter a MD5 fingerprint of your keystore in Google Maps API signup: http://code.google.com/android/maps-api-signup.html

And here's how you get your keystore's MD5 fingerprint in Windows.

  1. You probably already have JDK installed. Find out your Java bin directory. Mine is:
    C:\Program Files\Java\jdk1.6.0_24\bin
  2. Enter this directory path in your PATH Environment variable (see picture).
  3. Start "cmd" and navigate to your
    C:\Users\<yourusername>\.android
    directory
  4. Type this command:
    keytool -list -keystore debug.keystore
  5. The password is empty, just hit enter
  6. You're done. Copy the MD5 fingerprint in that url, you get an API key, which you use in your Android MapView Layout file.
    android:apiKey="your api key here"

Mar 2, 2012

Repcached does not compile

If you want the tutorial on installing repcached, click here.

For the record, I am using:

Ubuntu 11.10 

Linux 3.0.0-12-server #20-Ubuntu SMP Fri Oct 7 16:36:30 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux
gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3)
GNU Make 3.81


If you're getting this error when doing make for repcached,



memcached.c: In function âadd_iovâ:
memcached.c:696:30: error: âIOV_MAXâ undeclared (first use in this function)
memcached.c:696:30: note: each undeclared identifier is reported only once for each function it appears in
memcached.c: In function âprocess_statâ:
memcached.c:1127:9: warning: format â%dâ expects argument of type âintâ, but argument 3 has type âlong unsigned intâ [-Wformat]
memcached.c:1134:9: warning: format â%lluâ expects argument of type âlong long unsigned intâ, but argument 3 has type âuint64_tâ [-Wformat]
memcached.c:1138:9: warning: format â%lluâ expects argument of type âlong long unsigned intâ, but argument 3 has type âuint64_tâ [-Wformat]
memcached.c:1139:9: warning: format â%lluâ expects argument of type âlong long unsigned intâ, but argument 3 has type âuint64_tâ [-Wformat]
memcached.c:1140:9: warning: format â%lluâ expects argument of type âlong long unsigned intâ, but argument 3 has type âuint64_tâ [-Wformat]
memcached.c:1141:9: warning: format â%lluâ expects argument of type âlong long unsigned intâ, but argument 3 has type âuint64_tâ [-Wformat]
memcached.c:1142:9: warning: format â%lluâ expects argument of type âlong long unsigned intâ, but argument 3 has type âuint64_tâ [-Wformat]
memcached.c:1143:9: warning: format â%lluâ expects argument of type âlong long unsigned intâ, but argument 3 has type âuint64_tâ [-Wformat]
memcached.c:1144:9: warning: format â%lluâ expects argument of type âlong long unsigned intâ, but argument 3 has type âuint64_tâ [-Wformat]
memcached.c:1145:9: warning: format â%lluâ expects argument of type âlong long unsigned intâ, but argument 3 has type âuint64_tâ [-Wformat]
memcached.c:1146:9: warning: format â%lluâ expects argument of type âlong long unsigned intâ, but argument 3 has type âsize_tâ [-Wformat]
memcached.c:1149:9: warning: format â%lluâ expects argument of type âlong long unsigned intâ, but argument 3 has type âuint64_tâ [-Wformat]
memcached.c: In function âprocess_get_commandâ:
memcached.c:1331:19: warning: format â%lluâ expects argument of type âlong long unsigned intâ, but argument 3 has type âuint64_tâ [-Wformat]
memcached.c: In function âdo_add_deltaâ:
memcached.c:1573:5: warning: format â%lluâ expects argument of type âlong long unsigned intâ, but argument 3 has type âuint64_tâ [-Wformat]
make[2]: *** [memcached-memcached.o] Error 1
make[2]: Leaving directory `/root/memcached-1.2.8-repcached-2.2'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/root/memcached-1.2.8-repcached-2.2'
make: *** [all] Error 2


Related discussion here.

Compiler says that IOV_MAX is not defined. I'm not really sure what this is, but it compiled fine on Ubuntu 10.04. I guess that const is not used anymore.

In memcached.c code, we can see that IOV_MAX is defined if the OS is FreeBSD or iOS, so I decided to just define it anyway.

Here is my diff of the code that made it compile, in case you need it.

57,59c57
< #if defined(__FreeBSD__) || defined(__APPLE__)
< # define IOV_MAX 1024
< #endif
---
> #define IOV_MAX 1024

Feb 28, 2012

PHP :: Advice on using count()

I may be a little late realising this, but a few dozen thousand lines of PHP code in, it's better late than never.

Let's look at example #1 on count() manual
http://php.net/manual/en/function.count.php

$result count(null); // $result == 0
$result count(false); // $result == 1


Does this strike you as a bit odd? Why the hell should count(0) or count(false) be equal to 1?

Well strangely enough, that's how it is. So for example, if you wrote a mysql_query() wrapper where you return false if the query fails and if you expect an array where you check the number of items, you find out that if the query fails, the count will return 1, and you might get some unexpected results.

Keeping computer security in mind, it's best to avoid count() when just checking if some data is returned.

Alternatives are empty() if checks if a variable contains something other than 0, '0', null, false, array() or ''.

OR, in your wrapper functions, if the query fails, just return NULL!



Apache :: Could not determine fully qualified domain name


Error message:

apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName


Is preety much self-explanatory

Add this
ServerName localhost

In your server configuration file.


Apache :: VirtualHost overlap on port

Errors like


[warn] _default_ VirtualHost overlap on port 443, the first has precedence

are caused because the virtualhosts are not named.
(The same applies for any other port, for example 80)

Add this in your apache configuration file

NameVirtualHost *:443


In Ubuntu server, Linux, that configuration is actually located in the ports.conf file in /etc/apache2.


NameVirtualHost *:80
NameVirtualHost *:443


Listen 80

Feb 26, 2012

MySQL not starting when restoring files in /var/lib/mysql

If you get errors like:


120226  1:54:14 [Note] Plugin 'FEDERATED' is disabled.
120226  1:54:14  InnoDB: Initializing buffer pool, size = 8.0M
120226  1:54:14  InnoDB: Completed initialization of buffer pool
120226  1:54:15  InnoDB: Started; log sequence number 0 44233
120226  1:54:15 [ERROR] Event Scheduler: Failed to open table mysql.event
120226  1:54:15 [ERROR] Event Scheduler: Error while loading from disk.
120226  1:54:15 [Note] Event Scheduler: Purging the queue. 0 events
120226  1:54:15 [ERROR] Aborting


120226  1:54:15  InnoDB: Starting shutdown...
120226  1:54:20  InnoDB: Shutdown completed; log sequence number 0 44233
120226  1:54:20 [Note] mysqld: Shutdown complete

or

120226  1:59:18 [Note] Plugin 'FEDERATED' is disabled.
mysqld: Can't find file: './mysql/plugin.frm' (errno: 13)
120226  1:59:18 [ERROR] Can't open the mysql.plugin table. Please run mysql_upgrade to create it.
120226  1:59:18  InnoDB: Initializing buffer pool, size = 8.0M
120226  1:59:18  InnoDB: Completed initialization of buffer pool
120226  1:59:18  InnoDB: Started; log sequence number 0 44233
120226  1:59:18 [ERROR] mysqld: Can't find file: './mysql/host.frm' (errno: 13)
120226  1:59:18 [ERROR] Fatal error: Can't open and lock privilege tables: Can't find file: './mysql/host.frm' (errno: 13)

You need to check the file permissions.

The user and group is mysql:mysql
File permissions are rw for user and group (660)

Solution
chown mysql:mysql -R /var/lib/mysql
chmod 660 -R /var/lib/mysql

Feb 22, 2012

NETBIOS / Samba share does not accept username and password

If your username and password gets rejected when logging in MS file share, try using the INT domain for login.

example:

username: INT\your_username
password: your_password


Feb 21, 2012

Linux/Ubuntu :: pure-ftpd does not allow login to user with /usr/sbin/nologin shell

Expectations:
You have created a user with /usr/sbin/nologin shell (ftp-only user) in Linux/Ubuntu.
If you SSH to the box with this username and password it should not work.
If you FTP to the box with this username and password it should.

Symptoms:
Pure-ftpd does not permit login if the shell is set to /bin/false or /usr/sbin/nologin.
If you change the shell to /bin/bash it works.


Connected to localhost.
220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
220-You are user number 2 of 50 allowed.
220-Local time is now 17:53. Server port: 21.
220-This is a private system - No anonymous login
220-IPv6 connections are also welcome on this server.
220 You will be disconnected after 15 minutes of inactivity.
Name (localhost:root): ftponly
331 User ftponly OK. Password required
Password:
530 Login authentication failed
Login failed.
Remote system type is UNIX.
Using binary mode to transfer files.

Solution:
You need to add the nologin or false shell to the file /etc/shells.

root@box:/# cat /etc/shells
# /etc/shells: valid login shells
/bin/csh
/bin/sh
/usr/bin/es
/usr/bin/ksh
/bin/ksh
/usr/bin/rc
/usr/bin/tcsh
/bin/tcsh
/usr/bin/esh
/bin/dash
/bin/bash
/bin/rbash
/usr/bin/screen
/bin/false
/usr/sbin/nologin



Feb 18, 2012

PHP :: sending SMS via najdi.si FREE SMS

You need to make an account on https://id.najdi.si before you can use the code.

Example usage:
$sms = new sms();
$sms->send('090666666','one does not simply send an SMS');

https://github.com/jeancaffou/PHP-Najdi-SMS