Android--搶紅包神器 輔助功能Accessibility 最新適配

新鮮出爐的搶紅包神器

前提:實(shí)現(xiàn)一個微信自動搶紅包并不是很難胯甩,原理就是利用android的輔助功能,監(jiān)聽一下窗口變化堪嫂,找到對應(yīng)控件ID偎箫,模擬點(diǎn)擊。寫好一個service服務(wù)類即可完成皆串。但上手會發(fā)現(xiàn)這其中還是有很多問題的淹办,所以我們主要是適配版本解決問題。

一恶复、問題

關(guān)于搶紅包神器的文章也很多怜森,但使用起來效果卻不佳速挑,總結(jié)一下會有以下幾個問題 (看看是不是就是你們遇到的問題):

  • 1. 紅包來源

大多數(shù)搶紅包神器只適配了從通知欄進(jìn)入的紅包 也就是微信在后臺 此時來了紅包,監(jiān)聽通知欄副硅,然后點(diǎn)進(jìn)去【搶】姥宝。但是事實(shí)上我認(rèn)為還需要適配兩個場景,一個是在聊天列表頁來紅包恐疲,一個是在好友會話頁面來了紅包腊满。

  • 2. 微信版本更新,搶紅包神器紅能就不能用了

這個就是需要各個版本進(jìn)行適配 因?yàn)槲⑿琶扛掳姹九嗉海總€控件的id會發(fā)生變化碳蛋,類名有時候甚至都會混淆,改變省咨。所以當(dāng)類名肃弟、id名稱發(fā)生改變時,程序找id為null零蓉,也就沒有辦法繼續(xù)操作點(diǎn)擊笤受,從而導(dǎo)致?lián)尲t包神器功能失效。

  • 3. 卡在【拆】的頁面不繼續(xù)

關(guān)于這個問題有以下發(fā)生的可能壁公,第一種就是【拆】這個button的id發(fā)生了變化感论,第二種是手機(jī)版本大于21,在搶紅包這個頁面可能存在window嵌套紊册,不能單單在getRootInActiveWindow 查找比肄,需要對21前和21后的版本進(jìn)行適配。親測有效囊陡。

二芳绩、解決方案

  • 1. 紅包來源問題

若想實(shí)現(xiàn)在聊天列表頁和好友會話頁面的紅包監(jiān)聽,需要我們監(jiān)聽窗口內(nèi)容變化撞反,也就是AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED妥色,當(dāng)監(jiān)聽到窗口內(nèi)容變化時做相應(yīng)的處理。

  • 2. 適配微信版本

本地適配遏片,存放在一個靜態(tài) map中 key存放微信版本 value存放一個需要適配的id合集對象嘹害。然后在服務(wù)開始前判斷當(dāng)前手機(jī)安裝微信版本,然后去本地map中取出相應(yīng)的id合集吮便。這樣使用map存儲版本號以及需要適配的id值來做兼容笔呀。或是直接適配最新的版本髓需,用戶版本過低许师,提示升級。

  • 3.拆紅包

手機(jī)版本21前后做適配

三、了解android輔助功能Accessibility

AccessibilityServiceInfo
AccessibilityService
AccessibilityManager
AccessibilityEvent
Build accessibility services

AccessibilityService

AccessibilityServiceInfo

AccessibiliyEvent

AccessibilityManager

四微渠、需要適配的對象(id名稱搭幻、class名稱等)

我們把需要適配的對象起名為WxChatTag 云控更新(構(gòu)建json)或本地靜態(tài)map存儲。

public static class WxChatTag implements Serializable {
        //4個Activity名字
        private String ChatListClassName;//聊天列表頁
        private String ConversationClassName;//會話頁面
        private String PopOpenRedPacketClassName;//彈出開紅包的頁面
        private String MoneyDetailClassName;//紅包領(lǐng)取詳情頁面
        //id
        private String OpenRedPacketButtonId;//拆紅包的id
        private String MoneyDetailTextId;//紅包詳情頁的錢數(shù)id
        //會話詳情頁
        private String ConversationPageListViewId;//會話頁面的listview的id
        private String ConversationPageRedPacketItemId;//會話頁面紅包View的id
        private String ConversationPageRecentMsgId;//會話頁面最新消息的id

        //聊天記錄列表頁面
        private String ChatListPageItemId;//聊天列表頁面Item的id
        private String ChatListPageRedHintId;//聊天列表頁紅色圓點(diǎn)提示view的id
        private String ChatListPageKeyTextId;//聊天列表頁新消息信息text的id

        private String KeySearchName;//會話列表頁面查找紅包的關(guān)鍵詞 領(lǐng)取紅包
//getter setter
}

關(guān)于class name名字獲取的技巧 【adb命令】

adb shell dumpsys activity | grep "mFocusedActivity" 打印棧頂當(dāng)前activity

關(guān)于id對應(yīng)情況如下圖示

MoneyDetailTextId

ConversationPageRedPacketItemId

ConversationPageListViewId

ConversationPageRecentMsgId

OpenRedPacketButtonId

ChatListPageItemId;

ChatListPageKeyTextId

ChatListPageRedHintId

五逞盆、簡易流程圖

以下為我的搶紅包神器的主要流程圖 大家作為參考檀蹋。

為了適配微信版本,首先要判斷當(dāng)前用戶的微信版本和你適配的微信版本是否相同纳击。然后進(jìn)行自定義操作续扔。你可以本地map存儲取值,也可以動態(tài)適配焕数,網(wǎng)絡(luò)請求纱昧。

監(jiān)聽onAccessibilityEvent

監(jiān)聽通知欄

監(jiān)聽到通知欄的后續(xù)操作

監(jiān)聽到窗口變化
首先判斷當(dāng)前activity 一共有四個activity窗口需要我們做處理,其他不做處理堡赔。

監(jiān)聽窗口變化

監(jiān)聽內(nèi)容變化
這一部的主要目的就是實(shí)現(xiàn)在聊天列表頁和好友會話頁面的紅包監(jiān)聽识脆。

監(jiān)聽內(nèi)容變化

六、主要代碼

public class MyWxQhbService extends AccessibilityService {

    /**
     * 微信的包名
     */
    public static final String PACKAGE_NAME = "com.tencent.mm";

    /**
     * 紅包消息的關(guān)鍵字
     */
    private static final String KEY = "[微信紅包]";

    private static final int APP_STATE_BACKGROUND = -1;
    private static final int APP_STATE_FOREGROUND = 1;

    private static final int WINDOW_LAUNCHER_UI = 1; // ChatListClassName
    private static final int WINDOW_LUCKY_MONEY_OPEN = 2; // PopOpenRedPacketClassName
    private static final int WINDOW_LUCKY_MONEY_DETAILUI = 3; // MoneyDetailClassName
    private static final int WINDOW_OTHER = -1;

    private static final int SILENCE_TIME = 1300;

    private int mAppState = APP_STATE_FOREGROUND;
    private int mCurrentWindow = WINDOW_OTHER;
    private boolean isSilence; // 沉默, 防止沒搶到紅包而反復(fù)點(diǎn)

    private static String ChatListClassName = "com.tencent.mm.ui.LauncherUI"; // 聊天列表頁
    private static String ConversationClassName = "com.tencent.mm.ui.LauncherUI"; //會話頁面
    private static String PopOpenRedPacketClassName = "com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI"; //彈出開紅包的頁面
    private static String MoneyDetailClassName = "com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI"; // 紅包領(lǐng)取詳情頁面


    private static String OpenRedPacketButtonId = "com.tencent.mm:id/cnu"; //  拆紅包頁面 '開'的id
    private static String MoneyDetailTextId = "com.tencent.mm:id/cnu";//紅包詳情頁 錢數(shù)id


    private static String ChatListPageItemId = "com.tencent.mm:id/azj"; // 聊天列表頁面Item的id
    private static String ChatListPageRedHintId = "com.tencent.mm:id/lu"; // 聊天列表頁紅色圓點(diǎn)提示view的id
    private static String ChatListPageKeyTextId = "com.tencent.mm:id/azn"; // 聊天記錄列表中Item關(guān)鍵詞的id

    private static String ConversationPageListViewId = "com.tencent.mm:id/ahf"; // 會話頁面的listview的id
    private static String ConversationPageRedPacketItemId = "com.tencent.mm:id/aku"; // 會話頁面紅包View的id
    private static String ConversationPageRecentMsgId = "com.tencent.mm:id/a5"; // 會話頁面最新一條信息的id

    private static String KeySearchName = "領(lǐng)取紅包";//會話頁面關(guān)鍵字搜索


    private PackageInfo mWeChatPackageInfo;
    private Intent intent = new Intent("com.wx.qhb.receiver");


    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        Log.d("qhb", "onServiceConnected");

        updateConfig();
    }

    /**
     * 更新可變id善已、class的Config
     */
    private void updateConfig() {
        Log.d("qhb", "updateConfig");
        //獲取微信包信息
        mWeChatPackageInfo = PackageUtils.getPackageInfo(getApplicationContext(), "com.tencent.mm");
        final int versionCode = mWeChatPackageInfo.versionCode;
        Log.d("qhb", "微信:versionCode:" + versionCode);
        if (versionCode == 1360) {
            return;
        } else {
            Log.d("qhb", "versionCode>1360");
            //網(wǎng)絡(luò)請求
            ConfigHelper.getConfig(getApplicationContext(), new ConfigHelper.RequestConfigCallBack() {
                @Override
                public void onRequestFailed() {
                    Toast.makeText(getApplicationContext(), "網(wǎng)絡(luò)錯誤,啟動工具失敗", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onSuccess(ConfigBean.Config config) {
                    if (config != null) {
                        boolean isInit = false;
                        List<ConfigBean.WeChatVersionConfig> weChatVersionConfigs = config.getWeChatVersionConfigs();
                        for (ConfigBean.WeChatVersionConfig weChatVersionConfig : weChatVersionConfigs) {
                            if (weChatVersionConfig.getWeChatVersionCode() == versionCode) {
                                isInit = true;
                                initField(weChatVersionConfig.getWxChatTag());
                            }
                        }
                        if (!isInit) {
                            //說明沒有適配該微信版本
                            Log.d("qhb", "發(fā)送廣播");
                            sendBroadcast(intent);
                        }

                    }

                }
            });
        }


    }

    /**
     * 賦值config
     *
     * @param mWxChatTag
     */
    private void initField(ConfigBean.WxChatTag mWxChatTag) {
        Log.d("qhb", "initField");
        if (mWxChatTag == null) {
            return;
        }
        ChatListClassName = mWxChatTag.getChatListClassName();
        ConversationClassName = mWxChatTag.getConversationClassName();
        PopOpenRedPacketClassName = mWxChatTag.getPopOpenRedPacketClassName();
        MoneyDetailClassName = mWxChatTag.getMoneyDetailClassName();


        OpenRedPacketButtonId = mWxChatTag.getOpenRedPacketButtonId();
        MoneyDetailTextId = mWxChatTag.getMoneyDetailTextId();


        ChatListPageItemId = mWxChatTag.getChatListPageItemId();
        ChatListPageRedHintId = mWxChatTag.getChatListPageRedHintId();
        ChatListPageKeyTextId = mWxChatTag.getChatListPageKeyTextId();

        ConversationPageListViewId = mWxChatTag.getConversationPageListViewId();
        ConversationPageRecentMsgId = mWxChatTag.getConversationPageRecentMsgId();
        ConversationPageRedPacketItemId = mWxChatTag.getConversationPageRedPacketItemId();

        KeySearchName = mWxChatTag.getKeySearchName();
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        switch (event.getEventType()) {
            case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED: // 通知欄狀態(tài)變化
                notificationEvent(event);
                break;
            case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: // 窗口狀態(tài)變化
                windowStateEvent(event);
                break;
            case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:  // 窗口內(nèi)容變化
                windowContentEvent(event);
                break;
            default:
                break;
        }
    }

    /**
     * 微信是否運(yùn)行在前臺
     */
    private boolean isRunningForeground(Context context) {
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
        if (!tasks.isEmpty()) {
            String packageName = tasks.get(0).topActivity.getPackageName();
            if (PACKAGE_NAME.equals(packageName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 處理通知欄事件
     */
    private void notificationEvent(AccessibilityEvent event) {
        Log.d("qhb", "通知欄事件");
        if (!isRunningForeground(getApplicationContext())) {
            mAppState = APP_STATE_BACKGROUND;
        } else {
            mAppState = APP_STATE_FOREGROUND;
        }

        Parcelable data = event.getParcelableData();
        if (data == null || !(data instanceof Notification)) {
            return;
        }

        List<CharSequence> texts = event.getText();
        if (!texts.isEmpty()) {
            String text = String.valueOf(texts.get(0));
            int index = text.lastIndexOf(":");
            if (index != -1) {
                text = text.substring(index + 1);
            }
            if (text.contains(KEY)) {
//                isHasRedPacket = true;
                Notification nf = (Notification) data;
                PendingIntent pendingIntent = nf.contentIntent;
                if (NotifyUtils.isLockScreen(getApplicationContext())) {  // 是否為鎖屏或黑屏狀態(tài)
                    if (SpUtils.isLockScreenAutomaticGrab()) {
                        NotifyUtils.wakeAndUnlock(getApplicationContext());
                        NotifyUtils.send(pendingIntent); // 打開微信
                    } else {
                        NotifyUtils.showNotify(getApplicationContext(), String.valueOf(nf.tickerText), pendingIntent); // 顯示有紅包通知
                    }
                } else {
                    NotifyUtils.send(pendingIntent); // 打開微信
                }

                // 播放聲音和震動
                NotifyUtils.playEffect(getApplicationContext());
            }
        }
    }

    /**
     * 窗口狀態(tài)變化
     */
    private void windowStateEvent(AccessibilityEvent event) {
//        Log.d("qhb", "窗口狀態(tài)變化");
        CharSequence className = event.getClassName();
        if (className == null) {
            return;
        }
        String name = className.toString();

        if (className.equals(ChatListClassName)) {
            mCurrentWindow = WINDOW_LAUNCHER_UI;
        } else if (className.equals(ConversationClassName)) {
            mCurrentWindow = WINDOW_LAUNCHER_UI;
        } else if (className.equals(PopOpenRedPacketClassName)) {
            mCurrentWindow = WINDOW_LUCKY_MONEY_OPEN;
        } else if (className.equals(MoneyDetailClassName)) {
            mCurrentWindow = WINDOW_LUCKY_MONEY_DETAILUI;
        } else {
            mCurrentWindow = WINDOW_OTHER;

        }

        switch (mCurrentWindow) {
            case WINDOW_LAUNCHER_UI:
                clickRedPackets(); // 在聊天界面, 去點(diǎn)中紅包
                break;
            case WINDOW_LUCKY_MONEY_OPEN:
                getLuckyMoney();
                break;
            case WINDOW_LUCKY_MONEY_DETAILUI:
                detailsRedPacket(); //看詳細(xì)的紀(jì)錄界面
                break;
        }


    }

    /**
     * 窗口內(nèi)容變化
     */
    private void windowContentEvent(AccessibilityEvent event) {
        Log.d("qhb", "窗口內(nèi)容變化");
        if (mCurrentWindow != WINDOW_LAUNCHER_UI) { // //不在聊天界面或聊天列表灼捂,不處理
            return;
        }

        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if (nodeInfo == null) {
            return;
        }

        // 直接去獲取當(dāng)前會話的最后一條Item, 不為null, 則是當(dāng)前會話列表
        AccessibilityNodeInfo item = AccessibilityUtils.findNodeInfosByIdLast(nodeInfo, ConversationPageRecentMsgId);
        if (item != null) {
            if (isSilence) { // 沉默中, return
                return;
            }
            clickLastMsg(nodeInfo);
            return;
        }

        // 直接去獲取聊天記錄的第一條Item, 不為null, 則是聊天記錄列表
        item = AccessibilityUtils.findNodeInfosById(nodeInfo, ChatListPageItemId); //第一條消息
        if (item != null) {
            AccessibilityNodeInfo red = AccessibilityUtils.findNodeInfosById(item, ChatListPageRedHintId);
            if (red != null) { // 有小圓點(diǎn), 說明有未讀消息
                AccessibilityNodeInfo label = AccessibilityUtils.findNodeInfosById(item, ChatListPageKeyTextId);
                if (label != null) {
                    String text = String.valueOf(label.getText());
                    Log.d("qhb", "列表頁" + label.getText());
                    int index = text.lastIndexOf(":");
                    if (index != -1) {
                        text = text.substring(index + 1);
                    }
                    if (text.contains(KEY)) {
//                        isHasRedPacket = true;
                        // 有紅包, 點(diǎn)開item
                        AccessibilityUtils.performClick(label);
                    }
                }
            }
            return;
        }
    }

    private void clickRedPackets() {

        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if (nodeInfo == null) {
            return;
        }
        //分兩種情況1.在聊天列表頁
        //2.在聊天會話頁
        //這兩個頁面的名稱都是com.tencent.mm.ui.LauncherUI這個名字
        AccessibilityNodeInfo listNode = AccessibilityUtils.findNodeInfosByTexts(nodeInfo, KEY);
        if (listNode != null) {
            Log.d("qhb", "聊天列表的微信紅包的node" + "不為空");
            AccessibilityUtils.performClick(listNode.getParent().getParent().getParent().getParent());
            return;
        } else {
            Log.d("qhb", "聊天列表的微信紅包的node" + "為空");
        }
        // 聊天會話窗口,遍歷節(jié)點(diǎn)匹配
        AccessibilityNodeInfo node = AccessibilityUtils.findNodeInfosByText(nodeInfo, KeySearchName);
        if (node != null) {
            Log.d("qhb", "會話頁領(lǐng)取紅包的node" + "不為空");
            AccessibilityUtils.performClick(node);
        } else {
            Log.d("qhb", "會話頁領(lǐng)取紅包的node" + "為空");
            return;
        }

    }


    /**
     * 點(diǎn)最新消息
     */
    private void clickLastMsg(AccessibilityNodeInfo nodeInfo) {
        AccessibilityNodeInfo listView = AccessibilityUtils.findNodeInfosById(nodeInfo, ConversationPageListViewId); //找到聊天會話頁面的會話內(nèi)容的listview
        if (listView == null) {
            return;
        }

        if (mWeChatPackageInfo.versionCode >= 1360 && listView.getChildCount() > 0) {
            listView = listView.getChild(0);
        }

        int childCount = listView.getChildCount();
        if (childCount <= 0) {
            return;
        }
        AccessibilityNodeInfo item = listView.getChild(childCount - 1);
        if (item != null) { // 每一條新消息都試著點(diǎn)紅包
            AccessibilityNodeInfo real = AccessibilityUtils.findNodeInfosById(item, ConversationPageRedPacketItemId);
            if (real != null) { // 真紅包

                // 新版本后, 1100(包括)以上, 能判斷紅包是否已經(jīng)領(lǐng)取
                if (mWeChatPackageInfo.versionCode >= 1100) {
                    AccessibilityNodeInfo realToo = AccessibilityUtils.findNodeInfosByText(real, KeySearchName);
                    if (realToo == null) {
                        return;
                    }
                }
                AccessibilityUtils.performClick(real);
            }

        }
        return;
    }

    /**
     * 搶紅包
     */
    private void getLuckyMoney() {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            List<AccessibilityWindowInfo> nodeInfos = getWindows();
            for (AccessibilityWindowInfo window : nodeInfos) {
                AccessibilityNodeInfo nodeInfo = window.getRoot();
                if (nodeInfo == null) {
                    break;
                }
                List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId(OpenRedPacketButtonId);
                if (list != null && list.size() > 0) {
                    AccessibilityUtils.performOpenRedPacketWithDelay(list.get(0));
                    return;
                }
            }
        }

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
            AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();  //獲得整個窗口對象
            if (nodeInfo == null) {
                return;
            }

            List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId(OpenRedPacketButtonId);
            if (list != null && list.size() > 0) {
                AccessibilityUtils.performOpenRedPacketWithDelay(list.get(0));
                return;
            }

            //如果沒找到拆紅包的button换团,則將界面上所有子節(jié)點(diǎn)都點(diǎn)擊一次
            for (int i = nodeInfo.getChildCount() - 1; i >= 0; i--) {
                if (("android.widget.Button").equals(nodeInfo.getChild(i).getClassName())) {
                    AccessibilityUtils.performOpenRedPacketWithDelay(nodeInfo.getChild(i));
                    return;
                }
            }
//            Toast.makeText(this, "未找到開紅包按鈕", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 領(lǐng)取詳情
     */
    private void detailsRedPacket() {
        // 到這, 領(lǐng)取流程算是完了
        Log.d("qhb", "領(lǐng)取流程完事");

        List<AccessibilityNodeInfo> moneyNode = getRootInActiveWindow().findAccessibilityNodeInfosByViewId(MoneyDetailTextId);
        if (moneyNode != null && moneyNode.size() > 0) {
            String moneyStr = moneyNode.get(0).getText().toString();
            float money = Float.parseFloat(moneyStr);
            SpUtils.put("totalNum", SpUtils.get("totalNum", 0) + 1);
            SpUtils.put("totalMoney", SpUtils.get("totalMoney", 0f) + money);
        }
        back();

    }

    /**
     * 返回
     */
    private void back() {
        back(-1);
    }

    /**
     * 返回
     */
    private void back(int count) {
        Log.d("qhb", "back:" + count);
        silence(); // 沉默

        int backCount;
        if (mAppState == APP_STATE_BACKGROUND) {
            mAppState = APP_STATE_FOREGROUND;
            backCount = 3;
        } else {
            backCount = 1;
        }

        if (count != -1) {
            backCount = count;
        }

        for (int i = 0; i < backCount; i++) {
            AccessibilityUtils.performBack(this);
            if (i < backCount - 1) {
                SystemClock.sleep(666);// 需要個時間差
            }
        }
    }

    /**
     * 沉默
     */
    private void silence() {
        isSilence = true; // 開啟沉默
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                isSilence = false;
            }
        }, SILENCE_TIME);
    }


    @Override
    public void onInterrupt() {
        Log.d("qhb", "onInterrupt 搶紅包服務(wù)中斷");
    }

}

七悉稠、效果圖

開啟.gif
通知欄的紅包.gif
聊天列表頁來了紅包.gif

會話頁的紅包.gif

八、apk體驗(yàn)鏈接

apk體驗(yàn)鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末艘包,一起剝皮案震驚了整個濱河市的猛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌想虎,老刑警劉巖卦尊,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異舌厨,居然都是意外死亡岂却,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進(jìn)店門裙椭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來躏哩,“玉大人,你說我怎么就攤上這事揉燃≌鹜ィ” “怎么了?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵你雌,是天一觀的道長。 經(jīng)常有香客問我,道長婿崭,這世上最難降的妖魔是什么拨拓? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮氓栈,結(jié)果婚禮上渣磷,老公的妹妹穿的比我還像新娘。我一直安慰自己授瘦,他們只是感情好醋界,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著提完,像睡著了一般形纺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上徒欣,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天逐样,我揣著相機(jī)與錄音,去河邊找鬼打肝。 笑死脂新,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的粗梭。 我是一名探鬼主播争便,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼断医!你這毒婦竟也來了滞乙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤孩锡,失蹤者是張志新(化名)和其女友劉穎酷宵,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體躬窜,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡浇垦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了荣挨。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片男韧。...
    茶點(diǎn)故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖默垄,靈堂內(nèi)的尸體忽然破棺而出此虑,到底是詐尸還是另有隱情,我是刑警寧澤口锭,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布朦前,位于F島的核電站介杆,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏韭寸。R本人自食惡果不足惜春哨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望恩伺。 院中可真熱鬧赴背,春花似錦、人聲如沸晶渠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽褒脯。三九已至便瑟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間憨颠,已是汗流浹背胳徽。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留爽彤,地道東北人养盗。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像适篙,于是被迫代替她去往敵國和親往核。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內(nèi)容

  • 生命其實(shí)很短嚷节,只有兩天 一天用來出生聂儒,而一天用來死亡 它們相遇的一刻,也就有了生死存亡 只是生命一開始硫痰,就有了區(qū)別...
    周延龍閱讀 262評論 0 1
  • 01 孔子曰:吾十有五而志于學(xué)效斑。15歲非春,這個年齡節(jié)點(diǎn)很有意思,按照當(dāng)前的教育階段缓屠,是一個孩子從初中畢業(yè)進(jìn)入高中之際...
    04b12f4ce9fd閱讀 595評論 0 2