到官网下载jar包,下载GA发布版本即可
在项目中将httpclient-4.5.5.jar、httpcore-4.4.9.jar、httpmime-4.5.5.jar、commons-logging-1.2.jar四个jar包放进lib中
服务器端
@Controller @RequestMapping("/HttpInfoController") public class GetHttpInfoController { @RequestMapping("/getAndroid") @ResponseBody public String getAndroid(HttpServletRequest request, HttpServletResponse response) { String data = request.getParameter("data"); try { String path="/root/Android.log"; File file=new File(path); //若不存在即创建文件 if(!file.exists()) file.createNewFile(); //创建文件输入流 FileOutputStream out=new FileOutputStream(file,true); //如果追加方式用true StringBuffer sb=new StringBuffer(); SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); sb.append("-----------"+sdf.format(new Date())+"------------ "); sb.append(data+" "); //写入 out.write(sb.toString().getBytes("utf-8"));//注意需要转换对应的字符集 out.close(); } catch(IOException ex) { System.out.println(ex.getStackTrace()); return "success"; }finally { } return "success"; } }
移动端
发送请求工具类
package com.autumn.tools; import android.icu.util.Output; import android.util.Log; import com.autumn.pojo.GPSPojo; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.HTTP; import org.apache.http.util.EntityUtils; public class HttpClientUtil { public static void main(String[] args) throws IOException, KeyManagementException, NoSuchAlgorithmException { //post(URL,"Android项目HttpClient手动发送post()"); //postAndroid(URL,"Android项目HttpClient手动发送postAndroid()"); GPSPojo gpsPojo = new GPSPojo(); gpsPojo.setUserId("qyid1"); gpsPojo.setUserName("autumn"); postObjectAndroid(URL,gpsPojo); } //通用记录到日志url public static String URL = "http://*****/getAndroid"; public static String URL_LOGIN = "http://***/forAndroid"; /** * 正常环境中使用 * @param data */ public static void post(String url,String data) { // 实例化httpclient CloseableHttpClient httpclient = HttpClients.createDefault(); // 创建post实例 if(url==null||url.isEmpty()){ url = URL; } HttpPost httpPost = new HttpPost(URL); httpPost.setHeader("Content-type", "application/x-www-form-urlencoded"); // 添加参数 List<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair("data", data)); CloseableHttpResponse response = null; // 将参数放入post实例 try { httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); // httpclient执行操作返回response response = httpclient.execute(httpPost); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 安卓使用放入data:json格式的对象 * @param data */ public static void postAndroid(final String url,final String data) { Runnable runnable = new Runnable() { public void run() { // 实例化httpclient // CloseableHttpClient httpclient = HttpClients.createDefault(); 使用会与android核心包起冲突 org.apache.http.client.HttpClient httpclient = new DefaultHttpClient(); // 创建post实例 HttpPost httpPost = null; if(url==null||url.isEmpty()){ httpPost = new HttpPost(URL); }else{ httpPost = new HttpPost(url); } httpPost.setHeader("Content-type", "application/x-www-form-urlencoded"); // 添加参数 List<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair("data", data)); // CloseableHttpResponse response = null; 使用会与android核心包起冲突 HttpResponse response = null; // 将参数放入post实例 try { httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); response = httpclient.execute(httpPost); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; new Thread(runnable).start(); } /** * 安卓使用放Http发送Object对象中的每一个字段作为参数,值作为参数值 * @param data */ public static void postObjectAndroid(final String url,final Object data) { Runnable runnable = new Runnable() { public void run() { // 实例化httpclient // CloseableHttpClient httpclient = HttpClients.createDefault(); 使用会与android核心包起冲突 org.apache.http.client.HttpClient httpclient = new DefaultHttpClient(); // 创建post实例 HttpPost httpPost = null; if(url==null||url.isEmpty()){ httpPost = new HttpPost(URL); }else{ httpPost = new HttpPost(url); } httpPost.setHeader("Content-type", "application/x-www-form-urlencoded"); // 添加参数 List<NameValuePair> params = new ArrayList<NameValuePair>(); Class dataClass = data.getClass(); Field[] declaredFields = dataClass.getDeclaredFields(); for (Field field:declaredFields){ try { field.setAccessible(true); if(field.get(data)!=null){ //字段值不为null,则作为参数 params.add(new BasicNameValuePair(field.getName(),field.get(data).toString())); } } catch (IllegalAccessException e) { e.printStackTrace(); } } //params.add(new BasicNameValuePair("data", data)); // CloseableHttpResponse response = null; 使用会与android核心包起冲突 HttpResponse response = null; // 将参数放入post实例 try { httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); response = httpclient.execute(httpPost); if (response.getStatusLine().getStatusCode() == 200) {//如果返回成功则解析 HttpEntity responseEntity = response.getEntity(); //方法一 InputStream inputStream = responseEntity.getContent(); StringBuilder stringBuilder = new StringBuilder(); byte[] temp = new byte[1024]; OutputStream outputStream = new ByteArrayOutputStream(); int len =0; while((len=inputStream.read(temp))!=-1){ outputStream.write(temp,0,len); String result = new String(temp); stringBuilder.append(result); } Log.i("stringBuilder",stringBuilder.toString()); //方法二 /*String str = EntityUtils.toString(responseEntity, HTTP.UTF_8); Log.i("str",str);*/ } } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; new Thread(runnable).start(); } }
消息通知监听ListenerService
package com.autumn.service; import android.app.Notification; import android.os.Bundle; import android.service.notification.StatusBarNotification; import com.autumn.tools.HttpClientUtil; /** * 消息监听 * @author Autumn */ public class NotificationMonitorService extends android.service.notification.NotificationListenerService { // 在收到消息时触发 @Override public void onNotificationPosted(StatusBarNotification sbn) { // TODO Auto-generated method stub Bundle extras = sbn.getNotification().extras; // 获取接收消息APP的包名 String notificationPkg = sbn.getPackageName(); // 获取接收消息的抬头 final String notificationTitle = extras.getString(Notification.EXTRA_TITLE); // 获取接收消息的内容 String notificationText = extras.getString(Notification.EXTRA_TEXT); if(notificationTitle==null&¬ificationText==null){ //如果为空,则不执行 return; } //发送数据 HttpClientUtil.postAndroid("autumn app: "+notificationPkg+" title: " + notificationTitle + " & " + notificationText); //Log.e("listener_post", "autumn app post: "+notificationPkg+" title: " + notificationTitle + " & " + notificationText); } // 在删除消息时触发 @Override public void onNotificationRemoved(StatusBarNotification sbn) { // TODO Auto-generated method stub Bundle extras = sbn.getNotification().extras; // 获取接收消息APP的包名 String notificationPkg = sbn.getPackageName(); // 获取接收消息的抬头 String notificationTitle = extras.getString(Notification.EXTRA_TITLE); // 获取接收消息的内容 String notificationText = extras.getString(Notification.EXTRA_TEXT); //Log.e("listener_remove", "autumn app post: "+notificationPkg+" title: " + notificationTitle + " & " + notificationText); } }
要在AndroidManifest.xml注册service和权限
<!-- 访问网络,发送数据需要上网 --> <uses-permission android:name="android.permission.INTERNET" /> <!-- application中注册消息监听service --> <service android:name="com.autumn.service.NotificationMonitorService" <!--这里写service所在位置,默认包用.,不是默认包要写全路径,与activity同包可以只写类名--> android:label="NotificationMonitor" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" > <intent-filter> <action android:name="android.service.notification.NotificationListenerService" /> </intent-filter> </service>
启动监听服务分两种方式,一个是跳到授权界面并启动服务,第二个直接启动服务
Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"); startActivity(intent); //授权,跳到授权界面并启动服务 Intent startIntent = new Intent(this, BackService.class); startService(startIntent); //启动服务
然后在MainActivity.java中添加运行service,onCreate()方法中代码
Intent intent_listener=new Intent(this, NotificationMonitorService.class); intent_listener.setAction("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"); startService(intent_listener); //启动监听后台服务 setContentView(R.layout.activity_main); //获取启动服务按钮 Button btn_getAcc = (Button) findViewById(R.id.bt1); //按钮点击事件 btn_getAcc.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String string = Settings.Secure.getString(getContentResolver(), "enabled_notification_listeners"); if (!string.contains(NotificationMonitorService.class.getName())) { Toast.makeText(MainActivity.this, "未获得权限,请选择允许权限", Toast.LENGTH_SHORT).show(); }else { Toast.makeText(MainActivity.this, "已经获得权限", Toast.LENGTH_SHORT).show(); } Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"); startActivity(intent);// 来授权 会跳到授权界面 } });
软件自启
软件开关机自启广播
package com.autumn.receiver; import com.autumn.service.NotificationMonitorService; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; /** * 软件自启代码 * @author Autumn */ public class BroReceiver extends BroadcastReceiver { public BroReceiver() { } @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { Intent intent1=new Intent(context, NotificationMonitorService.class); intent1.setAction("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"); context.startService(intent1); //启动监听服务 } } }
AndroidManifest.xml中注册
<!--开机权限--> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<!-- 自启 --> <receiver android:name="com.autumn.receiver.BroReceiver" android:enabled="true" android:exported="true" > <intent-filter android:priority="1000" > <action android:name="android.intent.action.BOOT_COMPLETED" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </receiver>
服务器查看接受数据 tail -f Android.log
注意事项:
1.httpclient出现和system/framework中的jar包起冲突情况
这是由于使用了CloseableHttpClient造成的,把
CloseableHttpClient httpclient = HttpClients.createDefault(); CloseableHttpResponse httpResponse = httpclient.execute(httpRequest);
替换成
HttpClient httpclient = new DefaultHttpClient(); HttpResponse httpResponse = httpclient.execute(httpRequest);
2.主线程中不可以存在http请求,要另起线程
Runnable runnable = new Runnable() { public void run() { HttpClient.postAndroid("Notification posted 通知标题: " + "通知内容:"); } }; new Thread(runnable).start();
3.本人用的MIUI9系统,会出现每次点进去都要选择权限等一系列问题解决方案如下。
1.设置->更多设置->系统安全->通知使用权
2.软件设为自启动