ssCAROのブログ

色んなとこで見つけたプログラムのメモ置き場っぽい

プッシュメールの受信

au-one(gmail)からのプッシュメールの通知を受け取れるようになった。
IMAPFolderのidle()で取れるみたい。
idle()でメールが来るまで待機しているのでスレッドにする。
指定フォルダ(INBOX)に変化があれば通知される。

idleコマンドのサーバー側タイムアウトとかで再接続されるとか確認できていない。

IMAP4プロトコルのIDLEコマンドを使う。

参考サイト
GmailAssistant
http://gmailassistant.sourceforge.net/

package com.example.android.IMAPDemo;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.event.MessageCountEvent;
import javax.mail.event.MessageCountListener;
import javax.mail.internet.InternetAddress;
import com.sun.mail.imap.IMAPFolder;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class IMAPDemoActivity extends Activity {
    private Button buttonStart;
    private Button buttonStop;
    private TextView textMessage;
    
    private Handler mHandler = new Handler();
    private List mListLog = new ArrayList();
    private boolean mIdleStop = false;
    private Thread mThread = null;
    private Store mStore = null;
    private IMAPFolder mFolder = null;
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        buttonStart = (Button)findViewById(R.id.buttonStart);
        buttonStart.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                buttonStart_onClick();
            }
        });
        buttonStop = (Button)findViewById(R.id.buttonStop);
        buttonStop.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                buttonStop_onClick();
            }
        });
        textMessage = (TextView)findViewById(R.id.textMessage);
        Bundle bundle = textMessage.getInputExtras(true);
        bundle.putBoolean("allowEmoji", true);
    }
    
    @Override
    protected void onPause () {
        super.onPause();
    }
    
    public void buttonStart_onClick() {
        Properties props = new Properties();
        props.setProperty("mail.store.protocol", "imaps");
        //props.setProperty("mail.imap.host", "imap.gmail.com");
        //props.setProperty("mail.imap.port", "993");
        //props.setProperty("mail.imap.socketFactory.port", "993");
        //props.setProperty("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        //props.setProperty("mail.imap.socketFactory.fallback", "false");
        //props.setProperty("mail.imap.connectionpoolsize", "10");
        //props.setProperty("mail.imap.separatestoreconnection", "true");
        //props.setProperty("mail.imap.partialfetch", "false");
        //Properties props = System.getProperties();
        
        Session sess = Session.getDefaultInstance(props, null);
        
        String user = "*****@auone.jp";
        String password = "*****";
        String push_folder = "INBOX";
        
        try {
            mStore = sess.getStore("imaps");
            mStore.connect("imap.gmail.com", 993, user, password);
            
            // メール通知確認を開始
            startIdleLoop(mStore, push_folder);
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public void buttonStop_onClick() {
        mIdleStop = true;
        if (mFolder != null) {
            try {
                mFolder.close(false);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (mStore != null) {
            try {
                mStore.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // メール通知確認を停止
        stopIdleLoop();
    }

    /**
     * メール通知確認を開始
     * @param mailStore
     * @param mailFolder
     */
    private void startIdleLoop(final Store mailStore, final String mailFolder) {
        Runnable runner = new Runnable() {
            public void run() {
                //INBOXに変化があった
                final MessageCountListener idleListener = new MessageCountListener() {
                    //メールが追加(別フォルダから移動でも)
                    public void messagesAdded(MessageCountEvent e) {
                        String subject = "";
                        try {
                            Message message[] = e.getMessages();
                            statusCall(message[0]);
                            subject = message[0].getSubject();
                        } catch (MessagingException me) {
                            me.printStackTrace();
                            subject = me.toString();
                        }
                        setMessage("Added: " + subject);
                    }
                    //メールが削除(別フォルダに移動でも)
                    public void messagesRemoved(MessageCountEvent e) {
                        setMessage("Removed");
                    }
                };
                
                NextIdleIteration:
                while (!mIdleStop) {
                    sleep(2000L);
                    
                    try {
                        mFolder = (IMAPFolder)mailStore.getFolder(mailFolder);
                        mFolder.addMessageCountListener(idleListener);
                        
                        if (!mFolder.exists()) {
                            continue NextIdleIteration;
                        }
                        
                        if (!mFolder.isOpen()) {
                            mFolder.open(Folder.READ_ONLY);
                        }
                        
                        setMessage("idle called");
                        // idle() でメールが来るまで待機してる
                        // メールが来ると抜ける
                        mFolder.idle();
                        setMessage("idle returned");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        mThread = new Thread(runner);
        mThread.start();
    }
    /**
     * メール通知確認を停止
     */
    private void stopIdleLoop() {
        mIdleStop = true;
        if (mThread != null) {
            mThread.interrupt();
        }
    }
    
    private void statusCall(final Message message) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    InternetAddress addrFrom = (InternetAddress)message.getFrom()[0];
                    String address = addrFrom.getAddress();
                    String subject = message.getSubject();
                    
                    NotificationManager notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
                    Notification notification = new Notification(
                            R.drawable.icon,
                            "メールが届きました",
                            System.currentTimeMillis());
                    Intent intent = new Intent(Intent.ACTION_VIEW);
                    PendingIntent contentIntent = PendingIntent.getActivity(IMAPDemoActivity.this, 0, intent, 0);
                    notification.setLatestEventInfo(
                            IMAPDemoActivity.this,
                            address,
                            subject,
                            contentIntent);
                    notificationManager.notify(R.string.app_name, notification);
                } catch (MessagingException e) {
                    e.printStackTrace();
                }
            }
        });
    }
    
    private void setMessage(final String log) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (mListLog.size() > 20) {
                    mListLog.remove(0);
                }
                mListLog.add(log + "\n");
                StringBuffer sb = new StringBuffer();
                for (int i = 0; i < mListLog.size(); i++) {
                    sb.append(mListLog.get(i));
                }
                textMessage.setText(sb.toString());
            }
        });
    }
    
    private void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}