【问题标题】:Cannot delete Shared Preference that is set in another Activity Android无法删除在另一个 Activity Android 中设置的共享首选项
【发布时间】:2021-05-25 18:45:28
【问题描述】:

我想删除在 LoginActivity 上设置的 authToken,但我不能从作为 MainActivity 一部分的 LogoutFragment 中删除。想知道我哪里可能出错了。我看到了一些关于此的线程,但似乎没有一个有效。在 LoginActivity 中,我可以轻松清除共享首选项

谢谢

package com.mpl.mpl.ui.logout;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.WebView;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;

import com.mpl.mpl.LoginActivity;
import com.mpl.mpl.databinding.FragmentLogoutBinding;
import com.mpl.mpl.ui.logout.LogoutViewModel;


public class LogoutFragment extends Fragment {

    private LogoutViewModel logoutViewModel;
    private FragmentLogoutBinding binding;
    private WebView webView;


    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        logoutViewModel =
                new ViewModelProvider(this).get(LogoutViewModel.class);

        binding = FragmentLogoutBinding.inflate(inflater, container, false);
        View root = binding.getRoot();

        CookieSyncManager cookieSyncMngr = CookieSyncManager.createInstance(getActivity());
        CookieManager cookieManager = CookieManager.getInstance();
        cookieManager.removeAllCookie();



        Intent intent = new Intent(getActivity(), LoginActivity.class);

        SharedPreferences preferences = getContext().getSharedPreferences("authToken", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = preferences.edit();
        editor.clear();
        editor.apply();

        startActivity(intent);

        return root;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }
}

登录片段:

package com.mpl.mpl.ui.login;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;

import com.loopj.android.http.JsonHttpResponseHandler;
import com.mpl.mpl.MainActivity;
import com.mpl.mpl.R;
import com.mpl.mpl.databinding.FragmentLoginBinding;
import com.mpl.mpl.restClient.MplRestClient;


import org.json.JSONException;
import org.json.JSONObject;


public class LoginFragment extends Fragment implements View.OnClickListener {

    private LoginViewModel loginViewModel;
    private FragmentLoginBinding binding;
    private WebView webView;
    private Button button;
    private Button forgottenPasswordBtn;
    private Button registerBtn;

    private EditText email;
    private EditText password;
    private EditText errorMessageField;

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        loginViewModel =
                new ViewModelProvider(this).get(LoginViewModel.class);


        binding = FragmentLoginBinding.inflate(inflater, container, false);
        View root = binding.getRoot();

        webView = (WebView) root.findViewById(R.id.loginWebView);
        webView.setWebChromeClient(new WebChromeClient());


        webView.setWebViewClient(new WebViewClient() {

            public void onPageFinished(WebView view, String url) {

                SharedPreferences pref;

                pref = getActivity().getPreferences(Context.MODE_PRIVATE);
                String token = pref.getString("authToken", null);

                if (token != null) {
                    webView.loadUrl("javascript:testFunction('" + token + "');");
                }
                try {
                    getLoginStatus();
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }

        });
        webView.loadUrl("hidden");
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);


        webView.addJavascriptInterface(new IJavascriptHandler(), "cpjs");

        password = (EditText) root.findViewById(R.id.passwordField);
        email = (EditText) root.findViewById(R.id.emailField);
        errorMessageField = (EditText) root.findViewById(R.id.statusMessage);

        button = (Button) root.findViewById(R.id.buttonTest);
        button.setOnClickListener(this);

        registerBtn = root.findViewById(R.id.registerBtn);
        registerBtn.setOnClickListener(this);

        forgottenPasswordBtn = (Button) root.findViewById(R.id.forgottenPasswordBtn);
        forgottenPasswordBtn.setOnClickListener(this);


        return root;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }


    @Override
    public void onClick(View v) {
        //do what you want to do when button is clicked
        switch (v.getId()) {
            case R.id.buttonTest:

                try {
                    getLoginStatus();
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                break;

            case R.id.forgottenPasswordBtn:
                Uri uri = Uri.parse("hidden"); // missing 'http://' will cause crashed
                Intent forgottenIntent = new Intent(Intent.ACTION_VIEW, uri);
                startActivity(forgottenIntent);
                break;

            case R.id.registerBtn:
                NavController navController = Navigation.findNavController(getActivity(), R.id.nav_host_fragment_login_content_main);
                navController.navigate(R.id.nav_register);
                break;


        }
    }


    public void getLoginStatus() throws JSONException {
        MplRestClient.post("ajax/logintest.php?eml=" + email.getText().toString() + "&pwdr=" + password.getText().toString(), null, new JsonHttpResponseHandler() {

            @SuppressLint("SetTextI18n")
            @Override
            public void onSuccess(int statusCode, cz.msebera.android.httpclient.Header[] headers, JSONObject response) {
                // If the response is JSONObject instead of expected JSONArray

                try {

                    String message = response.getString("status");

                    switch (message) {
                        case "verify":

                            errorMessageField.setText("Please Verify Your Email");
                            errorMessageField.setVisibility(View.VISIBLE);
                            break;

                        case "success":

                            String token = response.getString("token");

                            errorMessageField.setText("");
                            errorMessageField.setVisibility(View.GONE);

                            webView.loadUrl("javascript:testFunction('" + token + "');");
                            break;

                        default:
                            errorMessageField.setText("Please Check Your Details");
                            errorMessageField.setVisibility(View.VISIBLE);
                            break;
                    }


                } catch (Exception e) {
                    Toast.makeText(getActivity(), "fail",
                            Toast.LENGTH_LONG).show();
                }

            }

            @Override
            public void onFailure(int statusCode, cz.msebera.android.httpclient.Header[] headers, String responseString, Throwable throwable) {
                super.onFailure(statusCode, headers, responseString, throwable);

            }
        });
    }

    final class IJavascriptHandler {
        IJavascriptHandler() {

        }

        @JavascriptInterface
        public void sendToAndroid(String text) {

            if (text.length() > 11) {

                SharedPreferences pref = getActivity().getPreferences(Context.MODE_PRIVATE);
                SharedPreferences.Editor edt = pref.edit();
                edt.putString("authToken", text);
                edt.commit();


                pref = getActivity().getPreferences(Context.MODE_PRIVATE);
                String id = pref.getString("authToken", null);


                Intent intent = new Intent(getActivity(), MainActivity.class);
                startActivity(intent);

            }

        }
    }

}

LoginFragment 是 LoginActivity 的一部分,共享偏好设置在 IJavascriptHandler 部分

【问题讨论】:

  • 向您展示登录活动 - 它在哪里工作。您很可能以两种不同的方式访问它。
  • @dominicoder 我已经添加了设置 authToken 的 LoginFragment
  • 由于您使用的是 MODE_PRIVATE ,因此在使用 getPreferences() 时也要发送“令牌”,如here 所述。还要检查this answer
  • 是的 - 就像我想的那样。看我的回答。

标签: java android android-studio sharedpreferences


【解决方案1】:

您的问题

这是您设置首选项的方式:

SharedPreferences pref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor edt = pref.edit();
edt.putString("authToken", text);
edt.commit();

这就是你清理的方式:

SharedPreferences preferences = getContext().getSharedPreferences("authToken", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.clear();
editor.apply();

看到区别了吗?

当您使用getActivity().getPreferences(Context.MODE_PRIVATE)设置首选项时,您会将其设置为以活动命名的活动特定文件:see the documentation。

当您通过getContext().getSharedPreferences("authToken", Context.MODE_PRIVATE)获取首选项时,您正在尝试访问名为“authToken”的应用程序范围的首选项集:see the documentation。

所以你写到一个地方,从另一个地方读,所以它当然不会匹配。

解决方案

在获取和设置偏好的方式上保持一致。解决此问题的最简单方法是使用 PreferenceManager.getDefaultSharedPreferences 获取应用程序范围的首选项。

设置:

SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getActivity())
SharedPreferences.Editor edt = pref.edit();
edt.putString("authToken", text);
edt.apply();

清除:

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext())
SharedPreferences.Editor editor = preferences.edit();
editor.remove("authToken")
editor.apply();

【讨论】:

  • 这很好,很好的解释非常感谢您的帮助:)
猜你喜欢
  • 2012-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-23
  • 1970-01-01
  • 2011-04-08
  • 1970-01-01
相关资源
最近更新 更多