package com.sogou.sogouchat.os;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import com.sogou.sogouchat.bean.ContactNode;
import com.sogou.sogouchat.bean.DownNode;
import com.sogou.sogouchat.bean.MsgNode;
import com.sogou.sogouchat.bean.TelNode;
import com.sogou.sogouchat.os.DownloadManagerAsync.OnDownloadCompleteListener;
import com.sogou.sogouchat.os.DownloadManagerAsync.OnDownloadConnectListener;
import com.sogou.sogouchat.os.DownloadManagerAsync.OnDownloadErrorListener;
import com.sogou.sogouchat.os.DownloadManagerAsync.OnDownloadUpdateListener;
import android.app.NotificationManager;
import android.app.Service;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.Parcelable;
import android.os.RemoteException;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.Contacts;
import android.util.Log;
import android.widget.Toast;
public class MsgService extends Service {
private static final String TAG = "MsgService";
/** For showing and hiding our notification. */
NotificationManager mNM;
/** Keeps track of all current registered clients. */
ArrayList<Messenger> mClients = new ArrayList<Messenger>();
int mValue = 0;
// LinkedList<ContactNode> mContactList = new LinkedList<ContactNode>();
LinkedList<TelNode> mTelList = new LinkedList<TelNode>();
LinkedList<MsgNode> mMsgList = new LinkedList<MsgNode>();
ArrayList<DownNode> mDownList = new ArrayList<DownNode>();
int mMaxMsgId=0;
Context mContext;
SMSContentObserver mSmsObserver;
private int mMsgType;
private Intent mIntent = new Intent();
private Bundle mBundle = new Bundle();
private DownloadManagerAsync mDownMgr = new DownloadManagerAsync();
private DownListener mDownListener = new DownListener();
private Timer mDownTimer;
private TimerTask mDownTask;
private Handler mObserverHandler = new Handler() {
public void handleMessage(Message msg) {
Log.i(TAG, "mObserverHandler handleMessage") ;
switch (msg.what) {
case ChatAppConstant.SRV_BackMsg_New_Sms:{
sendSrvBroadcast(ChatAppConstant.SRV_BackMsg_New_Sms);
}
break;
default:
break;
}
}
};
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind") ;
return mBinder;
}
private final IMsgService.Stub mBinder = new IMsgService.Stub(){
@Override
public List<TelNode> getTelList() throws RemoteException {
// Log.i("IMsgService", "getContactList") ;
return mTelList;
}
public List<MsgNode> getNewMsgList() throws RemoteException {
// Log.i("IMsgService", "getContactList") ;
return mMsgList;
}
public void fetchContactDb() {
Log.i(TAG, "fetchContactDb");
// android.os.Debug.waitForDebugger();
if (mTelList.size() > 0) {
mTelList.clear();
}
doFetchContactBox();
doFetchMsgBox();
appendMsgList();
mMsgList.clear();
Log.i(TAG, "Print list ++");
// Iterator<ContactNode> it = mContactList.iterator();
// while(it.hasNext()){
// ContactNode node = it.next();
// node.logTo();
// }
Log.i(TAG, "Print list --");
}
public void fetchMsgBox(){
Log.i("IMsgService", "fetchMsgBox") ;
doFetchMsgBox();
}
public void handleSrvForeMsg(int msg, String arg1, String arg2){
Log.i("handleSrvMsg", "msg"+msg) ;
mMsgType = msg;
switch(msg){
case ChatAppConstant.SRV_ForeMsg_FetchDb:{
fetchContactDb();
sendSrvBroadcast(ChatAppConstant.SRV_BackMsg_FetchDb_Ok);
}
break;
case ChatAppConstant.SRV_ForeMsg_Down_Msg:{
Log.i("handleSrvMsg", "msg file ="+arg2) ;
mDownMgr.download(arg1, arg2);
}
break;
case ChatAppConstant.SRV_ForeMsg_Read_Sms:{
// setReadSms(arg1);
}
break;
default:{
}
break;
}
}
public void downMediaList(List<DownNode> msgList){
Iterator<DownNode> it = msgList.iterator();
while(it.hasNext()){
DownNode node = it.next();
addDownList(node);
}
//Start down timer
if (mDownTask == null ) {
mDownTask = new TimerTask(){
@Override
public void run() {
Log.i(TAG, "mDownTask run") ;
// TODO Auto-generated method stub
if (mDownList.size()>0 ){
Log.i(TAG, "mDownTask mRunning="+mDownMgr.mRunning);
if (!mDownMgr.mRunning){
DownNode node = mDownList.remove(0);
if (node.mShortUrl.length()>0){
Log.i(TAG, "mDownTask run start++"+node.mShortUrl) ;
mDownMgr.download(node);
}
}
}
else {
Log.i(TAG, "mDownTask stop TimerTask!!!!!") ;
mDownTask.cancel();
mDownTask = null;
}
}
};
mDownTimer.schedule(mDownTask, 1000, 5000);
}
}
};
@Override
public void onCreate() {
Log.i(TAG, "onCreate") ;
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
// Display a notification about us starting.
showNotification();
mContext = this;
mSmsObserver = new SMSContentObserver(mContext, mObserverHandler, this);
Uri smsUri = Uri.parse("content://sms");
getContentResolver().registerContentObserver(smsUri, true,mSmsObserver);
Toast.makeText(this, "server create", Toast.LENGTH_SHORT).show();
mDownMgr.setOnDownloadCompleteListener(mDownListener);
mDownMgr.setOnDownloadConnectListener(mDownListener);
mDownMgr.setOnDownloadErrorListener(mDownListener);
mDownMgr.setOnDownloadUpdateListener(mDownListener);
checkSavePath();
mDownTimer = new Timer();
}
@Override
public void onDestroy() {
// Cancel the persistent notification.
mNM.cancel("server start", 1000);
// Tell the user we stopped.
Toast.makeText(this, "server stop", Toast.LENGTH_SHORT).show();
}
private void showNotification() {
}
private void sendSrvBroadcast(int value){
Log.i(TAG, "sendSrvBroadcast") ;
mBundle.putInt("CastType", value);
mIntent.putExtras(mBundle);
mIntent.setAction("com.sogouchat.action.CONTENT_CHANGED_ACTION");
sendBroadcast(mIntent);
}
private void sendSrvBroadcast(int value, String body){
Log.i(TAG, "sendSrvBroadcast") ;
mBundle.putInt("CastType", value);
mBundle.putString("File", body);
mIntent.putExtras(mBundle);
mIntent.setAction("com.sogouchat.action.CONTENT_CHANGED_ACTION");
sendBroadcast(mIntent);
}
private void sendSrvBroadcast(int value, Parcelable body){
Log.i(TAG, "sendSrvBroadcast") ;
mBundle.putInt("CastType", value);
mBundle.putParcelable("parcel", body);
mIntent.putExtras(mBundle);
mIntent.setAction("com.sogouchat.action.CONTENT_CHANGED_ACTION");
sendBroadcast(mIntent);
}
public void doFetchMsgBox() {
Log.i(TAG, "doFetchMsgBox");
// 查询发件箱里的内容
Uri outSMSUri = Uri.parse("content://sms");
String[] projection= new String[] { "_id", "thread_id", "protocol", "read", "status", "type", "date", "address", "subject", "body"};
String selection = "1=1) group by "+"thread_id"+" -- (";
Cursor cur = mContext.getContentResolver().query(outSMSUri,
projection, selection, null, "date asc");
if (cur != null) {
// 循环遍历
cur.moveToFirst();
while (cur.moveToNext()) {
addMsgNode(cur);
}
cur.close();
}
}
private void addMsgNode(Cursor cur) {
MsgNode node = new MsgNode();
node.mMsgId = cur.getInt(cur.getColumnIndex("_id"));
// record max msgid
if (node.mMsgId > mMaxMsgId) mMaxMsgId = node.mMsgId;
node.mThreadId = cur.getInt(cur.getColumnIndex("thread_id"));
node.mProtocol = cur.getInt(cur.getColumnIndex("protocol"));
node.mRead = cur.getInt(cur.getColumnIndex("read"));
node.mStatus = cur.getInt(cur.getColumnIndex("status"));
node.mType = cur.getInt(cur.getColumnIndex("type"));
node.mDate = cur.getLong(cur.getColumnIndex("date"));
node.mAdress = cur.getString(cur.getColumnIndex("address"));
node.mSubject = cur.getString(cur.getColumnIndex("subject"));
node.mBody = cur.getString(cur.getColumnIndex("body"));
if (node.mAdress == null) return;
mMsgList.add(node);
Log.i(TAG, "addMsgNode+"+ node.mBody);
}
public void doFetchContactBox() {
Log.i(TAG, "doFetchContactBox");
// the selected cols for contact users
String[] selectCol = new String[] { ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.TYPE };
final int COL_ID = 0;
final int COL_NAME = 1;
final int COL_Num = 2;
final int COL_Type = 3;
String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
+ Contacts.HAS_PHONE_NUMBER + "=1) AND ("
+ Contacts.DISPLAY_NAME + " != '' ))";
Cursor cursor = this.getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
selectCol,
select,
null,
ContactsContract.Contacts.DISPLAY_NAME
+ " COLLATE LOCALIZED ASC");
if (cursor == null) {
Toast.makeText(this, "cursor is null!", Toast.LENGTH_LONG).show();
return;
} else if (cursor.getCount() == 0) {
Toast.makeText(this, "cursor count is zero!", Toast.LENGTH_LONG)
.show();
}
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
TelNode telNode = new TelNode();
// 遍历所有的联系人下面所有的电话号码
telNode.mContactId = cursor.getInt(COL_ID);
telNode.mName = cursor.getString(COL_NAME);
telNode.mTel = cursor.getString(COL_Num);
telNode.mType = cursor.getInt(COL_Type);
// Log.i(TAG, "addTelNumNode---"+ telNode.mContactId);
// Log.i(TAG, "addTelNumNode+"+ telNode.mDisName);
// Log.i(TAG, "addTelNumNode+"+ telNode.mTel);
// Log.i(TAG, "addTelNumNode+++");
mTelList.add(telNode);
cursor.moveToNext();
}
cursor.close();
}
void appendMsgList(){
Log.i(TAG, "appendMsgList");
Iterator<MsgNode> msgIt = mMsgList.iterator();
while(msgIt.hasNext()){
// Log.i(TAG, "appendMsgList 1");
MsgNode msgNode = msgIt.next();
// Log.i(TAG, "appendMsgList 2");
TelNode telNode = getTelNumNode(msgNode.mAdress);
// Log.i(TAG, "appendMsgList 3");
if (telNode == null){
// Log.i(TAG, "mergeMsgList NOT find");
telNode = new TelNode();
telNode.mTel = msgNode.mAdress;
telNode.mName = telNode.mTel;
mTelList.add(telNode);
}
// Log.i(TAG, "appendMsgList 4");
if (telNode.mMsgList == null){
telNode.mMsgList = new ArrayList<MsgNode>();
}
// Log.i(TAG, "appendMsgList 5");
telNode.mMsgCnt++;
if (msgNode.mRead == 0) telNode.mNewMsgCnt++;
if (msgNode.mDate > telNode.mLastDate){
telNode.mLastDate = msgNode.mDate;
telNode.mLastBody = msgNode.mBody;
}
// Log.i(TAG, "appendMsgList 6");
telNode.mMsgList.add(msgNode);
}
}
TelNode getTelNumNode(String tel) {
// Log.i(TAG, "getTelNumNode"+tel);
if (tel == null) {
return null;
}
Iterator<TelNode> telIt = mTelList.iterator();
while (telIt.hasNext()) {
TelNode telNode = telIt.next();
if (isSameTel (telNode.mTel, tel)) {
return telNode;
}
}
// Log.i(TAG, "getTelNumNode Not"+tel);
return null;
}
private boolean isSameTel(String tel1, String tel2){
String sub1 =null;
String sub2 = null;
int len1 = tel1.length();
int len2 = tel2.length();
if (len1>5){
sub1= tel1.substring(len1-5, len1);
}
else{
sub1= tel1;
}
if (len2>5){
sub2= tel2.substring(len2-5, len2);
}
else{
sub2= tel2;
}
boolean result = tel1.contains(sub2) || tel2.contains(sub1);
return result;
}
class DownListener implements OnDownloadUpdateListener,
OnDownloadConnectListener,
OnDownloadCompleteListener,
OnDownloadErrorListener {
@Override
public void onDownloadError(DownloadManagerAsync manager, Exception e) {
// TODO Auto-generated method stub
Log.i(TAG, "onDownloadError"+e) ;
}
@Override
public void onDownloadComplete(DownloadManagerAsync manager,
Object result, String file) {
// TODO Auto-generated method stub
Log.i(TAG, "onDownloadComplete"+file) ;
// Log.i(TAG, "mDownTask mRunning="+mDownMgr.mRunning);
sendSrvBroadcast( ChatAppConstant.SRV_BackMsg_File_Down_Ok, file);
}
@Override
public void onDownloadConnect(DownloadManagerAsync manager) {
// TODO Auto-generated method stub
Log.i(TAG, "onDownloadConnect") ;
// Log.i(TAG, "mDownTask mRunning="+mDownMgr.mRunning);
}
@Override
public void onDownloadUpdate(DownloadManagerAsync manager, int percent) {
// TODO Auto-generated method stub
Log.i(TAG, "onDownloadUpdate"+percent) ;
// Log.i(TAG, "mDownTask mRunning="+mDownMgr.mRunning);
}
}
public static boolean hasSdcard() {
String status = Environment.getExternalStorageState();
if (status.equals(Environment.MEDIA_MOUNTED)) {
return true;
} else {
return false;
}
}
private void checkSavePath() {
if (getSDPath() == null) {
Log.i(TAG, "SD is not existing.");
} else {
if (Environment.MEDIA_MOUNTED.equals(Environment
.getExternalStorageState())) {
File sdcardDir = Environment.getExternalStorageDirectory();
String newPath = sdcardDir.getPath() + "/sogouchat/";
File path = new File(newPath);
if (!path.exists()) {
path.mkdirs();
System.out.println("paht ok,path:" + newPath);
}
newPath = newPath + "/media/";
path = new File(newPath);
if (!path.exists()) {
// 若不存在,创建目录,可以在应用启动的时候创建
path.mkdirs();
System.out.println("paht ok,path:" + newPath);
}
} else {
System.out.println("false");
}
}
}
public String getSDPath() {
File SDdir = null;
boolean sdCardExist = Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED);
if (sdCardExist) {
SDdir = Environment.getExternalStorageDirectory();
}
if (SDdir != null) {
return SDdir.toString();
} else {
return null;
}
}
public void setReadSms(String tel){
Log.i(TAG, "setRead tel ="+tel);
ContentValues cv = new ContentValues();
cv.put("read", "1");
Uri smsUri = Uri.parse("content://sms/index");
mContext.getContentResolver().update(smsUri, cv,
"address= ? and type = ?",new String[] {tel, "1"});
}
private void addDownList(DownNode node){
Iterator<DownNode> it = mDownList.iterator();
while(it.hasNext()){
if (it.next().mDate == node.mDate){
break;
}
}
if (!it.hasNext()){
mDownList.add(0, node);
}
}
}