繁体   English   中英

如何从Twitter获取家庭时间轴数据

[英]how to get home timeline data from twitter

我开发了一个应用程序。在我的应用程序中,我想获取Twitter主页时间轴数据并显示listview。并且我使用了twitter4j库。我进行了很多搜索并阅读了twitter文档。在此文档中,使用了波纹管获取用户时间轴数据webservice:“ https://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=true&screen_name=twitterapi&count=2 ”。它工作正常,将显示数据。但我的要求是获取家庭时间轴数据在该文档中,他们提供了以下Web服务: https : //api.twitter.com/1.1/statuses/home_timeline.json 。这不起作用,并且不会显示家庭时间轴数据。请任何一个建议我,如何做。提前致谢

这是我的oncreate代码:这是我的职责:

import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
import com.dss.utils.UrltoValue;
import com.ibud.adapters.TweetList;
import twitter4j.Paging;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.User;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;
import twitter4j.conf.Configuration;
import twitter4j.conf.ConfigurationBuilder;
import twitter4j.json.DataObjectFactory;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.ActivityInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
import android.preference.PreferenceManager;
import android.text.Html;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

这是我的实例变量:

static String TWITTER_CONSUMER_KEY = "CjHtStxCA2toDQY6xnMwg"; // place your cosumer key here
    static String TWITTER_CONSUMER_SECRET = "jjhpODDhtl3FM26ETn7yt3Q1Wc7VdxZXequDrmwFg"; // place your consumer secret here

    // Preference Constants
    static String PREFERENCE_NAME = "twitter_oauth";
    static final String PREF_KEY_OAUTH_TOKEN = "oauth_token";
    static final String PREF_KEY_OAUTH_SECRET = "oauth_token_secret";
    static final String PREF_KEY_TWITTER_LOGIN = "isTwitterLogedIn";
    static final String TWITTER_CALLBACK_URL = "oauth://t4jsample";

    // Twitter oauth urls
    static final String URL_TWITTER_AUTH = "auth_url";
    static final String URL_TWITTER_OAUTH_VERIFIER = "oauth_verifier";
    static final String URL_TWITTER_OAUTH_TOKEN = "oauth_token";
    String username="";
    private String strResponse;
    private String[] strText;
    LinearLayout llTotal;
    ListView lvlist;
    List<Status> statuses = new ArrayList<Status>();

    // Login button
    Button btnLoginTwitter,btnLoginFaceBook,btnBack;
    // Update status button
    Button btnUpdateStatus;
    // Logout button
    Button btnLogoutTwitter;
    // EditText for update
    EditText txtUpdate;
    // lbl update
    TextView lblUpdate;
    TextView lblUserName;
    // Progress dialog
    ProgressDialog pDialog;
    // Twitter
    private static Twitter twitter;
    private static RequestToken requestToken;
    // Shared Preferences
    private static SharedPreferences mSharedPreferences;
    // Internet Connection detector
    private ConnectionDetector cd;
    AccessToken accessToken;
    // Alert Dialog Manager
    AlertDialogManager alert = new AlertDialogManager();

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

    cd = new ConnectionDetector(getApplicationContext());

    // Check if Internet present
    if (!cd.isConnectingToInternet()) {
        // Internet Connection is not present
        alert.showAlertDialog(MainActivity.this,
                "Internet Connection Error",
                "Please connect to working Internet connection", false);
        // stop executing code by return
        return;
    }

    // Check if twitter keys are set
    if (TWITTER_CONSUMER_KEY.trim().length() == 0
            || TWITTER_CONSUMER_SECRET.trim().length() == 0) {
        // Internet Connection is not present
        alert.showAlertDialog(MainActivity.this, "Twitter oAuth tokens",
                "Please set your twitter oauth tokens first!", false);
        // stop executing code by return
        return;
    }

    // All UI elements
    btnBack = (Button) findViewById(R.id.back);
    btnLoginFaceBook = (Button) findViewById(R.id.btnLoginFaceBook);
    btnLoginTwitter = (Button) findViewById(R.id.btnLoginTwitter);
    btnUpdateStatus = (Button) findViewById(R.id.btnUpdateStatus);
    btnLogoutTwitter = (Button) findViewById(R.id.btnLogoutTwitter);
    txtUpdate = (EditText) findViewById(R.id.txtUpdateStatus);
    lblUpdate = (TextView) findViewById(R.id.lblUpdate);
    lblUserName = (TextView) findViewById(R.id.lblUserName);

    // Shared Preferences
    mSharedPreferences = getApplicationContext().getSharedPreferences(
            "MyPref", 0);

    btnLoginTwitter.setOnClickListener(new View.OnClickListener() {

        public void onClick(View arg0) {

            loginToTwitter();
        }
    });
    btnBack.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {
            // Call login twitter function
            btnLogoutTwitter.setVisibility(View.GONE);
            btnUpdateStatus.setVisibility(View.GONE);
            txtUpdate.setVisibility(View.GONE);
            lblUpdate.setVisibility(View.GONE);
            lblUserName.setText("");
            lblUserName.setVisibility(View.GONE);
            btnLoginFaceBook.setVisibility(View.VISIBLE);
            btnLoginTwitter.setVisibility(View.VISIBLE);
        }
    });

    btnLoginFaceBook.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {
            // Call login twitter function
            Log.e("this is", "facebook onclick");
        }
    });

    /**
     * Button click event to Update Status, will call updateTwitterStatus()
     * function
     * */
    btnUpdateStatus.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // Call update status function
            // Get the status from EditText
            String status = txtUpdate.getText().toString();

            // Check for blank text
            if (status.trim().length() > 0) {
                // update status
                new updateTwitterStatus().execute(status);
            } else {
                // EditText is empty
                Toast.makeText(getApplicationContext(),
                        "Please    enter status message",
                        Toast.LENGTH_SHORT).show();
            }
        }
    });

    /**
     * Button click event for logout from twitter
     * */
    btnLogoutTwitter.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {
            // Call logout twitter function
            logoutFromTwitter();
        }
    });

    /**
     * This if conditions is tested once is redirected from twitter page.
     * Parse the uri to get oAuth Verifier
     * */
    if (!isTwitterLoggedInAlready()) {
        Uri uri = getIntent().getData();
        if (uri != null && uri.toString().startsWith(TWITTER_CALLBACK_URL)) {
            // oAuth verifier
            String verifier = uri
                    .getQueryParameter(URL_TWITTER_OAUTH_VERIFIER);

            try {
                // Get the access token
                accessToken = twitter.getOAuthAccessToken(requestToken,
                        verifier);

                // Shared Preferences
                Editor e = mSharedPreferences.edit();

                // After getting access token, access token secret
                // store them in application preferences
                e.putString(PREF_KEY_OAUTH_TOKEN, accessToken.getToken());
                e.putString(PREF_KEY_OAUTH_SECRET,
                        accessToken.getTokenSecret());
                // Store login status - true
                e.putBoolean(PREF_KEY_TWITTER_LOGIN, true);
                e.commit(); // save changes

                Log.e("Twitter OAuth Token", "> " + accessToken.getToken());

                // Hide login button
                btnLoginTwitter.setVisibility(View.GONE);
                btnLoginFaceBook.setVisibility(View.GONE);

                // Show Update Twitter
                lblUpdate.setVisibility(View.VISIBLE);
                txtUpdate.setVisibility(View.VISIBLE);
                btnUpdateStatus.setVisibility(View.VISIBLE);
                btnLogoutTwitter.setVisibility(View.VISIBLE);

                // Getting user details from twitter
                // For now i am getting his name only
                long userID = accessToken.getUserId();
                User user = twitter.showUser(userID);
                String username = user.getName();

                Log.e("user id:", "" + userID);
                Log.e("user name:", username);

                try {
                    ConfigurationBuilder builder = new ConfigurationBuilder();

                    Log.e("tryyyyyyyyy:", "try");

                    // TWITTER ACCESS TOKEN
                    String twit_access_token = mSharedPreferences
                            .getString(PREF_KEY_OAUTH_TOKEN, null);

                    Log.e("access token:", twit_access_token);

                    // TWITTER ACCESS TOKEN SECRET
                    String twit_access_token_secret = mSharedPreferences
                            .getString(PREF_KEY_OAUTH_SECRET, null);

                    Log.e("access token sec:", twit_access_token_secret);

                    builder.setOAuthConsumerKey(TWITTER_CONSUMER_KEY);
                    builder.setOAuthConsumerSecret(TWITTER_CONSUMER_SECRET);
                    builder.setOAuthAccessToken(twit_access_token);
                    builder.setOAuthAccessTokenSecret(twit_access_token_secret);
                    builder.setJSONStoreEnabled(true);
                    builder.setIncludeEntitiesEnabled(true);
                    // builder.setIncludeMyRetweetEnabled(true);
                    builder.setIncludeRTsEnabled(true);

                    AccessToken accessToken = new AccessToken(
                            twit_access_token, twit_access_token_secret);

                    Log.e("accesstoken:", "" + accessToken);

                    Twitter twitter = new TwitterFactory(builder.build())
                            .getInstance(accessToken);

                    Log.e("twitter:", "" + twitter);

                    Paging paging = new Paging(200); // MAX 200 IN ONE CALL.
                                                        // SET YOUR OWN
                                                        // NUMBER <= 200
                    statuses = twitter.getHomeTimeline(paging);

                    Log.e("statuses", "statuses");

                    try {

                        Log.e("tryyyyyyyyy in tryyyyyyyyyyyyyy:", "try");

                        String strInitialDataSet = DataObjectFactory
                                .getRawJSON(statuses);
                        JSONArray JATweets = new JSONArray(
                                strInitialDataSet);

                        Log.e("lengthhhhhhhhhhhh:", "" + JATweets.length());

                        for (int i = 0; i < JATweets.length(); i++) {

                            JSONObject JOTweets = JATweets.getJSONObject(i);
                            Log.e("TWEETS", JOTweets.toString());

                        }

                    } catch (Exception e1) {
                        // TODO: handle exception
                        e1.printStackTrace();
                    }
                } catch (Exception e2) {
                    // TODO: handle exception
                }

                // Displaying in xml ui
                lblUserName.setText(Html.fromHtml("<b>Welcome " + username
                        + "</b>"));

            } catch (Exception e) {
                // Check log for login errors
                Log.e("Twitter Login Error", "> " + e.getMessage());
            }
            /*
             * Intent i = new Intent(this,ShareActivity.class);
             * startActivity(i);
             */
        }
    }

}// oncreate.

private void loginToTwitter() {
    // Check if already logged in
    if (!isTwitterLoggedInAlready()) {
        ConfigurationBuilder builder = new ConfigurationBuilder();
        builder.setOAuthConsumerKey(TWITTER_CONSUMER_KEY);
        builder.setOAuthConsumerSecret(TWITTER_CONSUMER_SECRET);
        Configuration configuration = builder.build();

        TwitterFactory factory = new TwitterFactory(configuration);
        twitter = factory.getInstance();

        try {

            Log.e("clickkkkkkkkkkk:", "authoriseeeeeee");

            requestToken = twitter
                    .getOAuthRequestToken(TWITTER_CALLBACK_URL);
            this.startActivity(new Intent(Intent.ACTION_VIEW, Uri
                    .parse(requestToken.getAuthenticationURL())));
        } catch (TwitterException e) {
            e.printStackTrace();
        }
    } else {

        Log.e("elseeeeeeeeeeeee:", "elseeeeeeee");

        // user already logged into twitter
        Toast.makeText(getApplicationContext(),
                "Already Logged into twitter", Toast.LENGTH_LONG).show();
        btnLoginTwitter.setVisibility(View.GONE);
        btnLoginFaceBook.setVisibility(View.GONE);

        // Getting user details from twitter
        // For now i am getting his name only
        Uri uri = getIntent().getData();
        if (uri != null && uri.toString().startsWith(TWITTER_CALLBACK_URL)) {
            // oAuth verifier
            String verifier = uri
                    .getQueryParameter(URL_TWITTER_OAUTH_VERIFIER);

            try {
                // Get the access token
                accessToken = twitter.getOAuthAccessToken(requestToken,
                        verifier);

                // Shared Preferences
                Editor e = mSharedPreferences.edit();

                // After getting access token, access token secret
                // store them in application preferences
                e.putString(PREF_KEY_OAUTH_TOKEN, accessToken.getToken());
                e.putString(PREF_KEY_OAUTH_SECRET,
                        accessToken.getTokenSecret());
                // Store login status - true
                e.putBoolean(PREF_KEY_TWITTER_LOGIN, true);
                e.commit(); // save changes

                Log.e("Twitter OAuth Token", "> " + accessToken.getToken());

                long userID = accessToken.getUserId();
                Log.e("user id:", "" + userID);

                User user = twitter.showUser(userID);
                String username = user.getName();

                Log.e("user name:", username);

                // Hide login button
                btnLoginTwitter.setVisibility(View.GONE);

                // Displaying in xml ui
                lblUserName.setText(Html.fromHtml("<b>Welcome " + username
                        + "</b>"));
            } catch (Exception e) {
                // Check log for login errors
                Log.e("Twitter Login Error", "> " + e.getMessage());
            }

            /*
             * Intent i = new Intent(this,ShareActivity.class);
             * startActivity(i);
             */

        }

    }
}// login

这是发布推文:

class updateTwitterStatus extends AsyncTask<String, String, String> {

        /**
         * Before starting background thread Show Progress Dialog
         * */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(MainActivity.this);
            pDialog.setMessage("Updating to twitter...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(false);
            pDialog.show();
        }

        /**
         * getting Places JSON
         * */
        protected String doInBackground(String... args) {
            Log.d("Tweet Text", "> " + args[0]);

            Log.e("Tweet Text", "> " + args[0]);

            String status = args[0];
            try {
                ConfigurationBuilder builder = new ConfigurationBuilder();
                builder.setOAuthConsumerKey(TWITTER_CONSUMER_KEY);
                builder.setOAuthConsumerSecret(TWITTER_CONSUMER_SECRET);

                // Access Token 
                String access_token = mSharedPreferences.getString(PREF_KEY_OAUTH_TOKEN, "");
                // Access Token Secret
                String access_token_secret = mSharedPreferences.getString(PREF_KEY_OAUTH_SECRET, "");

                AccessToken accessToken = new AccessToken(access_token, access_token_secret);
                Twitter twitter = new TwitterFactory(builder.build()).getInstance(accessToken);

                // Update status
                twitter4j.Status response = twitter.updateStatus(status);

                Log.d("Status", "> " + response.getText());
                Log.e("Status", "> " + response.getText());

            } catch (TwitterException e) {
                // Error in updating status
                Log.d("Twitter Update Error", e.getMessage());
            }
            return null;
        }

        /**
         * After completing background task Dismiss the progress dialog and show
         * the data in UI Always use runOnUiThread(new Runnable()) to update UI
         * from background thread, otherwise you will get error
         * **/
        protected void onPostExecute(String file_url) {
            // dismiss the dialog after getting all products
            pDialog.dismiss();
            // updating UI from Background Thread
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(getApplicationContext(),"Status tweeted successfully", Toast.LENGTH_SHORT).show();
                    // Clearing EditText field
                    txtUpdate.setText("");
                }
            });

        }

    }//update.

private void logoutFromTwitter() {
        // Clear the shared preferences
        Editor e = mSharedPreferences.edit();
        e.remove(PREF_KEY_OAUTH_TOKEN);
        e.remove(PREF_KEY_OAUTH_SECRET);
        e.remove(PREF_KEY_TWITTER_LOGIN);
        e.commit();

        // After this take the appropriate action
        // I am showing the hiding/showing buttons again
        // You might not needed this code
        btnLogoutTwitter.setVisibility(View.GONE);
        btnUpdateStatus.setVisibility(View.GONE);
        txtUpdate.setVisibility(View.GONE);
        lblUpdate.setVisibility(View.GONE);
        lblUserName.setText("");
        lblUserName.setVisibility(View.GONE);
        btnLoginFaceBook.setVisibility(View.VISIBLE);
        btnLoginTwitter.setVisibility(View.VISIBLE);
    }


private boolean isTwitterLoggedInAlready() {
        // return twitter login status from Shared Preferences
        return mSharedPreferences.getBoolean(PREF_KEY_TWITTER_LOGIN, false);
    }

    protected void onResume() {
        super.onResume();
    }


    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) 
     {
        if ((keyCode == KeyEvent.KEYCODE_BACK))
        {
            //Log.e("this is","default back button..............");
            Intent intent = new Intent(Intent.ACTION_MAIN);
               intent.addCategory(Intent.CATEGORY_HOME);
               intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
               startActivity(intent);

        }
        return false;
     }

这是我的代码。请帮我做错的地方和我的xml代码:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
  android:orientation="vertical"
>

<RelativeLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    >
    <Button
        android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/back"
    android:layout_alignParentLeft="true"
    android:text="back"
        />

    </RelativeLayout>
<LinearLayout
     android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"

    >


 <Button android:id="@+id/btnLoginFaceBook"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Login with facebook"
    android:layout_marginLeft="10dip"
    android:layout_marginRight="10dip"
    android:layout_marginTop="30dip"/>

<!-- Twitter Login Button -->
<Button android:id="@+id/btnLoginTwitter"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Login with Twitter"
    android:layout_marginLeft="10dip"
    android:layout_marginRight="10dip"
    android:layout_marginTop="30dip"/>

<!-- user name label -->
<TextView android:id="@+id/lblUserName"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:padding="10dip"
    android:layout_marginTop="30dip"/>

<!-- label update status -->
<TextView android:id="@+id/lblUpdate" 
    android:text="Update Status"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="10dip"
    android:layout_marginRight="10dip"
    android:visibility="gone"/>

 <!-- Tweet EditText -->
 <EditText android:id="@+id/txtUpdateStatus"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dip"
    android:visibility="gone"/>

<!-- Tweet Button -->
<Button android:id="@+id/btnUpdateStatus"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Tweet"
    android:layout_marginLeft="10dip"
    android:layout_marginRight="10dip"
    android:visibility="gone"/>

 <!-- Twitter Logout button -->
 <Button android:id="@+id/btnLogoutTwitter"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Logout from Twitter"
    android:layout_marginLeft="10dip"
    android:layout_marginRight="10dip"
    android:layout_marginTop="50dip"
    android:visibility="gone"/>
</LinearLayout>
</LinearLayout>

使用此代码。 这是我的一个应用程序的生产代码。 我从strings.xml文件中获取了两个Strings TWITTER_CONSUMER_KEYTWITTER_CONSUMER_SECRET值。 从我的SharedPreferences文件中提取了Strings twit_access_tokentwit_access_token_secret的值。 用您自己的存储方法替换这些位。

try {
    ConfigurationBuilder builder = new ConfigurationBuilder();

    // GET THE CONSUMER KEY AND SECRET KEY FROM THE STRINGS XML
    String TWITTER_CONSUMER_KEY = getActivity().getString(R.string.TWITTER_CONSUMER_KEY);
    String TWITTER_CONSUMER_SECRET = getActivity().getString(R.string.TWITTER_CONSUMER_SECRET);

    // TWITTER ACCESS TOKEN
    String twit_access_token = twitPrefs.getString(PREF_KEY_OAUTH_TOKEN, null);

    // TWITTER ACCESS TOKEN SECRET
    String twit_access_token_secret = twitPrefs.getString(PREF_KEY_OAUTH_SECRET, null);

    builder.setOAuthConsumerKey(TWITTER_CONSUMER_KEY);
    builder.setOAuthConsumerSecret(TWITTER_CONSUMER_SECRET);
    builder.setOAuthAccessToken(twit_access_token);
    builder.setOAuthAccessTokenSecret(twit_access_token_secret);
    builder.setJSONStoreEnabled(true);
    builder.setIncludeEntitiesEnabled(true);
    builder.setIncludeMyRetweetEnabled(true);
    builder.setIncludeRTsEnabled(true);

    AccessToken accessToken = new AccessToken(twit_access_token, twit_access_token_secret);
    Twitter twitter = new TwitterFactory(builder.build()).getInstance(accessToken);

    Paging paging = new Paging(200); // MAX 200 IN ONE CALL. SET YOUR OWN NUMBER <= 200
    statuses = twitter.getHomeTimeline(paging);

    try {
        String strInitialDataSet = DataObjectFactory.getRawJSON(statuses);
        JSONArray JATweets = new JSONArray(strInitialDataSet);

        for (int i = 0; i < JATweets.length(); i++) {
                JSONObject JOTweets = JATweets.getJSONObject(i);
                Log.e("TWEETS", JOTweets.toString());
        }

    } catch (Exception e) {
        // TODO: handle exception
    }
} catch (Exception e) {
    // TODO: handle exception
}

注意1: statusesList<Status> statuses = new ArrayList<Status>();的实例List<Status> statuses = new ArrayList<Status>(); 我已经声明并实例化为全局实例。

注2:该属性是必需的builder.setJSONStoreEnabled(true); 如果您希望结果为JSON格式。 如果您需要不带JSON ,请告诉我。

最后更新:

在测试了OP的全部代码并调试了测试应用程序中的所有内容之后,罪魁祸首变成了一行(实际上是2行):

Paging paging = new Paging(200); // MAX 200 IN ONE CALL. SET YOUR OWN NUMBER <= 200
statuses = twitter.getHomeTimeline(paging);

事实证明,由于某种原因,Twitter API不喜欢Paging paging = new Paging(200); 将其更改为Paging paging = new Paging(10); 奇怪的是,给了我20条推文。 完全删除Paging....行,给了我19 结果很奇怪。 但是我目前最好的猜测是,该应用程序可能是Twitter开发人员网络上的新程序(它在身份验证期间仍显示该应用程序无法访问Direct Messages )。

将该部分更改为:

// Paging paging = new Paging(10);
statuses = twitter.getHomeTimeline();

暂无
暂无

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

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