Ok so after a lot of requests, lot of fuss and some busy office time, here is my V2 for Chat Heads !
This just extends the previous blog post & gives a Chat Head on an Incoming SMS. This blog post should be a starting guide if your planning to include chat head like notification for your upcoming android app.
So what are we waiting for ? Let's begin :
================================================================
ChatHeadService.java
================================================================
package com.example.testincoming;
import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
public class ChatHeadService extends Service {
String from,msg;
private WindowManager windowManager;
private ImageView chatHead;
WindowManager.LayoutParams params;
@Override public IBinder onBind(Intent intent) {
// Not used
from = intent.getStringExtra("From");
msg = intent.getStringExtra("Msg");
return null;
}
@Override public void onCreate() {
super.onCreate();
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
chatHead = new ImageView(this);
chatHead.setImageResource(R.drawable.ic_launcher);
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP | Gravity.LEFT;
params.x = 0;
params.y = 100;
windowManager.addView(chatHead, params);
chatHead.setOnTouchListener(new View.OnTouchListener() {
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
initialX = params.x;
initialY = params.y;
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
Intent i = new Intent(getBaseContext(),MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
i.setClass(getBaseContext(), MainActivity.class);
i.putExtra("Msg", msg);
i.putExtra("From", from);
startActivity(i);
return true;
case MotionEvent.ACTION_UP:
return true;
case MotionEvent.ACTION_MOVE:
params.x = initialX + (int) (event.getRawX() - initialTouchX);
params.y = initialY + (int) (event.getRawY() - initialTouchY);
windowManager.updateViewLayout(chatHead, params);
return true;
}
return false;
}
});
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
from = intent.getStringExtra("From");
msg = intent.getStringExtra("Msg");
Log.d("In Start", "In start");
return startId;
}
@Override
public void onDestroy() {
super.onDestroy();
if (chatHead != null) windowManager.removeView(chatHead);
}
So what did i change in this version :
1) We now start a activity from the service on Touch passing in the SMS Text received from the Broadcast Receiver.
2) The Activity Layout is completely empty except for a Absolute Layout as its parent
3) I have set the theme of the Application to a Dialog Theme.
================================================================
MainActivity.java
================================================================
package com.example.testincoming;
import android.os.Bundle;
import android.app.Activity;
import android.app.ActivityOptions;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
Button b ;
String from,msg;
ChatHeadService c = new ChatHeadService();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent incomingIntent = getIntent();
from = incomingIntent.getStringExtra("From");
msg = incomingIntent.getStringExtra("Msg");
Log.d("Activity", "Came in activity");
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(from);
builder.setMessage(msg);
Log.d("Activity", "Came in dialog");
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
Log.d("Activity", "Came in OK ");
MainActivity.this.finish();
}
});
builder.show();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Changes in this version in this Activity:
1) We now create a Dialog and take the text passed in from the Service
2) I set the sender's number/Name as the Dialog Title & the content of the SMS as the body of the Dialog.
3) I have set up a button on the dialog which on Click closes the dialog by finishing the activity.
================================================================
SmsListener.java
================================================================
package com.example.testincoming;
import android.animation.AnimatorSet.Builder;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
public class SmsListener extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){
Bundle bundle = intent.getExtras(); //---get the SMS message passed in---
SmsMessage[] msgs = null;
String msg_from;
if (bundle != null){
//---retrieve the SMS message received---
try{
Log.d("test", "came here!");
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
int length = msgs.length;
for(int i=0; i<length;i++){
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
msg_from = msgs[i].getOriginatingAddress();
String msgBody = msgs[i].getMessageBody();
Toast.makeText(context, msgBody, 550).show();
Intent chatHead = new Intent(context, ChatHeadService.class);
chatHead.putExtra("Msg", msgBody);
chatHead.putExtra("From", msg_from);
context.startService(chatHead);
Log.d("msgBody : ", msgBody);
}
}catch(Exception e){
Log.d("Exception caught",e.getMessage());
}
}
}
}
}
================================================================
Let's see what I did in the above class :
1) I create a Broadcast receiver which listens for Incoming SMS
2) I read the sms Text received & pass the sender Number , Msg to ChatHeadService class.
================================================================
So thats all that you need , dont forget to add appropriate permissions in the Manifest.
For any queries , drop me a comment !
Thanks