通过后台服务启动Android活动

3
我的目标是让UDP数据包接收应用在启动时持续运行,当它接收到有效的数据包时,必须处理消息并将其显示出来。经过一些研究,我做了以下几点:
1.广播接收器类 - 在启动时启动服务(mstart.java)。 2.监视UDP数据包的服务类(udp.java)。 3.显示消息文本的显示类(Rmsgs.java)。 4.全局变量GlobalState.Java。
我写了一个带有列表视图的独立UDP应用程序,它工作正常。因此,我知道这方面没有问题。当我编译并运行代码时,服务会在启动时启动,然后崩溃。为了调试,我去掉了UDP数据包接收部分。UDP类在接收数据包后将生成两个数组列表,并将其保存在全局类中,显示类将获取它。
    This code is working now, I found mistake I have made and corrected it.

现在我需要修改代码以接收UDP数据包。
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>

<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.QUICKBOOT_POWERON"/>
<application
    android:name="com.mmm.rmsg.GlobalState"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:largeHeap="true"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MsgView"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
           <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <receiver android:enabled="true" android:exported="true"
        android:name=".mstart"
        android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
            <action android:name="android.intent.action.QUICKBOOT_POWERON"/>
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>
    <service android:name=".udp"
      />
    </application>
<uses-permission android:name="android.permission.INTERNET"/>

广播接收器类

 package com.mmm.rmsg;
 import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class mstart extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {

    Toast.makeText(context, "Intent detcted.", Toast.LENGTH_LONG).show();

    Intent pushIntent = new Intent(context, udp.class);
    context.startService(pushIntent);
  }

  }

服务类

  package com.mmm.rmsg;
  import android.app.Service;
  import android.content.Context;
  import android.content.Intent;
  import android.os.IBinder;
  import android.os.PowerManager;
  import android.widget.Toast;
  import java.util.ArrayList;

  import static android.os.PowerManager.PARTIAL_WAKE_LOCK;


  public class udp extends Service {

  private static final String LOG_TAG =udp.class.getSimpleName();


  GlobalState gs = (GlobalState)getApplication();

 @Override
 public IBinder onBind(Intent arg0){

    return  null;
}

@Override public int onStartCommand(Intent intent, int flags, int startId) {

    setWakeLock();
    Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();

    new Thread(new Server()).start();

   return START_STICKY;




}


private void setWakeLock(){


    PowerManager.WakeLock mWakeLock;
    PowerManager powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
    mWakeLock=powerManager.newWakeLock(PARTIAL_WAKE_LOCK, LOG_TAG);
}

public class Server implements Runnable {

    @Override
    public void run() {

        ArrayList<String> list = new ArrayList<>();
        ArrayList<String> clist = new ArrayList<>();
        // here udp packets are recvd & processed into 2 list arrays

        list.add(0, "MAIN FAIL");
        list.add(1,"BOILER HEATER 20C");
        list.add(2, "COOLING NEED ATT");

        clist.add(0, "6");
        clist.add(1,"1");
        clist.add(2, "5");

        GlobalState gs = (GlobalState)getApplication();

          gs.setGmlist(list);
          gs.setGclist(clist);

        call();

    }

}

public void call() {


    Intent dialogIntent = new Intent(getBaseContext(), MsgView.class);
    dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(dialogIntent);

   }

  }

全局类

   package com.mmm.rmsg;

  import java.util.ArrayList;
  import android.app.Application;

  public class GlobalState extends Application
  {
    private ArrayList<String> Gmlist = new ArrayList<>();
    private ArrayList<String> Gclist = new ArrayList<>();
    private boolean chk = true;
    private boolean cchk = true;



   public ArrayList<String> getGmlist() {

    chk = Gmlist.isEmpty();

    if(chk==true)
    {
        Gmlist.add(0,"No Calls");
    }

     return Gmlist;
  }

   public ArrayList<String> getGclist() {
      cchk = Gclist.isEmpty();

    if(cchk==true)
    {
        Gclist.add(0,"0");
    }

    return Gclist;
}

    public void setGmlist(ArrayList<String> Gmlit) {

        for (int i = 0; i < Gmlit.size(); i++) {
            this.Gmlist.add(i, Gmlit.get(i));
        }


  }

  public void setGclist(ArrayList<String> Gclit) {

    for (int i = 0; i < Gclit.size(); i++) {
        this.Gmlist.add(i, Gclit.get(i));
      }

     }

   }

显示类

    package com.mmm.rmsg;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.widget.ListView;
    import android.content.Context;
    import android.graphics.Color;
    import android.widget.ArrayAdapter;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    import java.util.ArrayList;
    import java.util.Arrays;


    public class MsgView extends AppCompatActivity {

        ListView listView ;
        ArrayList<String> mlist = new ArrayList<>();
        ArrayList<String> plist = new ArrayList<>();

        @Override
        protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_msg_view);

            // Get ListView object from xml
            listView = (ListView) findViewById(R.id.list);

            GlobalState gs = (GlobalState) getApplication();

                mlist= gs.getGmlist();
                plist= gs.getGclist();



                String[] msgArray = mlist.toArray(new String[mlist.size()]);
                Arrays.toString(msgArray);
                String[] clrArray = plist.toArray(new String[plist.size()]);
                Arrays.toString(clrArray);


                listView.setAdapter(new ColorArrayAdapter(this, android.R.layout.simple_list_item_1, msgArray,clrArray));

        }



        public class ColorArrayAdapter extends ArrayAdapter<Object>{
            private String[] list;
            private String[] p;
            public ColorArrayAdapter(Context context, int textViewResourceId,
                             Object[] objects, Object[] obj) {
            super(context, textViewResourceId, objects);
            list = new String[objects.length];
            for (int i = 0; i < list.length; i++)
                list[i] = (String) objects[i];

            p = new String[objects.length];
                for (int i = 0; i < p.length; i++)
                p[i] = (String) obj[i];
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = (TextView)super.getView(position, convertView, parent);




        String c;
        for(int x=0; x< list.length; x++)
        {
            c=chk(x,p);

            if("R".equals(c) && position==x ) {
                view.setBackgroundColor(Color.RED);
            }
            else
            if("Y".equals(c) && position==x) {
                view.setBackgroundColor(Color.YELLOW);
            }
            else
            if("G".equals(c) && position==x) {
                view.setBackgroundColor(Color.GREEN);
           }

        }
            return view;
        }

    }


        public  String chk(int idx, String[] table){


    String res;
    if("6".equals(table[idx]) || "7".equals(table[idx])  || "8".equals(table[idx])) {
        res = "R";
    }
    else
    if("4".equals(table[idx])  || "5".equals(table[idx])) {
        res = "Y";
    }
    else
    if("1".equals(table[idx])|| "2".equals(table[idx]) || "3".equals(table[idx]) ) {
        res = "G";
    }
    else{
        res = "W";
    }



        return res;
    }


        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_msg_view, menu);
        return true;
    }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
            }

    return super.onOptionsItemSelected(item);
        }


        @Override
        protected void onDestroy(){
            super.onDestroy();

        }
    }
3个回答

4

您还没有开始您的线程。您可以像这样进行:

Thread initBkgThread = new Thread(new Runnable() {

        public void run() {
            udp();
        }
    });
initBkgThread .start();

谢谢。我已经完成了,一旦我测试过它,我会回复你。 - Jro
嗨,我已经完成了所有建议的更改,但它仍然无法工作。看起来我的接收器没有收到系统发送的任何消息。我创建了另一个应用程序与我的其他类,并且它能够正常运行。 - Jro
我想做的就是让应用程序在启动时持续运行,监视UDP端口以接收消息并显示。 - Jro

3

这是完整的代码还是一些片段?首先,你的text1未被初始化。

text1 = findViewById(R.id.<activity_calls_layout中的TextView控件ID>)


谢谢。这是完整的代码。我已经进行了以下更正: setContentView(R.layout.activity_smsgs); text1=(TextView)findViewById(R.id.textView1); - Jro

1
要从您的服务启动活动,您应该创建像这样的意图:
//Starting Smsgs 
Intent startAct = new Intent(context, Smsgs.class);
startAct.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(startAct);

你需要至少两个线程来完成这个任务,一个用于接收UDP数据包,另一个用于计算数据。你需要修改你的udp()函数如下:
//Warning, I did not test this code, handle it like pseude-code. 
private void udp(){

            // ...
            // Wait to receive a datagram
            dsocket.receive(packet);

            Thread showMsg = new Thread(new Runnable() {

                public void run() {
                   // Convert the contents to a string,
                   String message = new String(buffer, 0, packet.getLength());
                   Intent intent = new Intent(this, Smsgs.class);
                   intent.putExtra("msg",message);
                   intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                   startActivity(intent);

                }

            });
            showMsg.start();
            // ...
}

同时不要忘记启动另一个线程:initBkgThread.start()

希望这有所帮助。


1
谢谢。我添加了上述内容,而且“WAKE”一词是红色的。无法解析符号“WAKE”。我需要导入任何东西吗? - Jro
哦,抱歉,这是我应用程序中的一个常量,我修改了代码。 - bendaf
谢谢。是和否。我对我的代码进行了一些修改,它确实在启动时启动了服务。但是当服务调用活动以从while循环中显示消息时,似乎会使应用程序崩溃。为了检查我的代码是否正确,我编写了一个单独的应用程序,该应用程序接收UDP数据包并提取消息以使用列表视图显示,如果服务器取消消息,则将其从列表视图中删除,只要用户不关闭应用程序,它就可以正常工作。我已决定编写一个服务,该服务将在启动时启动,接收UDP数据包并将消息写入文件,该文件将始终得到更新。 - Jro
然后使用BIT Web服务器来显示消息,以防用户关闭Web视图,消息不会丢失。我的唯一问题是如何在忙于处理要写入文件的消息时避免丢失UDP数据包。 - Jro
我认为,你应该开启一个线程专门用于接收UDP数据包,另一个线程则用于在UI线程上显示或将其写入文件中... - bendaf
显示剩余6条评论

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