Using. NET to build a mobile client (Android/ios) service-side framework nhm--android-end message processing mechanism

Source: Internet
Author: User

Nhmframework the message processing mechanism of the Android terminal

1, outline: In our framework, the Android client inherits application to control the entire application life cycle, in the application OnCreate () method, we will start a mainservice, This service will be responsible for most of the activity's asynchronous message processing (including asynchronous HTTP requests), task scheduling, data sharing, and most persistent operations. So what is the purpose of this?

1) Asynchronous Message Processing: Asynchronous message processing is implemented in the service in order to keep the activity interface displayed in a separate thread, while other time-consuming operations (such as access servers, parsing data, processing data, GPS positioning, etc.) are placed in a new thread, This way the UI interface will not "Wait" for these time-consuming tasks, that is, when the program handles these tasks, the UI interface remains operational, does not die, and achieves a better user experience. Of course, you can also create time-consuming threads directly in the activity, but this way you can't manage many tasks, which is not conducive to program structure and code reuse.

2) Task scheduling: We use a stack-like data structure to manage tasks, and the process is as follows:

UI interface Create a new access server task-> This task to the service's task stack->mainservice perform task--update the results to Ui->ui to show the results

3) Data sharing: Mainservice provides a bridge for the transfer of parameters between the activity, especially some data that may be used by different activity multiple times, such as GPS location, it is more convenient to save the variable by mainservice than to direct the parameter between the activity.

2, points to understand:

1) We know that the Android service itself is not a separate thread--that is, when the service is started, there is no new thread to build, so we have to build a new thread to listen to the task request from the UI. , and then sends the result to the UI after the background processing, realizes the request of the UI asynchronous processing.

2) Inheriting application also does not create new threads, which means that inheriting application does not consume more system resources, even if you do not inherit, application life cycle also exists, you inherit, but can in the life cycle for the program in different timing stages "add "More processing.

3) The message near processing process in Mainservice is through a while (true) loop to monitor the task stack, the task stack has a task, the execution, execution results are sent to the UI layer through the message, the reader of C/s will certainly understand such a mechanism.

3, Getemployeebyid as an example of the timing diagram:

Second, the Android program start and complete exit

1, Start: Android program launch portal, is declared in Manifest.xml <action android:name= "Android.intent.action.MAIN"/> If you have inherited application and declared this inheritance in Manifest.xml, your application class will be executed. In our project, Mainservice is launched in application.

2, Exit: Remember the middle of 2011, some Android applications have been bursting out of the storm, leaving out the deliberate ingredient, single technically speaking, Android's exit is really not a command so simple. First, if you have more than one activity in your program, you must perform Finish () for all of your activity, and then if your program creates a new service, the service needs to execute the Intent.stopservice () method and Process.killprocess () has different interpretations on different Android versions ... So the first thing we should know is how to tell if an Android program is completely out of the way.

1) Open Eclipse,debug Your program, you will see this status under the Debug tab:

2) switch to DDMS, in devices, you will see this state:

As you can see, the bottom of the process (Ddms is looking at threads thread in process Process,debug) is the program we are debugging. At this point I quit the program and if the process is gone, it proves to be completely exited. That is, to see if the process is killed in DDMS to determine that it is truly a complete exit.

What is the correct way to exit? The correct exit of Android program should follow the following order:

1) Traverse all activity Execution finish () method;

2) traverse the service established in your program, and StopService ();

3) killprocess

In addition, you should pay special attention to the location of the above operation: service can not stop itself, so if you want to StopService () must be in application, Killproces is the same. If you perform the StopService () operation in the service, there will be no error, but in DDMS you will find that the process is still there, even though the debug window is already disconnect, and the program in the emulator has " Missing "--as long as you traverse all the activity and execute the finish () method, the running program in the emulator disappears, looks like the" Exit "program, and in the background, there may still be a service that you have established running.

Here's my androidmenifest.xml and Mainapp.java.

Androidmenifest.xml

<?xml version= "1.0" encoding= "Utf-8"? ><manifest xmlns:android= "http://schemas.android.com/apk/res/ Android "package=" nhm.atraining "android:versioncode=" 1 "android:versionname=" 1.0 "> <uses-sdk android: minsdkversion= "7"/> <uses-permission android:name= "Android.permission.INTERNET"/> <uses-permission and Roid:name= "Android.permission.GET_TASKS"/> <uses-permission android:name= "android.permission.WRITE_ External_storage "/> <application android:debuggable=" true "android:icon=" @drawable/ic_launcher "Android: Label= "@string/app_name" android:name= "com.nhm.training.logic.MainApp" > <service android:name= " Com.nhm.training.logic.MainService "> <intent-filter> <action android:name=" com.nhm.t Raining.logic.MainService "></action> </intent-filter> </service> <activit Y android:label= "@string/app_name" Android:name= ". Mainactivity "> <intent-filter> <action android:name= "Android.intent.action.MAIN"/> <category Android Oid:name= "Android.intent.category.LAUNCHER"/> </intent-filter> </activity> </appli Cation></manifest>
Mainapp.java
public class Mainapp extends application {public Mainapp mApp; @Overridepublic void OnCreate () {mApp = This;intent serv = n EW Intent ("Com.nhm.training.logic.MainService"); This.startservice (serv); Super.oncreate ();} @Overridepublic void Onterminate () {//TODO auto-generated method Stubsuper.onterminate ();} public void Destroy () {//TODO auto-generated method Stubfor (Activity ac:MainService.allActivity) {ac.finish ();} Intent it = new Intent ("Com.nhm.training.logic.MainService"); This.stopservice (it); Android.os.Process.killProcess ( Android.os.Process.myPid ()); System.exit (0);}}

Third, implement asynchronous task mechanism with Mainservice

Through the above principles, I believe that the reader has understood the main role of Mainservice, the following we will be to achieve mainservice. In the Com.nhm.training.logic package, the classes that are required for task processing are included, each explaining their role.

Iactivity: is an interface declaration that declares void Init () and void Refresh (Object ... param) Two interfaces, which primarily require that each activity must implement an initialization and update method to implement a task mechanism.

Mainapp: Inherited from application, mainly responsible for controlling the application at the start and exit of the time to open and stop Mainservice, in the late use of third-party APIs (such as Baidu map) may also do some processing in the application layer.

Mainservice: Completes the entire task message processing mechanism, throws a new thread at Mainservice onCreate () to listen to the task, executes the job when there is a task, and sends a message to the UI after the task is finished.

Serviceconst: Save some of the necessary static constants.

Task: The class that describes the task, including the task ID, task parameters, and so on.

I would like to Mainservice first draw a UML Class Diagraim and then give the code, the result of the machine rose a little problem, reverse Java project is always abnormal exit, alas, so directly to the code bar, but also hope you readers Haihan. Code is long, no class diagram is really not very good-looking ah.

public class Mainservice extends Service implements Runnable {public static arraylist<activity> allactivity = new Ar Raylist<activity> ();p ublic static int lastactivityid;public static String lastactivityname;private Uehandler Uehandler;public static list<task> tasklist = new arraylist<task> (0);;; public static arraylist<task> Alltask = new arraylist<task> ()//Get Activity Object public static from the collection by name Activity Getactivitybyname (String name) {for (int i = Allactivity.size ()-1; I >= 0; i--) {Activity AC = ALLACTIVITY.G ET (i); if (Ac.getclass (). GetName (). IndexOf (name) >= 0) {return AC;}} return null;} Add public static void NewTask (Task Task) {Alltask.add (Task);} public Boolean isrun = true; @Overridepublic ibinder onbind (Intent Intent) {//TODO auto-generated method Stubreturn null;} Update uiprivate Handler hand = new Handler () {@Overridepublic void Handlemessage (Message msg) {//TODO auto-generated Metho D stubsuper.handlemessage (msg); Bundle BTCCGF = msg.getdATA (); String acname = btccgf.getstring ("Acname"); Iactivity ia = (iactivity) mainservice.getactivitybyname (acname); switch ( Msg.what) {case ServiceConst.GET_EMPLOYEE_ERROR:ia.refresh (serviceconst.get_employee_error, msg.obj); break;case ServiceConst.TASK_GET_EMPLOYEE:ia.refresh (SERVICECONST.GET_EMPLOYEE_OK, msg.obj); break;}}; public void Setcurrentactivityname () {Activitymanager Activitymanager = (Activitymanager) getapplicationcontext (). Getsystemservice (Context.activity_service); list<runningtaskinfo> forgroundactivity = activitymanager.getrunningtasks (1); Runningtaskinfo currentactivity;currentactivity = forgroundactivity.get (0); String activityname = CurrentActivity.topActivity.getClassName (); lastactivityname = Activityname;} Execute task public void Dotask (Task Task) {setcurrentactivityname (); Message mess = Hand.obtainmessage (); mess.what = Task.gettaskid ();//define Refresh UI Changes Tasklist.add (Task); HashMap paramin = (HashMap) task.gettaskparam (); HashMap paramout = new HashMap (); String acname = string. ValueOf (Paramin.get ("Acname"));p aramout.put ("Acname", acname); Employees emp = Null;switch (Task.gettaskid ()) {case ServiceConst.TASK_GET_EMPLOYEE:try {int uid = (integer.valueof ( String.valueof (Paramin.get ("EmployeeID"))); emp = Bll.getemployeebyid (UID); mess.obj = emp;} catch (Exception e) {mess.what = Serviceconst.get_employee_error;} if (EMP = = null) {mess.what = Serviceconst.get_employee_error;} break;} bundle BC = new Bundle (); Bc.putstring ("Acname", Acname); mess.setdata (BC); Hand.sendmessage (mess);// Send the update UI message to the main thread alltask.remove (Task);//Finish task} @Overridepublic void Run () {//TODO auto-generated method Stubwhile (Isrun) { Task Lasttask = null;synchronized (alltask) {if (alltask.size () > 0) {//Fetch task Lasttask = alltask.get (0);//Perform Task Dotask (las Ttask);}} LOG.D ("Debug Main Service", "..."); try {thread.sleep (1000);} catch (Exception e) {}} @Overridepublic void OnCreate () {//TODO auto-generated method stub//log.d ("Debug main Service on Create "," ...... "); Super.oncreate (); UehaNdler = new Uehandler (this);//Set exception handling instance Thread.setdefaultuncaughtexceptionhandler (Uehandler); isrun = true; Thread t = new thread (this); T.start ();} @Overridepublic void OnDestroy () {//TODO auto-generated method Stubsuper.ondestroy (); isrun = false;} Alertuser prompting user for network status error public static void Alertneterror (Final Context con) {Alertdialog.builder ab = new Alertdialog.build Er (con); Ab.settitle (r.string.noroutetohostexception); Ab.setmessage (r.string.nosignalexception); Ab.setnegativebutton (r.string.apn_is_wrong1_exit,new Onclicklistener () {@Overridepublic void OnClick ( Dialoginterface dialog, int which) {//TODO auto-generated method Stubdialog.cancel ();//Exitapp (con);((Mainapp) (( Activity) (Con). Getapplication ()). Destroy ();}); Ab.setpositivebutton (r.string.apn_is_wrong1_setnet,new Onclicklistener () {@Overridepublic void OnClick ( Dialoginterface dialog, int which) {//TODO auto-generated method Stubdialog.dismiss (); Con.startactivity (New Intent ( Android.provider.Settings.ACTION_WIRELESS_SETTINGS));}); Ab.create (). Show ();} public static void Promptexit (Final Context con) {//Create dialog box Layoutinflater li = Layoutinflater.from (con); View Exitv = li.inflate (R.layout.exitdialog, NULL); Alertdialog.builder ab = new Alertdialog.builder (con); Ab.setview (EXITV);//Set the View object displayed by the dialog box Ab.setpositivebutton ( R.string.exit, New Onclicklistener () {public void OnClick (dialoginterface arg0, int arg1) {//TODO auto-generated method s Tub ((Mainapp) ((Activity) con). Getapplication ()). Destroy ();}); Ab.setnegativebutton (r.string.cancel, NULL);//Display dialog box Ab.show ();} public static void Init () {//TODO auto-generated method stub}}

Iv. Client Extensions--command stitching and encryption

In the previous article we have mentioned that to use a hashmap to save the parameters from the client to the server, the purpose is to more clearly describe the parameters sent to the URL in the BLL layer. The code is as follows:

/** * Convert the URL parameter hash table to an encrypted string * @param map * @return */public static string Tourlparam (HashMap map) {string cmd = string.valueof (Map.get ("cmd"));//Clear empty cmd for "unknown" if (cmd.equals (null) | | cmd.equals ("")) {cmd = "unknown";} To add a common parameter field, such as a IMEI,GPS location, this example only adds a current time Map.put ("Now", (New Date ()). ToString ()),//hashmap first converted to jsonjsonobject jstest = New Jsonobject (map); String Jsparam = jstest.tostring ();//Encrypt and compress json, add your own encryption algorithm Jsparam = Desencoder.encrypt (Jsparam); String enc = "";//The outermost layer is wrapped with base64encode, note the + and/replace of the Base64 character table with try {enc = new Base64encoder (). Encode ("UT F-8 "));} catch (Unsupportedencodingexception e) {//TODO auto-generated catch blockenc= ""; E.printstacktrace ();} Return enc;}

Give an example of how HTTP requests are implemented in the BLL layer

public static Employees Getemployeebyid (int id) {HASHMAP param = new HashMap ();p aram.put ("cmd", "GetEmployee");p Aram.put ("Method", "Byid");p aram.put ("id", id);//convert this hashmap to an encrypted string, string parmstr = Urlparamutils.tourlparam (param); String Paramstrall = baseurl+ "api/android_process.aspx?a=" + parmstr; Employees emp = new Employees (); try {//Use Http.get () connection to return Jsonarrayjsonarray JSON = Get (Paramstrall,null, True). Asjsonarray (); String Jsonfirst = json.get (0). toString (); LOG.D ("BLL", "Start Gson.fromjson");//Create a new Gson object and set the date type Gson Gson = new Gsonbuilder () in the same format as the server. Setdateformat (" Yyyy-mm-dd HH:mm:ss "). Create ();//deserialize JSON data to Employees type EMP = Gson.fromjson (Jsonfirst, Employees.class); LOG.D ("BLL", "End Gson.fromjson");} catch (Nexception e) {//Todo auto-generated catch Blockemp=null;e.printstacktrace ();} catch (Jsonexception e) {//Todo Au To-generated catch Blockemp=null;e.printstacktrace ();} return EMP;}
V. Client ui--mainactivity

With the foundation above, the mainacitivity is very simple. In activity onCreate (), the task is set up and the task is pressed to the task stack, and the task is executed in Mainservice new thread, while the foreground can display a "reading" progress bar with a progress, and when the task executes, Postback to activity update, activity is displayed according to the parameters returned. The mainactivity code is given below:

public class Mainactivity extends activity implements Iactivity {/** called when the activity is first created. */protecte D static View process;//add-on//back key display Exit Prompt @overridepublic boolean onKeyDown (int keycode, keyevent event) {//TODO Auto-genera Ted Method Stubif (keycode = = Keyevent.keycode_back) {mainservice.promptexit (this); return true;} Return Super.onkeydown (KeyCode, event);} @Overridepublic void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview ( R.layout.main);p rocess = This.findviewbyid (r.id.progress);//Show Progress bar process.setvisibility (view.visible) by default;// Save activity in Mainservice MainService.allActivity.add (this);//set parameter hashmaphashmap param = new HashMap ();p aram.put (" EmployeeID ", New Integer (2));p aram.put (" Acname "," mainactivity ");//Establish Tasktask task = new Task (serviceconst.task_get_ EMPLOYEE, param);//The Task stack mainservice.newtask (Task) pressed into the Mainservice;} @Overridepublic void init () {//TODO auto-generated method stub} @Overridepublic void Refresh (Object ... param) {//ToDo Auto-generated method stub//handles UI updates TextView Tvempname = (TextView) This.findviewbyid (r.id.empname);// Hides the progress bar process.setvisibility (view.gone); switch (((Integer) (param[0)). Intvalue ()) {case Serviceconst.get_employee_ The ok://server returns the correct situation Employees emp = (Employees) param[1];tvempname.settext (Emp.getfirstname ()); break;case serviceconst.get_employee_error://the server returned an error Tvempname.settext ("Error occered");

V. Server-side extension-client command parsing processing

When the client makes an HTTP request to the server, it actually requests the server-side URL: http://safe.ijiami.cn/= encrypted string, we need to parse request.querystring["a" on the service side, decrypt the string, Revert to Jsonobject and do the corresponding processing at the BLL layer on the service side. The C # code for the server android_process.aspx and employeebll.aspx is given below:

Public partial class Android_process:System.Web.UI.Page {string InStr;        Jsonobject Paramjson;            protected void Page_Load (object sender, EventArgs e) {string rst= "";                try {//Get encrypted string instr = Request.querystring["a"];                Parse the cryptographic string as Jsonobject string orgstr = Encrypthelper.decodebase64withdes (instr);                                Paramjson = Jsonconvert.deserializeobject (ORGSTR);                Takes the cmd command, returns the error string cmd = "" If a null value is obtained or gets failed; cmd = paramjson["cmd"].                ToString (); if (String.IsNullOrEmpty (cmd)) {Lt_rtn.                    Text = "{rst:error}";                Return                        }//Jump to Logical switch (CMD) {case "GetEmployee" according to the cmd command:                        rst = Employeebll.getemployeeinfo (Paramjson);              Break  }} catch (Exception) {Lt_rtn.            Text = "{rst:error}"; } lt_rtn.        Text = rst; }    }

public static class Employeebll    {public        static string Getemployeeinfo (Jsonobject Paramjson)        {            string Method = Paramjson["Method"]. ToString ();            String RTN = "";            Switch (method)            {case                "Byid":                    int id = Int. Parse (paramjson["id"). ToString ());                    Employeeentity ee = new employeeentity (ID);                    RTN = Ee.tojson ();                    break;            }            return RTN;        }    }

Six, simulator debugging

Now let's debug it in the simulator:

A) normal test:

II) Anomaly Testing

In the normal test, we want to get the name of the employee of id=2, here we change the ID to-1, because this employee does not exist, the server will return the exception, we look at the client processing.

You can see that the client handled the exception correctly.

Summarize

In this course, we implement the asynchronous task mechanism of Android through a service that resides in memory, and apply this asynchronous processing to HTTP access, the reader can continue to expand, and use such a mechanism to handle the time-consuming operation of GPs and uploading.

Starting with the next one, we'll split into two branches, one branch that continues to learn about Android's interaction with. NET Server, another branch that will turn to the iOS platform, and let iOS support our. NET service side.

Using. NET to build a mobile client (Android/ios) service-side framework nhm--android-end message processing mechanism

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.