摘要:本次实现了用户登录注册,将用户保存到Application 里面实现用户持久化,用户有已读消息查看,未读消息查看,发送消息功能,未读消息读取后,添加到已读消息里面,发送消息具有推送功能 可以全部发送,和选择人员发送,发送消息过后,如果当前用户在线会收到一条任务栏通知,点击通知可以查看到该消息,登录App时,APP应用会生成,未读信息角标,(实现了vivo和小米。
流程图:
项目结构
项目使用jar:
项目使用权限:
广播接收器:
android:name="cn.jpush.android.service.PushService"
android:enabled="true"
android:exported="false">
android:name="cn.jpush.android.intent.REGISTER" />
android:name="cn.jpush.android.intent.REPORT" />
android:name="cn.jpush.android.intent.PushService" />
android:name="cn.jpush.android.intent.PUSH_TIME" />
android:name="cn.jpush.android.service.DaemonService"
android:enabled="true"
android:exported="true">
android:name="cn.jpush.android.intent.DaemonService" />
android:name="com.example.pk.tuisong" />
android:name="cn.jpush.android.service.PushReceiver"
android:enabled="true">
android:priority="1000">
android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_PROXY" />
android:name="com.example.pk.tuisong" />
android:name="android.intent.action.USER_PRESENT" />
android:name="android.net.conn.CONNECTIVITY_CHANGE" />
android:name="android.intent.action.PACKAGE_ADDED" />
android:name="android.intent.action.PACKAGE_REMOVED" />
android:scheme="package" />
android:name="cn.jpush.android.ui.PushActivity"
android:configChanges="orientation|keyboardHidden"
android:exported="false"
android:theme="@android:style/Theme.NoTitleBar">
android:name="cn.jpush.android.ui.PushActivity" />
android:name="android.intent.category.DEFAULT" />
android:name="com.example.pk.tuisong" />
android:name="cn.jpush.android.ui.PopWinActivity"
android:configChanges="orientation|keyboardHidden"
android:exported="false"
android:theme="@style/MyDialogStyle">
android:name="android.intent.category.DEFAULT" />
android:name="com.example.pk.tuisong" />
android:name="cn.jpush.android.service.DownloadService"
android:enabled="true"
android:exported="false" />
android:name="cn.jpush.android.service.AlarmReceiver" />
数据表结构:
User表:
字段 |
类型 |
作用 |
备注 |
ID |
Int |
主键,自增长 |
确定每条数据的唯一性 |
Username |
String |
用户名,唯一 |
极光推送的别名 |
Password |
String |
密码 |
|
Xiaoxi表:
字段 |
类型 |
作用 |
备注 |
ID |
Int |
主键 |
确定每条数据的唯一性 |
Username |
String |
用户名 |
确定是哪个用户的消息 |
Xiaoxi |
String |
消息,内容 |
该条消息的内容 |
Biaoti |
String |
消息的标题 |
本条消息的标题 |
实现登录注册,把账号信息发送给服务器,绑定用户,以便后面消息传送操作!
(此功能上次已做!)
消息的传送:
进入该activity时 通过服务器查询出该用户的 已读消息 和未读消息,
点击已读消息时 会跳转到一个listview 里面显示了该用户的已读消息,
点击未读消息的时候 会跳转到一个listview 里面显示了该用户的未读消息,改listview 拥有一个点击事件,当点击某条消息时,会跳转到一个显示页面,显示该条信息,并把该消息的状态改为已读。
Listview的点击事件:
ListView list = (ListView) findViewById(R.id.listwd);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView> arg0, View arg1, int arg2, long arg3) { text=(TextView)arg1.findViewById(R.id.friend_username); String name1 = text.getText().toString(); int aid =text.getId(); Toast.makeText(Unread.this,"ID" + arg2 + "个项目",Toast.LENGTH_SHORT).show(); xiaoxics.setUsername(name); xiaoxics.setBiaoti(name1); xiaoxics.setXiaoxizt(arg2+""); String xiaoxijson = JSON.toJSONString(xiaoxics); Intent intent = new Intent(Unread.this,XianshiXinXi.class); intent.putExtra("shuju",xiaoxijson); startActivity(intent); } });
此处实现了listview里面 拥有一个简单的Textview的点击事件,请勿假如Button,加入Button 此点击事件将无效!
点击发送消息时,会跳到一个全新的activity
在这里 输入消息的标题和内容 点击发送所有人时 会把次消息发送给服务器 服务器保存该消息,并像用户推送
public staticString push(List
User user = new User();
user.setUsername(username1);
user.setPassword(biaoti);
String userjson = JSON.toJSONString(user);
String fhz = "loser";
String masterSecret ="cb79148f2b69efa00dbc16b0";
String appKey = "76a005b037fa2b8194fe412a";
JPushClient jpushClient =new JPushClient(masterSecret,appKey);
PushPayload payload =PushPayload.newBuilder()
.setMessage(Message.content(userjson))
.setPlatform(Platform.android_ios())
.setAudience(Audience.alias(username))
.setNotification(Notification.newBuilder()
.addPlatformNotification(AndroidNotification.newBuilder()
.addExtra("type","传回去的数据)
.setAlert("你有一条新消息")
.build())
.addPlatformNotification(IosNotification.newBuilder()
.addExtra("type","传回去的数据")
.setAlert("你有一条新消息")
.build())
.build())
.setOptions(Options.newBuilder()
.setApnsProduction(false)
.setTimeToLive(90)/
.build())
.build();
点击发送对象时 会把该页面的主题 和内容传到一个新的页面,该页面有一个listview ,该listview 显示了所有的用户名,具有一个多选事件,当选择完用户后,会把主题和内容和用户集合发送给服务器,服务器会根据用户名推送消息。
public class SendOut extends BaseActivity { ListView list; ListuserList,usernamelist = null; Fsong fsong = null; MyHandiler2 myHandiler2; ArrayList , Object>> listData; //适配器 CheckboxAdapter listItemAdapter; String name1=null; TextView buttonfsdxfhsy; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_send_out); buttonfsdxfhsy = (TextView) findViewById(R.id.buttonfsdxfhsy); myHandiler2 = new MyHandiler2(); Intent intent = getIntent(); String fsongjson = intent.getStringExtra("fsong"); fsong = JSON.parseObject(fsongjson, Fsong.class); //反回主页 buttonfsdxfhsy.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent23 = new Intent(SendOut.this,Home_page.class); intent23.putExtra("dxfsfh",fsong.getUsername()); startActivity(intent23); } }); Button getValue = (Button) findViewById(R.id.get_value); getValue.setOnClickListener(listener); //listview list = (ListView) findViewById(R.id.list); //存储数据的数组列表 listData = new ArrayList , Object>>(); //显示所有已读消息 final okHttp ok = new okHttp(); try { new Thread(new Runnable() { @Override public void run() { Message msg = new Message(); try { userList = ok.duxianzs(); msg.what = 1; String listjson = JSON.toJSONString(userList); Bundle bundle = new Bundle(); bundle.putSerializable("list", listjson); msg.setData(bundle); } catch (Exception e) { e.printStackTrace(); } myHandiler2.sendMessage(msg); } }).start(); } catch (Exception e) { e.printStackTrace(); } } //事件响应 View.OnClickListener listener = new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub HashMap , Boolean> state = listItemAdapter.state; List stringlist = new ArrayList() ; String options = "选择的项是:"; for (int j = 0; j < listItemAdapter.getCount(); j++) { System.out.println("state.get(" + j + ")==" + state.get(j)); if (state.get(j) != null) { User user = new User(); @SuppressWarnings("unchecked") HashMap, Object> map = (HashMap , Object>) listItemAdapter.getItem(j); String username = map.get("friend_username").toString(); user.setUsername(username); Log.i("info", "__________________________9527___________________" +username); options+="\n"+"."+username; Log.i("info", "__________________________9527___________________" +options); stringlist.add(user); } } fsong.setUserList(stringlist); Log.i("info", "__________________________9527___________________" +fsong.getXiaoxi()); final okHttp ok = new okHttp(); try { new Thread(new Runnable() { @Override public void run() { Message msg = new Message(); try { String xiaoxi = ok.dxtssj(fsong); msg.what = 2; Bundle bundle = new Bundle(); bundle.putSerializable("xiaoxixi", xiaoxi); Log.i("info", "____________9527______________9527___________________" +xiaoxi); msg.setData(bundle); } catch (Exception e) { e.printStackTrace(); } myHandiler2.sendMessage(msg); } }).start(); } catch (Exception e) { e.printStackTrace(); } } }; //数据的传递 public class MyHandiler2 extends Handler { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 1: String list12 = (String) msg.getData().getSerializable("list"); List userlistqw =JSON.parseArray(list12 , User.class); Log.i("info","____________________________________________________________"+userList.size()); for(int i=0;i<userList.size();i++){ HashMap, Object> map=new HashMap , Object>(); map.put("friend_username",userList.get(i).getUsername()); map.put("selected", false); //添加数据 listData.add(map); } //适配器 listItemAdapter = new CheckboxAdapter(SendOut.this, listData); list.setAdapter(listItemAdapter); break; case 2: String xiaoxixi = (String) msg.getData().getSerializable("xiaoxixi"); Log.i("info","_______________________888____888____888_____________________________"+xiaoxixi); String name =xiaoxixi.substring(0,1); if (name.equals("1")) { Toast.makeText(getApplicationContext(), "发送成功!", Toast.LENGTH_LONG).show(); } else { //显示选择内容 Toast.makeText(getApplicationContext(), "发送失败!", Toast.LENGTH_LONG).show(); } break; } } }
对接收推送回来的数据进行操作:
推送回来的消息会被BroadcastReceiver广播接收,在此广播中队接到的数据进行操作!
public class MyReceiver extends BroadcastReceiver{ String username = null; @Override public void onReceive(Context context, Intent intent) {
//判断是否接收到了数据,并任务栏显示: if (intent.getAction().equals(JPushInterface.ACTION_MESSAGE_RECEIVED)) { Bundle bundle = intent.getExtras(); String title = bundle.getString(JPushInterface.EXTRA_TITLE); String message = bundle.getString(JPushInterface.EXTRA_MESSAGE); username = message; String shuju =bundle.getString("type"); Toast.makeText(context, message, Toast.LENGTH_LONG).show(); Log.i("info","___message_____123_______________________"+bundle.toString()); }
//判断任务栏的推送是否被点击 点击了后的操作! if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(intent.getAction())) { Bundle bundle = intent.getExtras(); int name1=bundle.getInt(JPushInterface.EXTRA_NOTIFICATION_ID); String title = bundle.getString(JPushInterface.EXTRA_TITLE); String name =bundle.getString(JPushInterface.EXTRA_EXTRA); String message = bundle.getString(JPushInterface.EXTRA_MESSAGE); Log.i("info", "用户点击打开了通知--------120----->"+name.toString()); Mapp map =JSON.parseObject(name,Mapp.class); Log.i("info", "用户点击打开了通知--------120----->"+map.toString()); String usernam = map.getType(); Log.i("info", "用户点击打开了通知--------120----->"+usernam);
//点击过后 把推送回来的数据 转发到消息显示页面,让该页面显示此消息! Intent intent1 = new Intent(); intent1.putExtra("cgb",usernam); intent1.setClass(context,Tuisongxianshi.class); intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent1); } }
最后角标的实现:
下面就是手机角标的实现,只需要得到未读消息的条数,然后传入这两个方法就行
//获取手机品牌 String phoneName = android.os.Build.MODEL;
//vivo 角标设置
if(phoneName.equals("vivo Y51")){ Intent intent2 = new Intent("launcher.action.CHANGE_APPLICATION_NOTIFICATION_NUM"); intent2.putExtra("packageName",packageName); String launchClassName =lancherActivityClassName; intent2.putExtra("className", launchClassName); //显示的角标数! intent2.putExtra("notificationNum",a); sendBroadcast(intent2); } //小米角标判断 else{ try { Field field = notification.getClass().getDeclaredField("extraNotification"); Object extraNotification = field.get(notification); Method method = extraNotification.getClass().getDeclaredMethod("setMessageCount", int.class); method.invoke(extraNotification, a); } catch (Exception e) { e.printStackTrace(); } mNotificationManager.notify(0, notification); }
角标的实现:
每种手机品牌的角标实现方法并不一致,有的手机根本不支持角标,所以针对各种手机角标的问题,需要写入大量的代码,有的手机角标Dome 十分难找,所以写起来十分困难!
华为角标:
华为的角标只对大型的某些应用开发,所以在这里无法实现!
从保护用户体验的角度出发,华为角标暂时只对较大型的纯即时通讯类应用(例:聊天工具、邮箱)和大型企业的内部办公应用开放,还请各位开发者谅解!
Listview 的点击事件:
网上有很多 listview的点击Dome 但是并不都适用,这要看你listview里面的布局是什么样子的,如果只是简单的Textview 就可以直接 listview的对象点setOnItemClickListener(newAdapterView.OnItemClickListener()来实现点击事件,如果要加入Button等有需要另外的方法!
BroadcastReceiver 的取值问题:
当点击任务栏 进入if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(intent.getAction())) {
后,并取不到message 里面的值,最好吧 bundle。toString打印出来看一下,看里面传过来的究竟是什么,应为上面个IF取到了值,所以很容易忽略下面的if里面有可能是取不到值的,如果 不小心这里会怎么都找不出错来!
Intent 跳转新页面时,加入
intent1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK| Intent.FLAG_ACTIVITY_NEW_TASK);
这句!每次清除前面的activity ,让后面点击返回按钮时 会打开新的activity 这样让数据刷新!
列如:
Intent intent1 =new Intent(Tuisongxianshi.this,Home_page.class);
intent1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK| Intent.FLAG_ACTIVITY_NEW_TASK);
intent1.putExtra("tuisfh",name1);
startActivity(intent1);
实现BroadcastReceiver 接收到通知就更新 未读消息条数:
先在Home_page中 定义一个instance的成员变量!
staticHome_page instance;
然后在
protected voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_page);
instance = this;
在写一个instance的get方法:
public staticHome_page getInstance(){
return instance;
}
在BroadcastReceiver 中 得到消息的地方:
public voidonReceive(Context context,Intent intent) {
if (intent.getAction().equals(JPushInterface.ACTION_MESSAGE_RECEIVED)) {
Home_page.getInstance().runOnUiThread(newRunnable() {
@Override
public void run() {
// TODOAuto-generated method stub
//Toast.makeText(MessSendActivity.getInstance(),
// "frommessSend", 1).show();
TextView pb = (TextView) Home_page
.getInstance().findViewById(R.id.textViewjiaobiao);
String jiaobiaoshu = (String) pb.getText();
int a=Integer.parseInt(jiaobiaoshu);
pb.setText((a+1)+"");
}
});
}
就可以更新UI了!