Android:如何在启动时后台执行应用登录?

5

我有一个 VOIP 应用程序,我需要在设备启动时后台登录该应用程序。

目前我的应用程序初始化是在 UI 活动(onCreate())中完成的。

我心里有以下问题,有人可以帮忙解答吗?

  1. 必须进行服务设计才能完成此任务吗?
  2. 使用哪种服务远程(AIDL)或本地服务以及为什么?
  3. UIService 之间的交互如何进行?
  4. UI 活动后谁会得到回调?UI 还是 Service
  5. 我应该将 Service 作为我的控制器,即 ServiceUI 传递数据反之亦然吗?

示例应用程序:Skype。

5个回答

5

有许多方法可以实现你想要的,关键在于什么更适合你的风格和设计。希望这些信息对你有用。

  1. 要使应用程序在启动时后台登录,有几个选项。首先需要一个BroadcastReceiver,在清单文件中定义为接收器。让BroadcastReceiver捕获ACTION_BOOT_COMPLETED意图。从这里可以启动您的Service。这导致第2点。

  2. 如果您只是进行RESTful调用,则IntentService真的很理想。 IntentService和Service之间的区别很简单:IntentService运行在主线程之外,执行其“代码”并死亡。但是,Service在主线程上运行(这是一个重要的事实),因此运行时间较长,因此必须告诉它stopSelf()。更进一步地说,与Activity相比(应用程序组件被杀死以为新启动的应用程序腾出内存空间),Service也不太可能被杀死,即具有更高的优先级。服务还可以声明为foreground服务,这需要通知但提供了更高的优先级。我认为在您的情况下,Service非常完美。

  3. 一旦打开UI(Activity),连接到Service的最佳方法是Binder。这将允许来自不同应用程序/组件的多个接口访问Service。 AIDL非常酷,但根据我的经验,很难管理,因为所有参数都必须是基本类型或Parcables。 AIDL也更慢且效率更低,因为它实际上是一种IPC形式。当使用意图启动服务时,将调用onStartCommand()方法。如果应用程序尝试绑定到它,则会调用onBind()方法。但是,您可以使用Intent启动服务,然后绑定到它。如果您喜欢RESTful方法,只需快速调用数据即可使用带有ResultReceiver的IntentService。这是一篇非常好的文章,介绍了Google I/O示例以及整体实现得非常好,如果您对IntentService和ResultReceiver感兴趣。

  4. 这取决于您。使用Binder或AIDL,您的Activity可以像对象方法一样调用Service方法,其中“回调”只是方法返回。如果使用ResultReceiver,则与接收器进行交互的Activity将是回调。您还可以仅传递Intents来回,但这可能会变得混乱。再次针对您的情况,Binder方法以及接收器都是不错的选择。

  5. 将Service视为MVVM系统中的模型-将其用作获取数据的助手,而不是控制应用程序逻辑的东西。

如果这看起来有点混乱,那是因为有很多方法可以实现你想要的东西。只是要选择最适合你情况的方法,或者你“感觉”更好的方法。更不用说Android SDK非常庞大了。我尽可能涉及了所有能帮助你的话题。祝你好运!


答案与我的问题相关,因此将其标记为答案。谢谢 jjNford。 - NitZRobotKoder
1
@NitZRobotKoder 没问题,所有的服务及其使用可能会变得棘手。提前知道在哪里查找有所帮助。祝你好运! - jjNford

1

尝试使用启动接收器的服务。这里是我在快速谷歌搜索后找到的一个例子。然后确保将登录信息存储在某个地方,以便应用程序启动时使用。不确定您可能有哪些回调函数,因此很难回答这部分问题。我会说,如果回调应该影响UI,则让活动在启动时接管它们。如果您需要在仅运行服务时拥有UI,则最好弹出通知并使用回调数据调用适当的活动。


@Mikelsrael 感谢您的建议。回调将涉及登录成功/失败或网络上/下等内容。但我没有理解您评论中的上下文,即“如果您需要在仅服务正在运行时使用UI,则最好弹出通知并使用回调数据调用适当的活动”。 - NitZRobotKoder
1
@NitZRobotKoder 我在说通知用户的好方法是通过通知栏。因此,只需创建一个尝试登录并注册为网络更改广播接收器的服务。然后,当服务遇到需要通知用户的事件时,在通知栏中弹出通知。有关通知的更多信息,请参见此链接 http://developer.android.com/guide/topics/ui/notifiers/notifications.html - MikeIsrael
@NitZRobotKoder 我不知道这是什么意思。谁将负责打开通知并进行沟通?服务会负责。 - MikeIsrael
@Mikelsrael 我的意思是,由于它是VOIP应用程序,因此它会从服务器获取数据,那么谁接收它SERVICE/Active UI? - NitZRobotKoder
@NitZRobotKoder 你需要自己解决这些问题。设计一个VoIP应用程序是一个严肃的项目,你不可能在这里找到有人会为你完成它。 - MikeIsrael
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/10788/discussion-between-nitzrobotkoder-and-mikeisrael - NitZRobotKoder

0

你可以通过后台服务验证用户登录 包com.javaorigin.android.sample.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

public class MyService extends Service {

   String tag="TestService";
   @Override
   public void onCreate() {
       super.onCreate();
       Toast.makeText(this, "Service created...", Toast.LENGTH_LONG).show();      
       Log.i(tag, "Service created...");
   }

   @Override
   public void onStart(Intent intent, int startId) {      
       super.onStart(intent, startId);  
       Log.i(tag, "Service started...");
   }
   @Override
   public void onDestroy() {
       super.onDestroy();
       Toast.makeText(this, "Service destroyed...", Toast.LENGTH_LONG).show();
   }

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


public class SampleAction extends Activity {
   @Override
   protected void onCreate(Bundle savedInstanceState) {      
       super.onCreate(savedInstanceState);
       TextView view = new TextView(this);      
       view.setText("Service Test");
       Intent i = new Intent();
       i.setClassName( "com.javaorigin.android.sample.service",
        "com.javaorigin.android.sample.service.MyService" );
       bindService( i, null, Context.BIND_AUTO_CREATE);
       this.startService(i);      
       setContentView(view);
   }
}

Deepak,你正在启动活动,然后启动服务。我的应用程序应该在没有UI的情况下登录。 - NitZRobotKoder
想象一种情况,用户已经设置好了,而设置是不要每次都询问的。 - NitZRobotKoder
现在当您的主要活动启动时,您只需通过startService(new Intent(KhoobsurtiActivity.this,FetchPostService.class))调用后台服务即可。您想在该页面上进行哪些处理,您可以非常轻松地进行认证。 - coading fever
我想在后台静默登录,此时我的主活动将不会处于活动状态。当用户点击应用程序图标时,我应该看到主页,而不是任何登录进度。 - NitZRobotKoder

0
如果登录需要很长时间,请使用[AccountManager][1],并且只需执行一次。 AccountManager的背后思想是在您的Service中使用令牌或其他凭据。
在您的特定情况下,我认为将您的ActivityService绑定是最好的通信方式。

0
关于基本的Service使用,最好的知识来源是SDK。简而言之,AIDL用于IPC通信,只要在同一进程中运行服务,就不需要它。我想你有两个选择:
  1. 如果你只需要登录,你可以在启动时启动一个服务,登录,然后发送一个带有捆绑的登录数据的粘性广播,该广播将在应用程序中接收到。请参见this question以获取一组良好的启动服务的方法。

    @Override
    public void onCreate() {
        Data data = performLogin();
        Intent i = new Intent(ACTION_VOIP_LOGIN);
        i.putExtra(EXTRA_LOGIN_DATA, data);
        mContext.sendStickyBroadcast(i);
    }
    
    ...
    
    private final class LoginReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            // You may use a Bundle instead
            Data data = intent.getParcelableExtra();
            processLoginData(data)
        }
    }
    
    protected void onCreate(Bundle savedInstanceState) {
         ...
         IntentFilter filter = new IntentFilter(ACTION_VOIP_LOGIN);
         mContext.registerReceiver(new LoginReceiver(), filter);
    }
    
  2. 在第二种情况下,您可能希望将所有逻辑移动到服务中。在这里,您将扩展Binder类。有关详细信息,请参见此SDK文章


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接