简体   繁体   English

在Android Oreo版本中没有收到FCM通知消息?

[英]FCM notification message are not received in android Oreo version?

I have send FCM notification from server to users. 我已经从服务器向用户发送FCM通知。 It works fine(until api 25) but in Oreo when the application have not in background(services are closed) (or) completely closed .I am not getting any FCM notifications at this scenario but in Whatsapp works fine. 它工作正常(直到api 25),但在奥利奥,当应用程序没有在后台(服务已关闭)(或)完全关闭。我没有在这种情况下获得任何FCM通知,但在Whatsapp工作正常。 here i have attached FCM code 这里我附上了FCM代码

Manifest.xml 的Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.fcm">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service
            android:name=".MyFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
            </intent-filter>
        </service>

        <meta-data
            android:name="com.google.firebase.messaging.default_notification_icon"
            android:resource="@drawable/ic_stat_ic_notification" />

        <meta-data
            android:name="com.google.firebase.messaging.default_notification_color"
            android:resource="@color/colorAccent" />

        <meta-data
            android:name="com.google.firebase.messaging.default_notification_channel_id"
            android:value="fcm"/>

        <meta-data android:name="firebase_messaging_auto_init_enabled"
            android:value="false" />

        <meta-data android:name="firebase_analytics_collection_enabled"
            android:value="false" />

    </application>

</manifest>

app/gradle 应用程序/ gradle这个

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.fcm"
        minSdkVersion 16
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation 'com.google.firebase:firebase-messaging:17.1.0'
}

apply plugin: 'com.google.gms.google-services'

MyFirebaseMessagingService.java MyFirebaseMessagingService.java

package com.fcm;

import android.app.Service;
import android.util.Log;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

public class MyFirebaseMessagingService extends FirebaseMessagingService
{

    @Override
    public void onNewToken(String s) 
    {
    super.onNewToken(s);
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
    super.onMessageReceived(remoteMessage);
    Log.e("FCM Message Received","You Have FCM Message");
    }
}

MainActivity.java MainActivity.java

package com.nexge.fcm;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.InstanceIdResult;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener( this,  new OnSuccessListener<InstanceIdResult>() {
            @Override
            public void onSuccess(InstanceIdResult instanceIdResult) {
                String newToken = instanceIdResult.getToken();
                Log.e("newToken",newToken);
            }
        });
    }
}

When you target Android 8.0 (API level 26) , you must implement one or more notification channels. 当您定位到Android 8.0(API级别26)时 ,您必须实现一个或多个通知渠道。 If your targetSdkVersion is set to 25 or lower, when your app runs on Android 8.0 (API level 26) or higher, it behaves the same as it would on devices running Android 7.1 (API level 25) or lower. 如果您的targetSdkVersion设置为25或更低,当您的应用在Android 8.0(API级别26)或更高版本上运行时,其行为与运行Android 7.1(API级别25)或更低版本的设备上的行为相同。

Note: If you target Android 8.0 (API level 26) and post a notification without specifying a notification channel, the notification does not appear and the system logs an error. 注意:如果您定位Android 8.0(API级别26)并在未指定通知通道的情况下发布通知,则不会显示通知,系统会记录错误。

Note: You can turn on a new setting in Android 8.0 (API level 26) to display an on-screen warning that appears as a toast when an app targeting Android 8.0 (API level 26) attempts to post without a notification channel. 注意:您可以在Android 8.0(API级别26)中启用新设置,以显示屏幕警告,当针对Android 8.0(API级别26)的应用尝试在没有通知渠道的情况下发布时,该警告会显示为吐司。 To turn on the setting for a development device running Android 8.0 (API level 26), navigate to Settings > Developer options and enable Show notification channel warnings. 要打开运行Android 8.0(API级别26)的开发设备的设置,请导航到“设置”>“开发人员选项”启用“显示通知通道警告”。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
   NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
   String id = "id_product";
   // The user-visible name of the channel.
   CharSequence name = "Product";
   // The user-visible description of the channel.
   String description = "Notifications regarding our products";
   int importance = NotificationManager.IMPORTANCE_MAX;
   NotificationChannel mChannel = new NotificationChannel(id, name, importance);
   // Configure the notification channel.
   mChannel.setDescription(description);
   mChannel.enableLights(true);
   // Sets the notification light color for notifications posted to this
   // channel, if the device supports this feature.
   mChannel.setLightColor(Color.RED);
   notificationManager.createNotificationChannel(mChannel);
}

Creating a Push Notification on Android Oreo 在Android Oreo上创建推送通知

To create a notification, you will use the NotificationCompat.Builder class. 要创建通知,您将使用NotificationCompat.Builder类。 The constructor which was used before took only Context as a parameter, but in Android O, the constructor looks like this – 之前使用过的构造函数只将Context作为参数,但在Android O中,构造函数看起来像这样 -

NotificationCompat.Builder(Context context, String channelId)

The following code snippet will show you how to create a notification – 以下代码段将向您展示如何创建通知 -

Intent intent1 = new Intent(getApplicationContext(), Ma

inActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 123, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(getApplicationContext(),"id_product")
       .setSmallIcon(R.drawable.flatpnicon) //your app icon
       .setBadgeIconType(R.drawable.flatpnicon) //your app icon
       .setChannelId(id)
       .setContentTitle(extras.get("nt").toString())
       .setAutoCancel(true).setContentIntent(pendingIntent)
       .setNumber(1)
       .setColor(255)
       .setContentText(extras.get("nm").toString())
       .setWhen(System.currentTimeMillis());
notificationManager.notify(1, notificationBuilder.build());

Android O gives you a few more functions to customize your notification – Android O为您提供了一些自定义通知的功能 -

setNumber() – allows you to set the number displayed in the long-press menu setChannelId() – allows you set the Channel Id explicitly if you are using the old constructor setColor() – allows a RGB value to put a color theme for your notification setBadgeIconType() – allows you to set an icon to be displayed in the long-press menu setNumber() - 允许您设置长按菜单中显示的数字setChannelId() - 允许您在使用旧构造函数setColor()时显式设置通道ID - 允许RGB值为您设置颜色主题notification setBadgeIconType() - 允许您设置要在长按菜单中显示的图标

for more info check example here 有关详细信息, 请查看示例

"Starting in Android 8.0 (API level 26), all notifications must be assigned to a channel or it will not appear." “从Android 8.0(API级别26)开始,所有通知都必须分配给频道,否则不会出现。”

Individual notifications must now be put in a specific channel. 现在必须将个别通知放入特定频道。 ( Reference ) 参考

Option 1 [simple] Change the target android version Android 7.1 (API level 25) or lower. 选项1 [简单]更改目标Android版本Android 7.1(API级别25)或更低。

compileSdkVersion 25
    defaultConfig {
        applicationId "com.fcm"
        minSdkVersion 16
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }

Option 2 If you don't want to change the target version then follow the following method 选项2如果您不想更改目标版本,请按照以下方法操作

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
     NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
     NotificationChannel nc = new NotificationChannel(“[enter your product id]”, “[Name]”,NotificationManager.IMPORTANCE_MAX);
     nc.setDescription(“[your description for the notification]”);
     nc.enableLights(true);
     nc.setLightColor(Color.GREEN);
     nm.createNotificationChannel(nc);
  }

Use following Builder constructor 使用以下Builder构造函数

NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(appContext, [id you mentioned above in constructor of NotificationChannel])

Create the notification from the Builder 从Builder创建通知

nm.notify("0", notificationBuilder.build())
  notification = new NotificationCompat.Builder(this, ANDROID_CHANNEL_ID)
                    .setSmallIcon(R.drawable.ic_small_logo)
                    .setLargeIcon(picture)
                    .setContentTitle("Title")
                    .setContentText("Body")
                    .setContentIntent(pendingIntent)
                    .setAutoCancel(true)
                    .build();
  • ANDROID_CHANNEL_ID = "CHANNEL_ID"
  • PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
  • intent = new Intent(getApplicationContext(), HomeActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

You can use below class for generating notification in lower and upper version of android(Tested from 4.2(Jelly Bean) to 8.1.1(Oreo)). 您可以使用以下类在android的较低版本和较高版本中生成通知(从4.2(Jelly Bean)到8.1.1(Oreo)测试)。

public final class NotificationHelper extends Thread {

    private Context context;
    private NotificationManager notifManager;
    private NotificationCompat.Builder notification_compact;
    private Notification.Builder notification_builder;
    private int OREO_NOTIFICATION_TYPE = 2; //setting default notificaiton type 2, as 1 is not for constant updating
    //put string channel name and id in **<>**
    private static final String CHANNEL_ONE_ID = "<Your_channel_string_ID>";
    private static final String CHANNEL_ONE_NAME = "<Your channel_String_NAME>";
    private static final String CHANNEL_TWO_ID = "<Your_channel_string_ID_TWO>";
    private static final String CHANNEL_TWO_NAME = "<Your channel_String_NAME_TWO>";
    private String title = "", message = "";


    /**
     * @param context content of activity
     * @param title   title for notification_compact
     * @param message message to show in notification_compact
     */
    public NotificationHelper(Context context, String title, String message) {
        this.context = context;
        this.title = title;
        this.message = message;
        notifManager = getManager();
    }


    @Override
    public void run() {
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
            //do stuff for oreo
            createChannels();
            postNotificationAboveV25(OREO_NOTIFICATION_TYPE, title);
        } else {
            //do stuff for other versions
            postNotificationUptoV25();
        }
    }


    //method to show notificaiton above nougat
    private void postNotificationAboveV25(int id, String title) {
        notification_builder = getNotificatonBuilder(id, title);

        if (notification_builder != null) {
            getManager().notify(id, notification_builder.build());
        }
    }


    //get pending intent to launch activity
    private PendingIntent getPendingIntent() {

        Intent startActivity = context.getPackageManager()
                .getLaunchIntentForPackage(context.getPackageName())
                .setPackage(null)
                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

        return PendingIntent.getActivity(context, 0, startActivity, 0);

//        Intent resultIntent = new Intent(context, ActionActivity.class);
//        return PendingIntent.getActivity(context, AppHelper.NOTIFICATION_ID, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    }


    //method to get notification builder above nougat
    private Notification.Builder getNotificatonBuilder(int id, String title) {
        switch (id) {
            case 1:
                return notification_builder = getNotification1(title, message);

            case 2:
                return notification_builder = getNotification2(title, message);

            default:
                return notification_builder = getNotification2(title, message);
        }
    }


    //Create the notification_compact that’ll be posted to Channel One
    //use this one if your notification is a type of push notificaiton
    //                              or
    //if you are not updating it in continues intervals like every 4 or 5 seconds(ex. Timer)
    @SuppressLint("NewApi")
    private Notification.Builder getNotification1(String title, String body) {
        return new Notification.Builder(context, CHANNEL_ONE_ID)
                .setContentTitle(title)
                .setContentText(body)
                .setSmallIcon(R.drawable.app_icon)
                .setAutoCancel(true)
                .setTicker(title + AppHelper.getMessage(R.string.started))
                .setColor(AppHelper.getColor(context, R.color.colorPrimary))
                .setContentIntent(getPendingIntent());
    }


    //Create the notification_compact that’ll be posted to Channel Two
    //use this for continues intervals or updating continuesly
    @SuppressLint("NewApi")
    private Notification.Builder getNotification2(String title, String body) {
        return new Notification.Builder(context, CHANNEL_TWO_ID)
                .setContentTitle(title)
                .setContentText(body)
                .setTicker(title + AppHelper.getMessage(R.string.started))
                .setSmallIcon(R.drawable.app_icon)
                .setAutoCancel(true)
                .setColor(AppHelper.getColor(context, R.color.colorPrimary))
                .setContentIntent(getPendingIntent());
    }


    //method to post notification upto Nougat i.e., below api level 26
    @SuppressLint("NewApi")
    private void postNotificationUptoV25() {
        notification_compact = new NotificationCompat.Builder(context);
        notification_compact.setAutoCancel(true);
        notification_compact.setSmallIcon(R.drawable.app_icon);
        notification_compact.setTicker(title + AppHelper.getMessage(R.string.started));
        notification_compact.setContentTitle(title);
        notification_compact.setContentText(message);
        notification_compact.setColor(AppHelper.getColor(context, R.color.colorPrimary));
        notification_compact.setContentIntent(getPendingIntent());
//        notification_compact.setWhen(1506067106762L);

        getManager().notify(AppHelper.NOTIFICATION_ID, notification_compact.build());
    }


    //method to update notification
    public void updateNotification(String time) {

        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
            //update above NOUGAT V25
            if (notification_builder != null) {
                notification_builder.setContentText(message + "  " + time);
                getManager().notify(AppHelper.NOTIFICATION_ID, notification_builder.build());
            }
        } else {
            //update below NOUGAT V25
            if (notification_compact != null) {
                notification_compact.setContentText(message + "  " + time);
                getManager().notify(AppHelper.NOTIFICATION_ID, notification_compact.build());
            }
        }
    }

    //method to update remainting notification
    public void updateRemainingNotification(String time) {

        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
            //update above NOUGAT V25
            if (notification_builder != null) {
                notification_builder.setContentText(time + AppHelper.getMessage(R.string.remaining));
                getManager().notify(AppHelper.NOTIFICATION_ID, notification_builder.build());
            }
        } else {
            //update below NOUGAT V25
            if (notification_compact != null) {
                notification_compact.setContentText(time + AppHelper.getMessage(R.string.remaining));
                getManager().notify(AppHelper.NOTIFICATION_ID, notification_compact.build());
            }
        }
    }


    //method to create channels which is necessary above Nougat(API - 25) i.e., at Oreo(API - 26)
    @SuppressLint("NewApi")
    private void createChannels() {

        NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ONE_ID,
                CHANNEL_ONE_NAME, notifManager.IMPORTANCE_DEFAULT);
        notificationChannel.enableLights(true);
        notificationChannel.setLightColor(Color.RED);
        notificationChannel.setShowBadge(true);
        notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
        getManager().createNotificationChannel(notificationChannel);

        NotificationChannel notificationChannel2 = new NotificationChannel(CHANNEL_TWO_ID,
                CHANNEL_TWO_NAME, notifManager.IMPORTANCE_DEFAULT);
        notificationChannel2.enableLights(false);
        notificationChannel2.enableVibration(true);
        notificationChannel2.setLightColor(Color.RED);
        notificationChannel2.setShowBadge(false);
        getManager().createNotificationChannel(notificationChannel2);

    }


    //method to get Object of Notification Manager
    private NotificationManager getManager() {
        if (notifManager == null)
            notifManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

        return notifManager;
    }


    /**
     * call this method to destroy notification
     */
    public void destroyNotification() {
        if (notifManager != null)
            notifManager.cancel(AppHelper.NOTIFICATION_ID);
    }
}

Just call this class from FCM, with context and msg. 只需使用上下文和消息来从FCM调用此类。 As its a thread class you can update the notification constantly also. 作为一个线程类,您也可以不断更新通知。

Don't forget to call destroyNotification() method, when your work ends. 当你的工作结束时,不要忘记调用destroyNotification()方法。

You can discover and make changes in it, as you like 您可以根据需要发现并进行更改

In oreo version can not add a notification without Channel so need to add following code in firebase notification Service class for oreo notification without channel can not send notification : 在oreo版本中无法在没有Channel的情况下添加通知,因此需要在firebase通知中添加以下代码,无需通道的oreo通知服务类无法发送通知:

private void sendMyNotification(String message,String title) {
    NotificationManager notificationManager =
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    Intent intent = new Intent(this, MainActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
    Uri soundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        @SuppressLint("WrongConstant")
        NotificationChannel notificationChannel=new NotificationChannel("my_notification","n_channel",NotificationManager.IMPORTANCE_MAX);
        notificationChannel.setDescription("description");
        notificationChannel.setName("Channel Name");
        notificationManager.createNotificationChannel(notificationChannel);
    }
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.listlogo)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.tlogo))
                .setContentTitle(title)
                .setContentText(message)
                .setAutoCancel(true)
                .setSound(soundUri)
                .setContentIntent(pendingIntent)
                .setDefaults(Notification.DEFAULT_ALL)
                .setPriority(NotificationManager.IMPORTANCE_MAX)
                .setOnlyAlertOnce(true)
                .setChannelId("my_notification")
                .setColor(Color.parseColor("#3F5996"));
        //.setProgress(100,50,false);
        notificationManager.notify(0, notificationBuilder.build());
}

Then you are sending notifications without data{} object in your json. 然后你在json中发送没有data{}对象的通知。 That's an old bug(?) or like supposed to work like that. 这是一个旧的错误(?)或者应该像那样工作。 If you don't have any data in your notification, then you won't trigger notifications while your app is on foreground. 如果您的通知中没有任何数据,那么当您的应用处于前台时,您将不会触发通知。

Example json: 示例json:

"notification":
{
  "title": "notification_title",
  "body": "notification_body"
},

"data":
{
  "example":"hey",
  "example2":"you need me."
},

"priority" : "high",

"registration_ids":
[
  "crYjxvFkASE:APA91bGv4GWj9erJ6LsblEzpag5ObkcESEsBthxsJObJ38DhZ3GbSMLlGQK3qS_qvUvrcrg_cqBgCWhBeq1X2wgxO7gmcc_gW0jM4qZYYugF5wraTHwvDKNnjQwn8dpyGEbFMXLOCvE9"
]

only data notifications is handled on android Oreo 只有数据通知在android Oreo上处理

try to remove the notification 尝试删除通知

`
 remove this key notification 
 {"notification":
 {
  "title": "notification_title",
  "body": "notification_body"
 },
 // keep only the data key 
  "data":
 {
  "example":"hey",
  "example2":"you need me."
 },

 "priority" : "high",

 "registration_ids":
    []


`

when the app is in background .. the onRecievedMessage will not called if the payload is contains both notification key and data key .. 当应用程序处于后台时...如果有效负载包含通知密钥和数据密钥,则不会调用onRecievedMessage。

so remove the notification .. and only keep the data key .. and it will work well 所以删除通知..只保留数据密钥..它将运作良好

private void generateNotification(String message, String title) {

    Intent intent = new Intent(getApplicationContext(), ActitivtyNotification.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
    NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

    Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
            .setSmallIcon(R.drawable.stkfood_logo)  //a resource for your custom small icon
            .setContentTitle(title) //the "title" value you sent in your notification
            .setContentText(message) //ditto
            .setAutoCancel(true)  //dismisses the notification on click
            .setSound(defaultSoundUri);

    //Setting up Notification channels for android O and above
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        int importance = NotificationManager.IMPORTANCE_HIGH;
        NotificationChannel notificationChannel = new NotificationChannel("3", "CHANNEL_NAME", importance);
        notificationChannel.enableLights(true);
        notificationChannel.setLightColor(Color.RED);
        notificationChannel.enableVibration(true);
        notificationChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
        assert mNotificationManager != null;
        notificationBuilder.setChannelId("3");
        mNotificationManager.createNotificationChannel(notificationChannel);
    }
    PendingIntent contentIntent = PendingIntent.getActivity(this, 3, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    notificationBuilder.setContentIntent(contentIntent);
    mNotificationManager.notify(3, notificationBuilder.build());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM