April 29, 2010

[SOLVED] Android: Convert dip to px.


It uses pixels, but I'm sure you're wondering how to use dips instead. The answer is inTypedValue.applyDimension()Here's an example of how to convert dips to px in code:



// Converts 14 dip into its equivalent px
Resources r = getResources();
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14, r.getDisplayMetrics());



Source: Does setWidthint pixels use dip or px? - Stack Overflow.

[SOLVED] Android: Using Custom Fonts


Android comes with 3 fonts (Sans, Serif, Monospace) which can be accesed using android:typeface="FONT_NAME". But most of the times you would want to use your own fonts instead of the stock ones. Android provides an "assets" folder where you can put your TTF font files and access them from within the code.



There are two ways of doing this,



1. Assign the Typeface object to TextView,



2. Paint the Typeface on screen Canvas.





Method 1 - Assigning Typeface object to TextView



public void onCreate(Bundle savedInstanceState) 
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

TextView bauhs = null,chiller=null,broadw=null,joker=null ;
Button mag=null;

setFont(bauhs, "fonts/BAUHS93.TTF", R.id.bauhs);

setFont(broadw, "fonts/BROADW.TTF", R.id.broadw);

setFont(chiller, "fonts/CHILLER.TTF", R.id.chiller);

setFont(joker, "fonts/JOKERMAN.TTF", R.id.joker);

setFont(mag, "fonts/MAGNETOB.TTF", R.id.magneto);

}

void setFont(TextView name, String path, int res)
{
name=(TextView)findViewById(res);
Typeface font = Typeface.createFromAsset(this.getAssets(), path);

name.setTypeface(font);

}


- "Typeface" is the class for handling fonts.


- The createFromAsset() method is used to specify the font path.


font object is assigned to the TextView name



Method 2 - Drawing the font on screen canvas



@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(new FontView(this));
}

private static class FontView extends View
{
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private Typeface mFace;

public FontView(Context context)
{
super(context);

// mFace = Typeface.createFromAsset(getContext().getAssets(),"fonts/MAGNETOB.TTF");

mPaint.setTextSize(34);
mPaint.setColor(Color.WHITE);
}

@Override
protected void onDraw(Canvas canvas)
{
canvas.drawColor(Color.BLACK);

drawFont(canvas, "fonts/BAUHS93.TTF", 50, "Bauhaus 93");

drawFont(canvas, "fonts/BROADW.TTF", 150, "Broadway");

drawFont(canvas, "fonts/CHILLER.TTF", 250, "Chiller");

drawFont(canvas, "fonts/JOKERMAN.TTF", 350, "Jokerman");

}

void drawFont(Canvas canvas, String path, int y, String name)
{
mFace = Typeface.createFromAsset(getContext().getAssets(),path);

mPaint.setTypeface(mFace);
canvas.drawText(name, 30, y, mPaint);

}
}


- We need to extend the View class to access and override the onDraw() method.



- A Paint object is created which allows us to set the font size and color.



- The TypeFace object mFace is assigned to mPaint which is drawn on screen using the drawText().



drawText() takes 3 parameters, the text to be painted, its X-Y location and the Paint object.





Note: There is a difference between arial.ttf and ARIAL.TTF . If it ARIAL.TTF in your /assets folder and arial.ttf in your code, it will not work.

So if you have set the path correct but still wondering why the font is not being displayed, check this naming.


Source: Using Custom Fonts - ModMyGPhone Wiki.

[SOLVED] Creating and Using Databases in Android

Creating and Using Databases in Android.

April 17, 2010

[SOLVED] Copy MySQL database from one server to another remote server


Usually you run mysqldump to create database copy:
$ mysqldump -u user -p db-name > db-name.out


Copy db-name.out file using sftp/ssh to remote MySQL server:
$ scp db-name.out user@remote.box.com:/backup


Restore database at remote server (login over ssh):
$ mysql -u user -p db-name < db-name.out



How do I copy a MySQL database from one computer/server to another?


Short answer is you can copy database from one computer/server to another using ssh or mysql client.


You can run all the above 3 commands in one pass using mysqldump and mysql commands (insecure method, use only if you are using VPN or trust your network):
$ mysqldump db-name | mysql -h remote.box.com db-name


Use ssh if you don't have direct access to remote mysql server (secure method):
$ mysqldump db-name | ssh user@remote.box.com mysql db-name


You can just copy table called foo to remote database (and remote mysql server remote.box.com) called bar using same syntax:
$ mysqldump db-name foo | ssh user@remote.box.com mysql bar





Source: Copy MySQL database from one server to another remote server.

[SOLVED] Move or migrate user accounts from old Linux server to a new Linux server


Commands to type on old Linux system


First create a tar ball of old uses (old Linux system). Create a directory:
# mkdir /root/move/
Setup UID filter limit:
# export UGIDLIMIT=500
Now copy /etc/passwd accounts to /root/move/passwd.mig using awk to filter out system account (i.e. only copy user accounts)
# awk -v LIMIT=$UGIDLIMIT -F: '($3>=LIMIT) && ($3!=65534)' /etc/passwd > /root/move/passwd.mig
Copy /etc/group file:
# awk -v LIMIT=$UGIDLIMIT -F: '($3>=LIMIT) && ($3!=65534)' /etc/group > /root/move/group.mig
Copy /etc/shadow file:
# awk -v LIMIT=$UGIDLIMIT -F: '($3>=LIMIT) && ($3!=65534) {print $1}' /etc/passwd | tee - |egrep -f - /etc/shadow > /root/move/shadow.mig
Copy /etc/gshadow (rarely used):
# cp /etc/gshadow /root/move/gshadow.mig
Make a backup of /home and /var/spool/mail dirs:
# tar -zcvpf /root/move/home.tar.gz /home
# tar -zcvpf /root/move/mail.tar.gz /var/spool/mail


Where,




  • Users that are added to the Linux system always start with UID and GID values of as specified by Linux distribution or set by admin. Limits according to different Linux distro:

    • RHEL/CentOS/Fedora Core : Default is 500 and upper limit is 65534 (/etc/libuser.conf).

    • Debian and Ubuntu Linux : Default is 1000 and upper limit is 29999 (/etc/adduser.conf).



  • You should never ever create any new system user accounts on the newly installed Cent OS Linux. So above awk command filter out UID according to Linux distro.

  • export UGIDLIMIT=500 - setup UID start limit for normal user account. Set this value as per your Linux distro.

  • awk -v LIMIT=$UGIDLIMIT -F: '($3>=LIMIT) && ($3!=65534)' /etc/passwd > /root/move/passwd.mig - You need to pass UGIDLIMIT variable to awk using -v option (it assigns value of shell variable UGIDLIMIT to awk program variable LIMIT). Option -F: sets the field separator to : . Finally awk read each line from /etc/passwd, filter out system accounts and generates new file /root/move/passwd.mig. Same logic is applies to rest of awk command.

  • tar -zcvpf /root/move/home.tar.gz /home - Make a backup of users /home dir

  • tar -zcvpf /root/move/mail.tar.gz /var/spool/mail - Make a backup of users mail dir


Use scp or usb pen or tape to copy /root/move to a new Linux system.
# scp -r /root/move/* user@new.linuxserver.com:/path/to/location



Commands to type on new Linux system


First, make a backup of current users and passwords:
# mkdir /root/newsusers.bak
# cp /etc/passwd /etc/shadow /etc/group /etc/gshadow /root/newsusers.bak

Now restore passwd and other files in /etc/
# cd /path/to/location
# cat passwd.mig >> /etc/passwd
# cat group.mig >> /etc/group
# cat shadow.mig >> /etc/shadow
# /bin/cp gshadow.mig /etc/gshadow


Please note that you must use >> (append) and not > (create) shell redirection.


Now copy and extract home.tar.gz to new server /home
# cd /
# tar -zxvf /path/to/location/home.tar.gz


Now copy and extract mail.tar.gz (Mails) to new server /var/spool/mail
# cd /
# tar -zxvf /path/to/location/mail.tar.gz


Now reboot system; when the Linux comes back, your user accounts will work as they did before on old system:
# reboot


Source:Move or migrate user accounts from old Linux server to a new Linux server.

[SOLVED] “Could not reliably determine the server’s fully qualified domain name, using ... for ServerName”

 

You might probably faced the same following error while you were restarting the Apache server on Ubuntu.




$ sudo /etc/init.d/apache2 restart
Restarting web server apache2                                                apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName
... waiting apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName



To fix that problem, you need to edit the httpd.conf file. Open the terminal and type,




$ sudo gedit /etc/apache2/httpd.conf


By default httpd.conf file will be blank. Now, simply add the following line to the file.




ServerName localhost


Save the file and exit from gEdit.


Finally restart the server.




$ sudo /etc/init.d/apache2 restart


Source: How to fix Apache – “Could not reliably determine the server’s fully qualified domain name, using 127.0.1.1 for ServerName” Error on Ubuntu.

April 11, 2010

[SOLVED]How to determine screen size programmatically

@Override
public void onCreate(Bundle icicle) {
. . .
WindowManager w = getWindowManager();
Display d = w.getDefaultDisplay();
int width = d.getWidth();
int height = d.getHeight();
.

How to determine screen resolution programmatically - Android Developers Google Groups.

April 5, 2010

[SOLVED] Finding the name of installed applications

PackageManager pm = this.getPackageManager();
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);

List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0);
for(ResolveInfo info: list)
{
Log.w("App browser", info.activityInfo.applicationInfo.loadLabel( pm ).toString());
}


Source: Finding the name of installed applications - Android Developers Google Groups.

April 4, 2010

Eclipse Tip: Toggle Block Selection Mode "Alt+Shift+A"

Just found the "Toggele Block Selection Mode" in my Eclipse 3.5.2 "Alt+Shift+A". Juuuhuuu!!!

Related: http://www.vasanth.in/2009/03/31/eclipse-tip-block-selection-mode/

[SOLVED] Intents, sending multily data aka ACTION_SEND_MULTIPLY

FileBrowser Send / Receive Intents




Blackmoon File Browser app has grown from a simple browser to a full fledged file manager and able to launch apps based on the given file name so that you don't have to launch the app and then open the file. Expanding on this idea, FileBrowser grew arms with which to pass off data to other apps in singles or multiples. FileBrowser then grew ears to listen for other apps that wish to use it's functionality to pick files or folders. Most of these Intents are discoverable, but any good dev knows that getting information directly from the source trumps whatever else is available. In this article, I will specify what Intents FileBrowser uses and how you can use them in your own app.

Launch App Intent


The simplest form of Intent used by FileBrowser is the launch intent. There are two methods being used. One specific to "Open File" and the other is used by "Open with...". Open File is used to launch the default activity for the given file's MIME type. Determining a file's MIME type is beyond the scope of this article.
In the example, you want to VIEW the file which has a MIME type of theMIMEtype.
String theMIMEType = getMIMEtype(aFile);
if (theMIMEType!=null) {
Intent theIntent = new Intent(Intent.ACTION_VIEW);
theIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK+Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
theIntent.setDataAndType(Uri.fromFile(aFile), theMIMEType);
try {
startActivity(theIntent);
} catch (ActivityNotFoundException anfe) {
//show error
}
}

Since you declare what the MIME type is supposed to be, any file can try to be opened by any app... most likely it will not, but this allows for opening up an HTML file in a text editor rather than a web browser. If there is more than one app that is capable of handling the launch request for the given MIME type, Android will ask the user to pick one and give them the option of making that choice the default which would prevent Android from asking again in the future.

"Open with..." has a slightly different form of app launcher in that the startActivity() is called with a Chooser rather than merely relying on the default chosen for a particular MIME type. FileBrowser goes an extra step further and instead of merely using the MIME type of the given file, it uses the MIME category instead. A .jpg file with a MIME type of "image/jpeg" would have a MIME category of "image/*". This means that an image viewer that is able to open images, but not necessarily JPEG images will also be included in the list of apps that can receive this file. FileBrowser does this to allow more flexibility in how you can open a file since you sometimes want to use a slightly different app than the default one.
Intent theIntent = new Intent(Intent.ACTION_VIEW);
theIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK+Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
String theMIMEcategory = getMIMEcategory(aFile);
theIntent.setDataAndType(Uri.fromFile(aFile),theMIMEcategory);
try {
startActivity(Intent.createChooser(theIntent,aChooserTitleString));
} catch (Exception e) {
//show error
}

These two VIEW action Intents are the basic examples of how FileBrowser launches an app to open any given file. It launches them as separate apps so that it mimics what a person would actually do on their phone by launching the proper app and then loading that particular file to use with that app. Using FileBrowser merely changes the order of those steps so that you can see what file you wish to use first and then launch the proper app.

Listening for Intents


Listening for Intents is a two step process. The first step being to tell the AndroidManifest.xml which Intents to listen for and what Activity to launch in response to one. A single activity can have more than one Intent filter. FileBrowser's main activity has 3 intents associated with it. The first is the standard main app launcher. A second Intent filter deals specifically with the various pick Intents. The third Intent filter is a specialized pick filter - GET_CONTENT. Here is how FileBrowser defines the later two filters:
<intent-filter>
<action android:name="android.intent.action.PICK" />
<action android:name="org.openintents.action.PICK_FILE" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" />
<data android:scheme="folder" />
<data android:scheme="directory" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.GET_CONTENT" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.OPENABLE" />
<data android:mimeType="*/*" />
</intent-filter>

The first filter states to the Android system that it will accept any action that equals PICK or PICK_FILE. The OR is very important as this only applies to other actions listed in the same filter. We narrow down the PICK actions by specifying that in addtion to either PICK or PICK_FILE, the Intent must also have a data scheme of either "file" or "folder" or "directory". Any combination of Actions and Data Schemes that match that criteria will consider FileBrowser as a potential recipient for the Intent. The categories listed are DEFAULT, which every Intent filter should have, and BROWSABLE, meaning that your Activity is safe to use from a web browser.

The second filter is the GET_CONTENT filter, again listing the DEFAULT category all public filters should have as well as OPENABLE, meaning your activity is able to open the content the Intent is requesting. The data mimeType of "*/*" means that we are capable of opening and returning any MIME type desired. This filter was put into FileBrowser specifically to handle email attaching from the Gmail/Email apps. When Gmail asks Android for an app capable of attaching content to the email, FileBrowser will be listed as one of those apps that can pick a file to attach.

The second step in the process of responding to an Intent is to write the code necessary to send the data back to the requesting app. Since I have already covered how to write such code in an earlier article, I am just going to provide a link to it.

Sending a "Single Datum" Intent


Sending a single file is very similar to opening it. The difference is the Action to use and the Extras needed. The typical recipient for a Send request is email, but any number of apps can also receive such an Intent. I like to think of Send Intents as a kind of throw/catch arrangement as opposed to the View Intent which is more of a "point and look" arrangement.
String theMIMEType = getMIMEtype(aFile);
if (theMIMEType!=null) {
Intent theIntent = new Intent(Intent.ACTION_SEND);
theIntent.setType(theMIMEType);
theIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(aFile));
//next line specific to email attachments
theIntent.putExtra(Intent.EXTRA_SUBJECT, aFile.getName());
try {
startActivity(Intent.createChooser(theIntent, aChooserTitle));
} catch (Exception e) {
//show error
}
}

FileBrowser uses the Send Action, sets the MIME type for the file to be sent, but does not set the Data portion of the Intent. Instead, we add an Extra, specifically an EXTRA_STREAM, with the file Uri as it's value. The EXTRA_SUBJECT is not required, but is an optional feature specific to the email apps that use this Intent to attach files to an email.

Sending/Receiving a "Multiple Data" Intent


This particular feature of FileBrowser is not well defined elsewhere for Android apps. There is no real standard or example to follow and there isn't too many apps that can actually handle multiple files. Hopefully this article will allow more developers to understand and incorporate handling multiple data points (files in our case) into their apps.

Sending multiple files from FileBrowser first requires some mechanism to select mutiple files and organize them somehow. The implementation details of such are not important. Suffice to say, by the time we are ready to send multiple file Uris, we can get an ArrayList from our internal structure. The difficult part is not the packing of the list into the Intent, but actually analyzing each file Uri that is going into it so that the "overall" MIME type for the given list is set as the Intent type.

Sending Multiple


public static String getMIMEcategory(String aMIMEtype) {
if (aMIMEtype!=null) {
aMIMEtype = aMIMEtype.substring(0,aMIMEtype.lastIndexOf("/",aMIMEtype.length()-1))+"/*";
} else {
aMIMEtype = "*/*";
}
return aMIMEtype;
}

protected boolean packageMarkedFiles(Intent aIntent) {
ArrayList theUris = myFilesToSend.toUriList();
//iterate through the list and get overall mimeType
String theOverallMIMEtype = null;
String theMIMEtype = null;
String theOverallMIMEcategory = null;
String theMIMEcategory = null;
Iterator iu = theUris.iterator();
while (iu.hasNext()) {
String theFilename = iu.next().getLastPathSegment();
theMIMEtype = getMIMEtype(theFilename);
if (theOverallMIMEtype!=null) {
if (!theOverallMIMEtype.equals(theMIMEtype)) {
theOverallMIMEcategory = getMIMEcategory(theOverallMIMEtype);
theMIMEcat = getMIMEcategory(theMIMEtype);
if (!theOverallMIMEcat.equals(theMIMEcat)) {
theOverallMIMEtype = "multipart/mixed";
break; //no need to keep looking at the various types
} else {
theOverallMIMEtype = theOverallMIMEcat+"/*";
}
} else {
//nothing to do
}
} else {
theOverallMIMEtype = theMIMEtype;
}
}
if (theUris!=null && theOverallMIMEtype!=null) {
aIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM,theUris);
aIntent.setType(theOverallMIMEtype);
return true;
} else {
return false;
}
}

protected boolean sendMarkedFiles() {
Intent theIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
if (packageMarkedFiles(theIntent,false)) {
startActivity(Intent.createChooser(theIntent, aChooserTitle));
}
return true;
}

As before, determining a file's MIME type is beyond the scope of this article. Once you run through your list of file Uris and determine what the overall MIME type for the list is going to be, filling the Intent is quite simple as it becomes one call to putParcelableArrayListExtra().

Receiving Multiple


Receiving an ACTION_SEND_MULTIPLE Intent is also fairly straightforward since you just call the opposite method to retrive the list of Uris.
Intent theIntent = getIntent();
if (theIntent!=null) {
String theAction = theIntent.getAction();
if (Intent.ACTION_SEND_MULTIPLE.equals(theAction)) {
theFileList = theIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
}
}

Once you have your file Uri list, you can act upon it however you wish. Also, do not forget to put an Intent filter on your activity in the AndroidManifest.xml. The one FileBrowser uses to create playlists from multiple audio files is shown.
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="audio/*" />
</intent-filter>

I encourage other developers to incorporate listening for SEND_MULTIPLE requests into their apps that also listen for single requests. They do not add much more complexity to your app and if you are only listening for them, it is not hard at all to add it as a feature.


Source: FileBrowser Send / Receive Intents.

Another example yo can find on code.google.com

April 3, 2010

[SOLVED] Do not show soft keyboard on Activiry start

Just put windowsSoftInputMode attribute in your Manifest

 <activity name="EditContactActivity"
android:windowSoftInputMode="stateHidden">
...
</activity>

Android Developers Blog: Updating Applications for On-screen Input Methods.