Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 初探Android N--桌面提示未讀信息

初探Android N--桌面提示未讀信息

編輯:關於Android編程

之前一旦時間覺得不知道看些什麼學些什麼還打游戲,有點頹廢。然後想想總得繼續學習,正好I/O大會剛結束,那就來看一些新東西

大篇幅安利:Android">https://github.com/ddwhan0123/Useful-Open-Source-Android(我每天都在更啊!!)

平時總有一些小伙子們都在問,如何做到iOS的那些桌面圖標顯示未讀,這次的官方Smaple給出了解決方式!!!看下圖!!!!

這裡寫圖片描述

乍看之下就是普通的Notification

然後點了查閱了這條Message返回桌面之後

這裡寫圖片描述

看著Icon上面的數字,是不是很開熏?是不是就是一直想要的?<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPk9Lo6zO0sPHwLS/tM/C1eK2q8731NrExKOhPC9wPg0KPHA+PGltZyBhbHQ9"這裡寫圖片描述" src="/uploadfile/Collfiles/20160526/20160526091216165.png" title="\" />

這裡給出URL:https://developer.android.com/samples/MessagingService/index.html

這裡給出下載地址:https://developer.android.com/downloads/samples/MessagingService.zip

如果Google的不行,用這個:https://github.com/googlesamples/android-MessagingService/archive/master.zip

下載好build之後是這樣子的

這裡寫圖片描述

我們來看下這個功能室如何使用的(還是老風龔ky"/kf/web/php/" target="_blank" class="keylink">PHPyNGnu+HTw6Os1N3KsbK7zKvP6s+4tcS/tMq1z9ajqTwvcD4NCjxwPs/IveLKzc/C1eK49lNhbXBsZbPM0PLKx7jJwu+1xKO/PC9wPg0KPGJsb2NrcXVvdGU+DQoJPHA+VGhpcyBzYW1wbGUgc2hvd3MgYSBzaW1wbGUgc2VydmljZSB0aGF0IHNlbmRzIG5vdGlmaWNhdGlvbnMgdXNpbmcgTm90aWZpY2F0aW9uQ29tcGF0LiBJdCBhbHNvIGV4dGVuZHMgdGhlIG5vdGlmaWNhdGlvbiB3aXRoIFJlbW90ZSBJbnB1dCB0byBhbGxvdyBBbmRyb2lkIE4gZGV2aWNlcyB0byByZXBseSB2aWEgdGV4dCBkaXJlY3RseSBmcm9tIHRoZSBub3RpZmljYXRpb24gd2l0aG91dCBoYXZpbmcgdG8gb3BlbiBhbiBBcHAuIFRoZSBzYW1lIFJlbW90ZSBJbnB1dCBvYmplY3QgYWxzbyBhbGxvd3MgQW5kcm9pZCBBdXRvIHVzZXJzIHRvIHJlc3BvbmQgYnkgdm9pY2Ugd2hlbiB0aGUgbm90aWZpY2F0aW9uIGlzIHByZXNlbnRlZCB0aGVyZS4gTm90ZTogRWFjaCB1bnJlYWQgY29udmVyc2F0aW9uIGZyb20gYSB1c2VyIGlzIHNlbnQgYXMgYSBkaXN0aW5jdCBub3RpZmljYXRpb24uPC9wPg0KPC9ibG9ja3F1b3RlPg0KPHA+u/rQtbet0uvSu8/CPC9wPg0KPGJsb2NrcXVvdGU+DQoJPHA+tMvKvsD9z9TKvsHL0ru49rzytaW1xLf+zvGjrMq508NOb3RpZmljYXRpb25Db21wYXS3osvNzajWqqGjy/y7ucCp1bnBy9S2s8zK5MjrtcTNqNaqo6zIw0FuZHJvaWS1xE649sb3vP7NqLn9zsTX1taxvdO007jDzajWqqOstvjO3tDotPK/qtOm08O08Li0oaPP4M2stcTUtrPMyuTI67bUz/O7udTK0O3Ksc2osajM4bP209BBbmRyb2lktcTG+7O108O7p82ouf3T79L0z+zTpqGj16LS4qO6tNPTw7untcTDv7j2zrS2wbvhu7DX986q0ru49rWltsC3osvNzajWqqGjPC9wPg0KPC9ibG9ja3F1b3RlPg0KPHA+U2FtcGxl0rXO8cH3s8y089bCyOfPwqO6PC9wPg0KPHA+sPO2qNK7uPZTZXJ2aWNlyLu687Xju/ewtMWlt6LLzc/7z6LIu7rztLS9qMHLz/vPos2o1qqjrLWxzajWqrG7tKbA7VJlcGx5UmVjZWl2ZXK908rVY29udmVyc2F0aW9uSWTU2VJlYWRSZWNlaXZlcs2ouf1NZXNzYWdlTG9nZ2VyvMfCvMO/uPbKwrz+o6yyor2rxuTP1Mq+VGV4dFZpZXfJz6GjPC9wPg0KPHA+wLS/tM/CbWFuaWZlc3TOxLz+tcTE2sjdPC9wPg0KPHByZSBjbGFzcz0="brush:java;">

2個receiver ,1個activity,1個service。

receiver用於用戶操作接收
service作為通知發送
activity前台UI

這裡要提一點的是以下部分

  

這裡應用了一個資源,我們點進去看看是什麼


    

那加了這段東西能干嗎呢?

應用程序要顯示Android的自動概覽屏幕上的通知(簡單地說就是通知用)

我們來看一下具體是怎麼操作的

先是UI(作者是activity裡面貼了個Fragment)



public class MessagingFragment extends Fragment implements View.OnClickListener {

    private static final String TAG = MessagingFragment.class.getSimpleName();

    private Button mSendSingleConversation;
    private Button mSendTwoConversations;
    private Button mSendConversationWithThreeMessages;
    private TextView mDataPortView;
    private Button mClearLogButton;

    private Messenger mService;
    private boolean mBound;

    private final ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            mService = new Messenger(service);
            mBound = true;
            setButtonsState(true);
            Log.d(TAG,"--->onServiceConnected");
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mService = null;
            mBound = false;
            setButtonsState(false);
            Log.d(TAG,"--->onServiceDisconnected");
        }
    };
//根據SharedPreference的變化來刷新UI
    private final SharedPreferences.OnSharedPreferenceChangeListener listener =
            new SharedPreferences.OnSharedPreferenceChangeListener() {
        @Override
        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
            if (MessageLogger.LOG_KEY.equals(key)) {
                mDataPortView.setText(MessageLogger.getAllMessages(getActivity()));
            }
        }
    };

    public MessagingFragment() {
    }
    //獲取控件
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_message_me, container, false);

        mSendSingleConversation = (Button) rootView.findViewById(R.id.send_1_conversation);
        mSendSingleConversation.setOnClickListener(this);

        mSendTwoConversations = (Button) rootView.findViewById(R.id.send_2_conversations);
        mSendTwoConversations.setOnClickListener(this);

        mSendConversationWithThreeMessages =
                (Button) rootView.findViewById(R.id.send_1_conversation_3_messages);
        mSendConversationWithThreeMessages.setOnClickListener(this);

        mDataPortView = (TextView) rootView.findViewById(R.id.data_port);
        mDataPortView.setMovementMethod(new ScrollingMovementMethod());

        mClearLogButton = (Button) rootView.findViewById(R.id.clear);
        mClearLogButton.setOnClickListener(this);

        setButtonsState(false);

        return rootView;
    }

    //模擬消息發送行為
    @Override
    public void onClick(View view) {
        if (view == mSendSingleConversation) {
            sendMsg(1, 1);
        } else if (view == mSendTwoConversations) {
            sendMsg(2, 1);
        } else if (view == mSendConversationWithThreeMessages) {
            sendMsg(1, 3);
        } else if (view == mClearLogButton) {
            MessageLogger.clear(getActivity());
            mDataPortView.setText(MessageLogger.getAllMessages(getActivity()));
        }
    }

    //綁定MessagingService
    @Override
    public void onStart() {
        super.onStart();
        getActivity().bindService(new Intent(getActivity(), MessagingService.class), mConnection,
                Context.BIND_AUTO_CREATE);
    }

    //注銷監聽
    @Override
    public void onPause() {
        super.onPause();
        MessageLogger.getPrefs(getActivity()).unregisterOnSharedPreferenceChangeListener(listener);
    }

//注冊監聽SharedPreference
    @Override
    public void onResume() {
        super.onResume();
        mDataPortView.setText(MessageLogger.getAllMessages(getActivity()));
        MessageLogger.getPrefs(getActivity()).registerOnSharedPreferenceChangeListener(listener);
    }

    //解綁監聽
    @Override
    public void onStop() {
        super.onStop();
        if (mBound) {
            getActivity().unbindService(mConnection);
            mBound = false;
        }
    }

    //具體發送消息,傳入2個參數,一個是通知條數,一個是通知內消息的條數
    private void sendMsg(int howManyConversations, int messagesPerConversation) {
        if (mBound) {
            Message msg = Message.obtain(null, MessagingService.MSG_SEND_NOTIFICATION,
                    howManyConversations, messagesPerConversation);
            try {
                mService.send(msg);
            } catch (RemoteException e) {
                Log.e(TAG, "Error sending a message", e);
                MessageLogger.logMessage(getActivity(), "Error occurred while sending a message.");
            }
        }
    }

    private void setButtonsState(boolean enable) {
        mSendSingleConversation.setEnabled(enable);
        mSendTwoConversations.setEnabled(enable);
        mSendConversationWithThreeMessages.setEnabled(enable);
    }
}

UI(Fragment)這邊定義了一個ServiceConnection作為連接等行為的監聽,在剛創建時就已經進行了相應的綁定,日志如下,其他就看注解吧

05-25 10:59:53.874 24203-24203/com.example.android.messagingservice D/MessagingFragment: --->onServiceConnected

用戶點擊發送某一種消息業務交由MessagingService處理

public class MessagingService extends Service {
    private static final String TAG = MessagingService.class.getSimpleName();
    private static final String EOL = "\n";
    private static final String READ_ACTION =
            "com.example.android.messagingservice.ACTION_MESSAGE_READ";
    public static final String REPLY_ACTION =
            "com.example.android.messagingservice.ACTION_MESSAGE_REPLY";
    public static final String CONVERSATION_ID = "conversation_id";
    public static final String EXTRA_REMOTE_REPLY = "extra_remote_reply";
    public static final int MSG_SEND_NOTIFICATION = 1;

    private NotificationManagerCompat mNotificationManager;

    private final Messenger mMessenger = new Messenger(new IncomingHandler(this));

    @Override
    public void onCreate() {
        Log.d(TAG, "onCreate");
        mNotificationManager = NotificationManagerCompat.from(getApplicationContext());
    }

    //初始化時,將Messenger的行為交由了Handler處理
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind");
        return mMessenger.getBinder();
    }

    // Creates an intent that will be triggered when a message is marked as read.
    private Intent getMessageReadIntent(int id) {
        return new Intent()
                .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
                .setAction(READ_ACTION)
                .putExtra(CONVERSATION_ID, id);
    }

    // Creates an Intent that will be triggered when a voice reply is received.
    private Intent getMessageReplyIntent(int conversationId) {
        return new Intent()
                .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
                .setAction(REPLY_ACTION)
                .putExtra(CONVERSATION_ID, conversationId);
    }

    //發送通知
    private void sendNotification(int howManyConversations, int messagesPerConversation) {
        Conversations.Conversation[] conversations = Conversations.getUnreadConversations(
                howManyConversations, messagesPerConversation);
        for (Conversations.Conversation conv : conversations) {
            sendNotificationForConversation(conv);
        }
    }

    //發送通知談話
    private void sendNotificationForConversation(Conversations.Conversation conversation) {
        // A pending Intent for reads
        PendingIntent readPendingIntent = PendingIntent.getBroadcast(getApplicationContext(),
                conversation.getConversationId(),
                getMessageReadIntent(conversation.getConversationId()),
                PendingIntent.FLAG_UPDATE_CURRENT);

        // Build a RemoteInput for receiving voice input in a Car Notification or text input on
        // devices that support text input (like devices on Android N and above).
        RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_REMOTE_REPLY)
                .setLabel(getString(R.string.reply))
                .build();

        // Building a Pending Intent for the reply action to trigger
        PendingIntent replyIntent = PendingIntent.getBroadcast(getApplicationContext(),
                conversation.getConversationId(),
                getMessageReplyIntent(conversation.getConversationId()),
                PendingIntent.FLAG_UPDATE_CURRENT);

        // 建立一個Android N兼容的遠程輸入啟用行為。
        NotificationCompat.Action actionReplyByRemoteInput = new NotificationCompat.Action.Builder(
                R.drawable.notification_icon, getString(R.string.reply), replyIntent)
                .addRemoteInput(remoteInput)
                .build();

        // Create the UnreadConversation and populate it with the participant name
        // read and reply intents.
        UnreadConversation.Builder unreadConvBuilder =
                new UnreadConversation.Builder(conversation.getParticipantName())
                .setLatestTimestamp(conversation.getTimestamp())
                .setReadPendingIntent(readPendingIntent)
                .setReplyAction(replyIntent, remoteInput);

        // Note: Add messages from oldest to newest to the UnreadConversation.Builder
        StringBuilder messageForNotification = new StringBuilder();
        for (Iterator messages = conversation.getMessages().iterator();
             messages.hasNext(); ) {
            String message = messages.next();
            unreadConvBuilder.addMessage(message);
            messageForNotification.append(message);
            if (messages.hasNext()) {
                messageForNotification.append(EOL);
            }
        }

        //構建NotificationCompat
        NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext())
                .setSmallIcon(R.drawable.notification_icon)
                .setLargeIcon(BitmapFactory.decodeResource(
                        getApplicationContext().getResources(), R.drawable.android_contact))
                .setContentText(messageForNotification.toString())
                .setWhen(conversation.getTimestamp())
                .setContentTitle(conversation.getParticipantName())
                .setContentIntent(readPendingIntent)
                .extend(new CarExtender()
                        .setUnreadConversation(unreadConvBuilder.build())
                        .setColor(getApplicationContext().getResources()
                                .getColor(R.color.default_color_light)))
                .addAction(actionReplyByRemoteInput);

        MessageLogger.logMessage(getApplicationContext(), "Sending notification "
                + conversation.getConversationId() + " conversation: " + conversation);


//刷新通知內容
        mNotificationManager.notify(conversation.getConversationId(), builder.build());
    }

    /**
     * 處理來自客戶端的消息。
     */
    private static class IncomingHandler extends Handler {
        private final WeakReference mReference;

        IncomingHandler(MessagingService service) {
            mReference = new WeakReference<>(service);
        }

        @Override
        public void handleMessage(Message msg) {
            MessagingService service = mReference.get();
            switch (msg.what) {
                case MSG_SEND_NOTIFICATION:
                    int howManyConversations = msg.arg1 <= 0 ? 1 : msg.arg1;
                    int messagesPerConversation = msg.arg2 <= 0 ? 1 : msg.arg2;
                    if (service != null) {
                        service.sendNotification(howManyConversations, messagesPerConversation);
                    }
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }
}

事件進行一系列的分發傳給了2個Receiver

一個是我們點擊Notification就會有回應的MessageReadReceiver

這裡很明顯一點,用戶點了就清除這一條了

 NotificationManagerCompat.from(context)
                    .cancel(conversationId);

還有個是刷新Notification以及處理可能出現的交互行為的MessageReplyReceiver

主要實現行為如下

  notificationManager.notify(conversationId, repliedNotification);

然後SP內容變化了UI就變化了,這一個環路的一圈就走完了,主要實現就是Service裡的一系列事件分發。
當然這裡只是一個規范性的Demo,你自己的項目也許並不需要定義這麼多東西,搞點內部類就好了。

總結:

讀的過程中可能有點亂,但是大家主要看明白以下幾點就好:

1 如何創建,初始化,使用一個NotificationManagerCompat

2 如何傳遞消息(Intent Messenger)

3 如何反饋行為 (各類Receiver)

當然還有Handler 以及其他一些刷新UI的方法,這裡用的SP,你也可以不用SP,特別是異步行為時。

MessagingService裡有英文注解的我就沒翻譯了,看原版的更好點(畢竟我翻譯錯了,就誤人子弟了)

如果有時間的話我會去找一下別人封裝好的Git內容,如果沒得話我找時間造輪子吧。

這一篇就講到這裡,接下來一段時間都會去看 Android N的一些官方Sample

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved