【问题标题】:Starting a Service From the Alarm Manager (no empty constructor)从警报管理器启动服务(无空构造函数)
【发布时间】:2015-09-15 02:39:33
【问题描述】:

我在我的WebviewActivity 中实现了一个警报管理器,它应该在仪表板Fragment 中每 15 分钟后调用一次Service。当我尝试运行应用程序时,出现以下 Logcat 错误。

Logcat

09-15 04:34:35.250  21867-21867/com.example.s210121629.myhealth E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.example.s210121629.myhealth, PID: 21867
    java.lang.RuntimeException: Unable to instantiate service com.example.s210121629.myhealth.dashboard.DashboardActivity$MyService: java.lang.InstantiationException: can't instantiate class com.example.s210121629.myhealth.dashboard.DashboardActivity$MyService; no empty constructor
            at android.app.ActivityThread.handleCreateService(ActivityThread.java:2786)
            at android.app.ActivityThread.access$1900(ActivityThread.java:172)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1384)
            at android.os.Handler.dispatchMessage(Handler.java:102)

WebviewActivity

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.oauth_activity);
        ButterKnife.inject(this);
        pref = getSharedPreferences("AppPref", MODE_PRIVATE);
        myself = this;

        //TODO: Alarmmanager
        _oauth_signin = (Button) findViewById(R.id.oauth_signin);
        _refresh = (Button) findViewById(R.id.refresh);
        BASE64Encoder encoder = new BASE64Encoder();
        concatinate = CLIENT_ID + ":" + CLIENT_SECRET;
        concate = encoder.encode(concatinate.getBytes());
        mdbhelper = new DBHelper(getApplicationContext());

        _oauth_signin.setOnClickListener(new View.OnClickListener() {
            Dialog auth_dialog;

            @Override
            public void onClick(View v) {


                //TODO : Pop-up dialog to be displayed with Oauth2.0
                auth_dialog = new Dialog(WebViewActivity.this);
                auth_dialog.setContentView(R.layout.webview);
                _webview = (WebView) auth_dialog.findViewById(R.id.webView);
                _webview.getSettings().setJavaScriptEnabled(true);
                _webview.loadUrl(OAUTH_URL + "?response_type=" + RESPONSE_TYPE + "&client_id=" + CLIENT_ID + "&redirect_uri=" + REDIRECT_URI + "&scope=" + SCOPE + "&expires_in=" + EXPIRES_IN);
                _webview.setWebViewClient(new WebViewClient() {

                    boolean authComplete = false;
                    Intent resultIntent = new Intent();

                    @Override
                    public void onPageStarted(WebView view, String url, Bitmap favicon) {
                        super.onPageStarted(view, url, favicon);
                    }


                    @Override
                    public void onPageFinished(WebView view, String url) {
                        super.onPageFinished(view, url);

                        if (url.contains("?code=") && authComplete != true) {
                            Uri uri = Uri.parse(url);
                            authCode = uri.getQueryParameter("code");
                            Log.i("", "CODE : " + authCode);
                            authComplete = true;
                            resultIntent.putExtra("code", authCode);
                            WebViewActivity.this.setResult(Activity.RESULT_OK, resultIntent);
                            setResult(Activity.RESULT_CANCELED, resultIntent);
                            SharedPreferences.Editor edit = pref.edit();
                            edit.putString("Code", authCode);
                            edit.commit();
                            auth_dialog.dismiss();
                            new TokenGet().execute();
                            Toast.makeText(getApplicationContext(), "Authorization Code is: " + authCode, Toast.LENGTH_SHORT).show();
                            //        new RequestAccess().execute();
                        } else if (url.contains("error=access_denied")) {
                            Log.i("", "ACCESS_DENIED_HERE");
                            resultIntent.putExtra("code", authCode);
                            authComplete = true;
                            setResult(Activity.RESULT_CANCELED, resultIntent);
                            Toast.makeText(getApplicationContext(), "Error Occurred", Toast.LENGTH_SHORT).show();
                            auth_dialog.dismiss();
                        }
                    }

                });

                auth_dialog.setTitle("Authorize myHealth");
                auth_dialog.setCancelable(true);
                auth_dialog.show();
            }
        });
        AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(this, DashboardActivity.MyService.class);
      //  intent.setAction(MyReceiver.ACTION_ALARM_RECEIVER);//my custom string action name
        PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);//used unique ID as 1001
        long start = System.currentTimeMillis() + TimeUnit.MINUTES.toMinutes(2);
        long next =  TimeUnit.MINUTES.toMinutes(5);
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, start, AlarmManager.INTERVAL_FIFTEEN_MINUTES, pendingIntent);//first start will start

仪表板片段

public class **MyService** extends Service{
    public MyService() {
        super();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
      new refresh().execute();

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}
private class refresh extends AsyncTask<String, String, JSONObject> {
    @Override
    protected JSONObject doInBackground(String... params) {
        RefreshToken jParser = new RefreshToken();
        JSONObject json = jParser.refreshToken(TOKEN_URL, concate + "=", GRANT_TYPE_REFRESH_TOKEN, refreshToken);
        return json;
    }

    @Override
    protected void onPostExecute(JSONObject jsonObject) {

        if (jsonObject != null) {

            try {

                newAccess = jsonObject.getString("access_token");
                newRefresh = jsonObject.getString("refresh_token");


                Log.d("Refresh", newRefresh);

                mdbhelper.updateToken(newAccess, newRefresh, concate);
                Toast.makeText(getActivity(), "Token Updated", Toast.LENGTH_SHORT).show();
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        } else {
            Toast.makeText(getActivity(), "Network Error", Toast.LENGTH_SHORT).show();

        }
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }
}

清单

  <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.wake_lock" />
    <service
        android:name=".dashboard.DashboardActivity$MyService"
        android:enabled="true"></service>

MyService 类是DashboardActivity 中的一个内部类,因为我想访问DashboardFragment 中的网络调用方法。 Myservice 类内部确实有一个构造函数。如果我将 Myservice 设为静态,我将无法访问外部类的任何方法。

【问题讨论】:

    标签: java android alarmmanager repeatingalarm


    【解决方案1】:

    您的代码有点混乱。

    1. DashboardFragment 中,您实际上声明了一项服务。
    2. 您的服务类名称是 DashboardActivity.MyService.class,这很值得怀疑,因为服务应该始终与活动隔离。

    所以请尝试将 DashboardFragment 重命名为 Myservice,并生成如下意图:

    Intent intent = new Intent(this, MyService.class);

    另外,将您的清单文件更改为

    <service
    android:name="Your service pacakge + "." + MyService"
    android:enabled="true">
    </service>
    

    例如,如果您的服务的包是 com.android.system。那么你的安卓名字应该是"

     com.android.system.MyService
    

    【讨论】:

    • 之所以是DashboardActivity.Myservice.class是因为该类是DashboardFragment的内部类。
    【解决方案2】:

    如果你想让你的服务成为一个内部类。服务必须是一个静态类。像这样:

    public static class MyService extends Service {
        public MyService() {
            super();
        }}
    

    【讨论】:

    • 如果我将方法设为静态,那么我将无法访问外部类的任何方法
    • @Tungamirai 服务必须是静态的,如果你想让它成为一个内部类。
    • 有什么方法可以从静态内部类访问任何外部类方法
    • Activity 和 Service 可以通信,stackoverflow.com/questions/2463175/…。你的 Service 或 Activity 启动一个命令,然后另一个得到这个命令并做你想做的事。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多