-
安卓Android studio开发基础服务与广播功能的实现
2020-12-26 12:29:11安卓课上的第三个实验,对服务与广播功能的基本原理实现 即,模拟一个简单的功能页面,当默认状态下(没有短信接收时),一旦收到短信(相当于触发系统广播),激活改功能的音乐播放,此外,额外设定音乐播放的停止...安卓课上的第三个作业,对服务与广播功能的基本原理实现
即,模拟一个简单的功能页面,当默认状态下(没有短信接收时),一旦收到短信(相当于触发系统广播),激活改功能的音乐播放,此外,额外设定音乐播放的停止按钮作为功能的完善。
其中,【整体代码文件结构】:
其中,activity_main.xml的内容:
他构建的是一个按钮,在默认的时候是灰色,当有短信发送过来触发点亮,然后点击这个按钮再度变灰。
Mainactivity.java的内容:
在没有短信被接受时,按钮是默认的灰色,即iscast=false,这时的按钮亦是不可被点击使用的,当接受到短信,触发了音乐的播放后变为可用,这时可以点击按钮来关闭音乐的播放。
这里亦需要申请权限,需要在AndroidManified.xml做对应的注册。
MyAudioService.java:
实现当接受到短信后即刻触发播放对应路径里的音乐文件,当按钮被点击后即可停止播放的功能,他们同样需要在AndroidManifield.xml里进行注册。
SMSReceiver.java:
5、结果截图
运行,一开始默认的没有接受到短信的情况:
给自己发送短信:
切换到刚才的程序里,可以看见按钮变为可用,音乐正在播放
点击这个按钮,停止音乐播放
关于这个模拟实验的总结:
这个实验总体相对之前的还是比较容易,不过做的时候中间有遇到了一些AS自身的BUG,搞了半天,通过这次实验对androidmanifest.xml的作用也有了了解。
这个代码的代码仓库:https://gitee.com/mai-shiranui/broadcast -
AndroidStudio简单计算器的实现
2021-01-20 08:51:04首先此项目是本人学校安卓开发的一次作业,用Android Studio开发一个简单的计算器,这个计算器正常的功能为带括号的加减乘除多项式计算! 界面展示 废话不多说先展示一下界面!(模仿了小米计算器),有两种方式添加... -
android studio简单的密码日记本,实现增删改查功能
2019-06-23 16:06:21软件功能 :简单的密码日记本,实现增删改查功能 软件的使用知识点: 布局方面:线性布局,相对布局 控件方面:常见控件,List View, Navigation View(滑动菜单),FloatingActionButton (悬浮按钮) ...简单的记事本
软件名字:一本日记
软件功能 :简单的密码日记本,实现增删改查功能
软件的使用知识点:
布局方面:线性布局,相对布局
控件方面:常见控件,List View, Navigation View(滑动菜单),FloatingActionButton (悬浮按钮)
后台方面:主要是Adapter和Sq Lite,Intent
项目的结构如下图:
[外链图片转存失败(img-OocaH9L5-1563628277567)(C:\Users\weng\Desktop\安卓期末1.png)]
分析软件的组成:
展示核心的代码
1,登录
<EditText android:id="@+id/edt_username"------请输入昵称 android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:inputType="text" android:hint="请输入昵称" android:padding="5dp"/> <EditText android:id="@+id/edt_password"----------密 码 android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:inputType="textPassword" android:hint="请输入密码" android:padding="5dp"/> <Button android:id="@+id/btn_login"----------登录 android:layout_below="@+id/line_password" android:layout_width="80dp" android:layout_marginTop="40dp" android:layout_marginLeft="60dp" android:text="登 录" android:background="@android:color/white" android:textSize="24sp" android:layout_height="60dp" /> <Button android:id="@+id/btn_go_register"----------注册 android:layout_below="@+id/line_password" android:layout_toRightOf="@+id/btn_login" android:layout_width="80dp" android:layout_marginTop="40dp" android:layout_marginLeft="80dp" android:text="注 册" android:background="@android:color/white" android:textSize="24sp" android:layout_height="60dp" /> 登录的业务逻辑: ```java public class LoginActivity extends AppCompatActivity { public static int userID; public static String username; String name, password;//保存数据 private EditText edt_username;//用户名字 private EditText edt_password;//用户密码 private Button btn_login; private Button btn_register; //private SQLiteDatabase sqlDate; private MyDB myDB; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//隐藏状态栏 getSupportActionBar().hide();//隐藏标题栏 setContentView(R.layout.activity_main); initUI(); myDB = new MyDB(this);//创建对象 //注册 btn_register.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(LoginActivity.this, RegistActivity.class); startActivityForResult(intent,1); } }); //登入 btn_login.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { name = edt_username.getText().toString(); password = edt_password.getText().toString(); if (enter(name, password)) { Toast.makeText(LoginActivity.this, "登录成功" + name, Toast.LENGTH_SHORT).show(); new Thread(){ public void run() { try { Thread.sleep(1000); Intent intent1 = new Intent(LoginActivity.this, IndexActivity.class); startActivity(intent1); } catch (Exception e) { e.printStackTrace(); } } }.start(); } else if (TextUtils.isEmpty(name) || TextUtils.isEmpty(password) || TextUtils.isEmpty(name) && TextUtils.isEmpty(password)) { Toast.makeText(LoginActivity.this, "请输入用户名或密码", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(LoginActivity.this, "登入失败", Toast.LENGTH_SHORT).show(); } } }); } /** * 初始化:initUI() */ private void initUI() { edt_username = (EditText) findViewById(R.id.edt_username); edt_password = (EditText) findViewById(R.id.edt_password); btn_login = (Button) findViewById(R.id.btn_login); btn_register = (Button) findViewById(R.id.btn_go_register); } /** * 判断是否username,password 和数据库的相同 enter() */ public boolean enter(String name, String password) { SQLiteDatabase db = myDB.getWritableDatabase(); String sql = "select user_id from tb_user where username=? and password=?"; Cursor cursor = db.rawQuery(sql, new String[]{name, password}); if (cursor.getCount() != 0) {//返回Cursor 中的行数 if (cursor.moveToNext()) { userID = cursor.getInt(cursor.getColumnIndex("user_id")); username = name; } cursor.close(); return true; } return false; } /** * 数据回显 * @param requestCode * @param resultCode * @param data */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode==1 && resultCode==1){ String name=data.getStringExtra("name"); String password=data.getStringExtra("password"); edt_username.setText(name); edt_password.setText(password); } } }
2注册
<EditText android:id="@+id/edt_setusername"-------名字 android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:inputType="text" android:hint="请输入昵称:" android:padding="5dp"/> <EditText android:id="@+id/edt_setpassword"---------密码 android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:inputType="textPassword" android:hint="请输入密码" android:padding="5dp"/> <EditText android:id="@+id/edt_confirm_password"----确认密码 android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:inputType="textPassword" android:hint="请输入密码" android:padding="5dp"/> <Button android:id="@+id/btn_register"---------注册 android:layout_below="@+id/line_confirm_pwd" android:layout_width="match_parent" android:layout_marginTop="30dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:background="@android:color/white" android:text="确定注册" android:textSize="16sp" android:layout_height="45dp" />
注册的业务逻辑:
public class RegistActivity extends AppCompatActivity { private EditText edt_setname; private EditText edt_setpassword; private EditText edt_confirm_password; private Button btn_register; String name,password,id; private MyDB myDB; ContentValues contentValues=new ContentValues(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//隐藏状态栏 getSupportActionBar().hide();//隐藏标题栏*/ setContentView(R.layout.activity_regist); initUI(); myDB=new MyDB(this); btn_register.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { SQLiteDatabase db=myDB.getWritableDatabase(); name = edt_setname.getText().toString(); password = edt_setpassword.getText().toString(); if (edt_setname.getText().toString().contains(" ") || edt_setpassword.getText().toString().contains(" ")) { Toast.makeText(RegistActivity.this, "输入的用户名或密码不能包含空格", Toast.LENGTH_SHORT).show(); return; } else if(edt_setpassword.getText().toString().length()==0||edt_setname.getText().toString().length()==0){ Toast.makeText(RegistActivity.this, "请输入用户名或密码", Toast.LENGTH_SHORT).show(); return; } else if(!edt_confirm_password.getText().toString().equals(edt_setpassword.getText().toString())){ Toast.makeText(RegistActivity.this, "两次密码不一致,请确认再注册", Toast.LENGTH_SHORT).show(); return; } if(login(name)){ Toast.makeText(RegistActivity.this, "该用户名已注册", Toast.LENGTH_SHORT).show(); return; } contentValues.put("username", name); contentValues.put("password", password); db.insert("tb_user", null, contentValues); String sql="select user_id from tb_user where username=? and password=?"; Cursor cursor = db.rawQuery(sql, new String[] {name, password}); if(cursor.moveToNext()){//id id=Integer.toString(cursor.getInt(0));//防止数据库的值null和0 分不清 } cursor.close(); db.close(); Toast.makeText(RegistActivity.this, "注册成功", Toast.LENGTH_SHORT).show(); new Thread(){ @Override public void run() { super.run(); try { Thread.sleep(1000); Intent intent = new Intent(RegistActivity.this,LoginActivity.class); intent.putExtra("name",edt_setname.getText().toString()); intent.putExtra("password",edt_setpassword.getText().toString()); setResult(1, intent);//返回页面1 finish(); // startActivity(intent); } catch (InterruptedException e) { e.printStackTrace(); } } }.start(); } }); } /** * 初始化View :initUI() */ public void initUI(){ edt_setname=(EditText)findViewById(R.id.edt_setusername); edt_setpassword=(EditText)findViewById(R.id.edt_setpassword); edt_confirm_password=(EditText)findViewById(R.id.edt_confirm_password); btn_register=(Button)findViewById(R.id.btn_register); } /** * 查询数据库是否有重复的 * 进行数据的查询 login() */ public boolean login(String name){ SQLiteDatabase db=myDB.getWritableDatabase(); String sql="select * from tb_user where username=?"; Cursor cursor=db.rawQuery(sql,new String[]{name}); if (cursor.getCount()!=0){ cursor.close(); return true; } return false; } }
3主页面
<ListView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="wrap_content" > </ListView> <android.support.design.widget.FloatingActionButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginBottom="30dp" android:layout_marginRight="20dp" app:fabSize="mini" app:srcCompat="@android:drawable/ic_input_add" android:id="@+id/floactAdd" app:backgroundTint="@color/colorPrimaryDark" /> </RelativeLayout> <android.support.design.widget.NavigationView android:layout_gravity="left" app:headerLayout="@layout/head" app:menu="@menu/meun_main" android:id="@+id/navigat" android:layout_width="230dp" android:layout_height="match_parent"/>
主页面的业务逻辑:
public class IndexActivity extends AppCompatActivity { List<Note> mList; private FloatingActionButton fdb; private NavigationView navigationView; private ListView listView; private MyAdapter myAdapter; private MyDB myDB; private Cursor cursor; private SQLiteDatabase dbreader;; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//隐藏状态栏 getSupportActionBar().hide();//隐藏标题栏 setContentView(R.layout.activity_test); listView = (ListView) findViewById(R.id.list); navigationView = (NavigationView) findViewById(R.id.navigat); View view1 = navigationView.getHeaderView(0);//通过nav来查询head文件 TextView wc = view1.findViewById(R.id.welcome); myDB = new MyDB(this); dbreader = myDB.getReadableDatabase(); wc.setText("欢迎你:" + LoginActivity.username); Toast.makeText(IndexActivity.this, "登录成功,欢迎回来!", Toast.LENGTH_SHORT).show(); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) { Intent intent = new Intent(IndexActivity.this, showActivity.class); intent.putExtra("ID", mList.get(position).getId()); intent.putExtra("content", mList.get(position).getContent()); intent.putExtra("time", mList.get(position).getTime()); startActivity(intent); } }); fdb = (FloatingActionButton) findViewById(R.id.floactAdd); fdb.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(IndexActivity.this, AddContentActivity.class); startActivity(intent); } }); navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { switch (item.getItemId()){ case R.id.prsetposs: Intent intent1=new Intent(IndexActivity.this,setpasswordActivity.class); intent1.putExtra("username",LoginActivity.username); startActivity(intent1); break; case R.id.showtime: Toast.makeText(IndexActivity.this,AddContentActivity.getTime(),Toast.LENGTH_LONG).show(); break; case R.id.prsize: Toast.makeText(IndexActivity.this,IndexActivity.this.allDBNum() + "个用户使用了软件",Toast.LENGTH_LONG).show(); break; case R.id.success: Intent intent=new Intent(IndexActivity.this,LoginActivity.class); Toast.makeText(IndexActivity.this,"退出成功",Toast.LENGTH_LONG).show(); startActivity(intent); } return true; } }); } public void selectDb() { mList = new ArrayList<>(); cursor = dbreader.rawQuery("SELECT * FROM tb_note WHERE userID = ?", new String[]{LoginActivity.userID + ""}); while (cursor.moveToNext()) { Note note = new Note(); int id = cursor.getInt(cursor.getColumnIndex("ID")); String time = cursor.getString(cursor.getColumnIndex("time")); String content = cursor.getString(cursor.getColumnIndex("content")); note.setTime(time); note.setContent(content); note.setId(id); mList.add(note); } cursor.close(); myAdapter = new MyAdapter(this, mList); listView.setAdapter(myAdapter); } @Override protected void onResume() { super.onResume(); selectDb(); } /** *查询用户的个数 allDBNum() */ public int allDBNum( ){ String sql = "select count(*) count from tb_user"; Cursor cursor = dbreader.rawQuery(sql, null); cursor.moveToFirst(); int count= cursor.getInt(0); if (cursor.getCount()!=0){ cursor.close(); } return count; } }
4 List View 布局:
<LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:layout_gravity="center_vertical" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/list_content" android:textColor="#000" android:textSize="20sp" android:text="tv"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/list_time" android:textColor="#000" android:textSize="20sp" android:text="time"/> </LinearLayout>
5List View适配器:
public class MyAdapter extends BaseAdapter { private Context mContext; private List<Note> mList; private LinearLayout mlayout; public MyAdapter(Context mContext, List<Note> mList){ this.mContext=mContext; this.mList=mList; } @Override public int getCount() { return mList.size(); } @Override public Object getItem(int position) { return mList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = LayoutInflater.from(mContext); mlayout=(LinearLayout) inflater.inflate(R.layout.listre,null); TextView content=(TextView)mlayout.findViewById(R.id.list_content); TextView time=(TextView)mlayout.findViewById(R.id.list_time); content.setText(mList.get(position).getContent()); time.setText(mList.get(position).getTime()); return mlayout; } }
6数据库文件:
ublic class MyDB extends SQLiteOpenHelper{ //用户表 public static final String CREATE_USER="create table tb_user(" + "user_id integer primary key autoincrement," + "username varchar(50)," + "password varchar(50))"; // public static final String CREATE_NOTE="create table tb_note("+ "ID integer primary key AUTOINCREMENT,"+ "content TEXT NOT NULL,"+ "userID integer,"+ "time TEXT NOT NULL)"; //上下文 private Context mcontext; public static final String CREATE_NOTES=""; public MyDB(Context context) { super(context, "MyDB.db", null, 2); mcontext=context; } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_USER); db.execSQL(CREATE_NOTE); Toast.makeText(mcontext,"创建成功!",Toast.LENGTH_SHORT).show(); } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { } }
7Note的实体类:
public class Note { private Integer id; private Integer userID; private String content; private String time; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getUserID() { return userID; } public void setUserID(Integer userID) { this.userID = userID; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getTime() { return time; } public void setTime(String time) { this.time = time; } }
8添加内容的页面:
<EditText android:id="@+id/text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="top" android:hint="开始记录吧"/> <Button android:id="@+id/save" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="保存" android:onClick="save"/> <Button android:id="@+id/cancle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="取消" android:onClick="cancle"/>
添加内容的业务逻辑:
private EditText met; private MyDB myDB; private SQLiteDatabase mysqldb; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//隐藏状态栏 getSupportActionBar().hide();//隐藏标题栏 setContentView(R.layout.activity_add_content); met=(EditText)findViewById(R.id.text); myDB=new MyDB(this); mysqldb=myDB.getWritableDatabase(); } public void save(View v) { DdAdd(); finish(); } public void cancle(View v) { met.setText(""); finish(); } public void DdAdd(){ ContentValues cv = new ContentValues(); cv.put("content",met.getText().toString()); cv.put("time",getTime()); cv.put("userID", LoginActivity.userID); mysqldb.insert("tb_note",null,cv);//插入数据 } public static String getTime(){ SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); Date date=new Date(); String str=sdf.format(date); return str; }
9显示内容的页面:
<TextView android:id="@+id/showtime" android:layout_width="match_parent" android:layout_height="30dp" android:layout_marginLeft="10dp" android:textSize="20sp"/> <EditText android:id="@+id/showtext" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="20sp" android:gravity="top" android:layout_weight="1" android:layout_marginTop="10dp" android:layout_marginLeft="10dp" android:textColor="#000" android:hint="记事本"/> <Button android:id="@+id/delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="删除" android:onClick="delete"/> <Button android:id="@+id/update" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="修改" android:onClick="update" /> <Button android:id="@+id/back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="返回" android:onClick="goBack"/> </LinearLayout>
显示页面的业务逻辑:
public class showActivity extends AppCompatActivity { private EditText mtext; private TextView time; private MyDB myDB; private SQLiteDatabase msql; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//隐藏状态栏 getSupportActionBar().hide();//隐藏标题栏 setContentView(R.layout.activity_show); mtext=(EditText) findViewById(R.id.showtext); time=(TextView)findViewById(R.id.showtime); myDB=new MyDB(this); msql=myDB.getWritableDatabase(); mtext.setInputType(InputType.TYPE_CLASS_TEXT);//开启可以编写 mtext.setText(getIntent().getStringExtra("content")); time.setText(getIntent().getStringExtra("time")); } /** * 删除 delete * @param v */ public void delete(View v) { int id = getIntent().getIntExtra("ID",0); msql.delete("tb_note","ID = " + id,null); finish(); /** * 修改 update */ }public void update(View v){ int id = getIntent().getIntExtra("ID",0); String content=mtext.getText().toString(); msql.execSQL("UPDATE tb_note SET content=? WHERE ID = ?", new String[]{content,id+""}); finish(); } /** * 关闭 * @param v */ public void goBack(View v) { finish(); } }
10修改密码的页面:
<TextView android:layout_marginTop="-120dp" android:text="修改密码" android:textSize="34dp" android:layout_marginBottom="20dp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <EditText android:id="@+id/setpass" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="输入新密码" /> <Button android:id="@+id/yes" android:text="确定" android:layout_width="wrap_content" android:layout_height="match_parent" android:onClick="yes"/> <Button android:id="@+id/no" android:text="取消" android:layout_width="wrap_content" android:layout_height="match_parent" android:onClick="no"/> </LinearLayout>
修改密码的业务逻辑:
public class setpasswordActivity extends AppCompatActivity { private EditText setpass; private MyDB myDB; private SQLiteDatabase msql; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//隐藏状态栏 getSupportActionBar().hide(); setContentView(R.layout.activity_setpassword); myDB=new MyDB(this); msql=myDB.getWritableDatabase(); setpass=(EditText)findViewById(R.id.setpass); } public void yes(View v){ String username = getIntent().getStringExtra("username"); String pass=setpass.getText().toString(); msql.execSQL("UPDATE tb_user SET password=? WHERE username=?", new String[]{pass,username}); Toast.makeText(setpasswordActivity.this, "密码修改完了,请记住现在的密码", Toast.LENGTH_SHORT).show(); Intent intent2=new Intent(setpasswordActivity.this,LoginActivity.class); startActivity(intent2); finish(); } public void no(View v){ Intent intent=new Intent(setpasswordActivity.this,IndexActivity.class); startActivity(intent); finish(); } }
软件的展示图片:
登录:
注册:
主页面
主页面2
添加
修改
-
基于mysql-android studio-web服务器实现简单注册登录功能源码与解析
2018-04-25 15:49:38此资源实现安卓APP注册登录功能,通过Android Studio编写界面和相应功能,用Eclipse开启web服务器进行客户端与服务端之间的通信,并且将用户的账户密码经过MD5的加密后存入Mysql数据库中。 -
安卓后台服务相关-可以实现service后台运行自启动隐藏安装图标相当简单易懂studio直接导就行.rar
2019-07-29 16:15:49可以实现service后台运行,自启动,隐藏安装图标,相当简单易懂,studio直接导就行.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。 -
Unity与安卓之间的相互通信的简单实现
2020-02-13 17:43:352:要实现的功能: 要在unity项目中进行安卓功能扩展,有两种方式: 1、Unity项目导出为Android工程,然后在Android Studio(以后简称为AS)中进行二次开发,添加扩展功能。这样的方式开发起来很灵活,改动起来也...1:开发的准备工作;
Unity5.6.6
AndroidStudio3.5.3:关于android安装收藏了两篇博文
JDK
安卓SDK
2:要实现的功能:
要在unity项目中进行安卓功能扩展,有两种方式:
1、Unity项目导出为Android工程,然后在Android Studio(以后简称为AS)中进行二次开发,添加扩展功能。这样的方式开发起来很灵活,改动起来也很方便,但是就是很麻烦,因为每次改动都要打一回安卓工程。
2、将扩展功能制作成Android库文件(jar包),然后将jar包导入到Unity中,直接使用。这样的方式,使用者无法修改这个库文件的功能,但也更便于使用 。
因为我将要做的功能可能会在团队内传播使用,也不需要每个人都去做改动。因此选择第二种方式。
制作一个Android库文件(jar包),然后在Unity中使用它。
3:制作安卓Jar包:
1:新建一个android工程:
打开AS,新建一个android工程;选择Empty Activity
2:创建一个Android Library模块
选中app,然后右键,选Module,在Create New Module窗口中选择 Android Library
3:引入Unity中的Class.jar库
1)在unity的安装目录下件,找到一个名为classes.jar的文件
我的目录为 D:\Unity2018\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Development\Classes
2)然后将classes.jar粘贴到mysdk模块的libs目录下(需要将工程切换到project视图)
3)选中刚粘贴的classes.jar文件,右键,选择 Add as Library,出现一个弹窗口,默认选中mysdk模块,直接点确定
然后,这个classes.jar文件就被引入到工程中了,展开三角,可以看到如下三个模块,其中就有com.unity3d.player。如下
4):创建本模块的Activity文件
5):编写SDKMainActivity脚本
package com.xiexianzhong.mysdk; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.widget.Toast; import com.unity3d.player.UnityPlayer; import com.unity3d.player.UnityPlayerActivity; public class SDKMainActivity extends UnityPlayerActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } //unity调用Android public void UnityCallAndroid () { Toast.makeText(this,"unity调用android成功", Toast.LENGTH_LONG).show(); AndroidCallUnity(); } //android调用unity public void AndroidCallUnity () { //第1个参数为Unity场景中用于接收android消息的对象名称 //第2个参数为对象上的脚本的一个成员方法名称(脚本名称不限制) //第3个参数为unity方法的参数 UnityPlayer.UnitySendMessage("receiveObj", "UnityMethod", "This is args."); } }
6):将模块进行打包,在Build.gradle下输入如下代码
//----------------这是一组将module导出为jar的gradle命令------------------- // mysdk为自定义的jar包名称 //task to delete the old jar task deleteOldJar(type: Delete) { delete 'release/mysdk.jar' } //task to export contents as jar task exportJar(type: Copy) { from('build/intermediates/packaged-classes/release/') into('release/') include('classes.jar') ///Rename the jar rename('classes.jar', 'mysdk.jar') } exportJar.dependsOn(deleteOldJar, build) //---------------------------命令结束------------------------------
这组命令的功能就是打包方法1的自动化版。
build.gradle文件修改后,会提示要求同步,直接同步即可。同步结束,在IDE右上点开Gradle窗口,在other下找到 exportJar命令。
7):修改AndroidManifest.xml文件
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xiexianzhong.mysdk"> <!-- 这个android:label设置后,unity中ProductName就不生效了,记得改这个--> <application android:label="MySDK"> <!-- 这个android:name的值必须为包名+类名--> <activity android:name="com.xiexianzhong.mysdk.SDKMainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <!-- 这一行不能少,否则会闪退--> <meta-data android:name="unityplayer.UnityActivity" android:value="true" /> </activity> </application> </manifest>
8):到这里就可以将Jar包和androidMainfest拷贝出来了
2:在Unity使用Jar包;
1:正常新建一个Unity工程
a.新建一个Unity工程,在Assets目录下新建Plugins/Android/bin目录。
b.将第三步修改的AndroidManifest.xml文件拷贝到Assets/Plugins/Android目录下
c.将第三步生成的mysdk.jar文件拷贝到Assets/Plugins/Android/bin目录下
完成之后文件结构图如下:
2:编写AndroidTest脚本
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class AndroidTest : MonoBehaviour { private AndroidJavaClass jc; private AndroidJavaObject m_activity; public GameObject petObj; private Animation anim; public Button btn; // Use this for initialization void Start() { // 获取自己定义的Activity的实例 jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); m_activity = jc.GetStatic<AndroidJavaObject>("currentActivity"); btn.onClick.AddListener(OnBtnClick); anim = petObj.GetComponent<Animation>(); } public void UnityMethod(string msg) { Debug.Log(msg); anim.Play("Idle"); } //测试按钮的点击方法 没点击一次就调用一次android的方法 public void OnBtnClick() { Debug.Log("-----------"); //调用MyTestActivity的UnityCall方法 m_activity.Call("UnityCallAndroid"); } }
3:出包测试
-
Android AIDL简单实现(Android Studio环境)
2016-08-03 10:29:44简单实现 AIDL(进程间通信) aidl应用场景,因为安卓不同的应用运行在不同的进程,不能共享内存。当一个项目实现某一部分功能时依赖于另一个项目时候我们就可以用aidl来实现。 下面实现一个模拟远程的登陆操作,...简单实现 AIDL(进程间通信)
aidl应用场景,因为安卓不同的应用运行在不同的进程,不能共享内存。当一个项目实现某一部分功能时依赖于另一个项目时候我们就可以用aidl来实现。
下面实现一个模拟远程的登陆操作,登陆成功返回用户信息,登陆失败返回错误信息。
正确的用户名:user,密码:123456
实现方式:
先建立客户端或者服务端都可以,但是两个AIDL文件的包名等必须完全一致。
1、客户端:
建立.aidl文件,文件目录如下:
文件内容如下:
// ILoginInterface.aidl package com.demo.jinjin.aidlclient; // Declare any non-default types here with import statements interface ILoginInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); String login(String user,String pwd); }
此时编译项目,即可在generated目录下生成相应的java文件,目录如下:打开文件,可看到文件内容如下:
/* * This file is auto-generated. DO NOT MODIFY. * Original file: E:\\MyBase\\AIDLClient\\app\\src\\main\\aidl\\com\\demo\\jinjin\\aidlclient\\ILoginInterface.aidl */ package com.demo.jinjin.aidlclient; // Declare any non-default types here with import statements public interface ILoginInterface extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.demo.jinjin.aidlclient.ILoginInterface { private static final java.lang.String DESCRIPTOR = "com.demo.jinjin.aidlclient.ILoginInterface"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.demo.jinjin.aidlclient.ILoginInterface interface, * generating a proxy if needed. */ public static com.demo.jinjin.aidlclient.ILoginInterface asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof com.demo.jinjin.aidlclient.ILoginInterface))) { return ((com.demo.jinjin.aidlclient.ILoginInterface)iin); } return new com.demo.jinjin.aidlclient.ILoginInterface.Stub.Proxy(obj); } @Override public android.os.IBinder asBinder() { return this; } @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_basicTypes: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); long _arg1; _arg1 = data.readLong(); boolean _arg2; _arg2 = (0!=data.readInt()); float _arg3; _arg3 = data.readFloat(); double _arg4; _arg4 = data.readDouble(); java.lang.String _arg5; _arg5 = data.readString(); this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5); reply.writeNoException(); return true; } case TRANSACTION_login: { data.enforceInterface(DESCRIPTOR); java.lang.String _arg0; _arg0 = data.readString(); java.lang.String _arg1; _arg1 = data.readString(); java.lang.String _result = this.login(_arg0, _arg1); reply.writeNoException(); reply.writeString(_result); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.demo.jinjin.aidlclient.ILoginInterface { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(anInt); _data.writeLong(aLong); _data.writeInt(((aBoolean)?(1):(0))); _data.writeFloat(aFloat); _data.writeDouble(aDouble); _data.writeString(aString); mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } @Override public java.lang.String login(java.lang.String user, java.lang.String pwd) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); java.lang.String _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(user); _data.writeString(pwd); mRemote.transact(Stub.TRANSACTION_login, _data, _reply, 0); _reply.readException(); _result = _reply.readString(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_login = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); } /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException; public java.lang.String login(java.lang.String user, java.lang.String pwd) throws android.os.RemoteException; }
这个文件内容我们不许要做过多的关注。下面进行远程服务的绑定:
private ILoginInterface iLoginInterface; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { iLoginInterface = ILoginInterface.Stub.asInterface(service); LoginPresenter presenter = new LoginPresenter(MainActivity.this); presenter.login(iLoginInterface); unbindService(connection); } @Override public void onServiceDisconnected(ComponentName name) { connection = null; } };
bindService( new Intent("com.demo.jinjin.aidlserver"),connection, Context.BIND_AUTO_CREATE);
绑定成功之后进行登陆操作,登陆操作完成之后记得解绑,注意此处的intent的action与服务端service注册的action要保持一致。这块采用的是MVP的模式,所以登陆的具体方法在model中,通过presenter实现调度。
presenter如下:
public void login(ILoginInterface iLoginInterface){ LoginModel loginModel = new LoginModel(); try { loginModel.lolgin(iLoginView.getUser(), iLoginView.getPwd(),iLoginInterface, new OnLoginFinish() { @Override public void loginSuccess(User user) { iLoginView.showSnackBar(user.getUser()); } @Override public void loginFailed(String error) { iLoginView.showSnackBar(error); } }); } catch (RemoteException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } }
model如下:@Override public void lolgin(String user, String pwd, ILoginInterface iLoginInterface, OnLoginFinish onLoginFinish) throws RemoteException, JSONException { String result = iLoginInterface.login(user,pwd); Log.e("test","---------->" + result); JSONObject object = new JSONObject(result); if (100 ==object.getInt("result_code")){ JSONObject object1 = object.getJSONObject("result_info"); User user1 = new User(); user1.setUser(object1.getString("user")); user1.setPwd(object1.getString("pwd")); onLoginFinish.loginSuccess(user1); }else { onLoginFinish.loginFailed("用户名,密码错误"); } }
即可实现远程的登陆操作。2、服务端实现:
将客户端的aidl目录整体拷贝到服务端,如下:
之后对代码进行编译,生成相应的java目录:
下面进行远程service的定义,如下:
package com.demo.jinjin.aidlserver; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.support.annotation.Nullable; import android.util.Log; import com.demo.jinjin.aidlclient.ILoginInterface; import org.json.JSONException; import org.json.JSONObject; /** * Created by linkmax on 2016/8/2. */ public class LoginService extends Service { private static final String TAG = "AIDLService"; private void Log(String str){ Log.e(TAG,"----------" + str + "----------"); } public void onCreate(){ Log.e(TAG,"service created"); } public void onStart(Intent intent, int startId){ Log.e(TAG,"service started id = " + startId); } @Nullable @Override public IBinder onBind(Intent t){ Log.e(TAG,"service on bind"); return mBinder; } public void onDestroy(){ Log.e(TAG,"service on destroy"); super.onDestroy(); } public boolean onUnbind(Intent intent){ Log.e(TAG,"service on unbind"); return super.onUnbind(intent); } public void onRebind(Intent intent){ Log.e(TAG,"service on rebind"); super.onRebind(intent); } private final ILoginInterface.Stub mBinder = new ILoginInterface.Stub() { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } @Override public String login(String user, String pwd) throws RemoteException { if ("user".equals(user) && "123456".equals(pwd)){ JSONObject object = new JSONObject(); try { JSONObject object1 = new JSONObject(); object1.put("user","server_user"); object1.put("pwd","server_123456"); object.put("result_code",100); object.put("result_info",object1); } catch (JSONException e) { e.printStackTrace(); } return object.toString(); }else { JSONObject object = new JSONObject(); try { JSONObject object1 = new JSONObject(); object1.put("user","server_error"); object1.put("pwd","server_error"); object.put("result_code",200); object.put("result_info",object1); } catch (JSONException e) { e.printStackTrace(); } return object.toString(); } } }; }
最后进行远程service的注册,如下:<service android:name=".LoginService"> <intent-filter> <action android:name="com.demo.jinjin.aidlserver"/> </intent-filter> </service>
注意,两边的action需要保持一致。此时启动客户端与服务端即可实现远程的登陆操作。
源码下载:源码
-
安卓实战项目-动态桌面-简单实现
2017-10-11 16:13:25先上效果图 准备:1,桌面是一个小视频,要求,...前言:对于动态的壁纸大部分手机厂商还是保留的,不过发现oppo某一款就没有这个功能了,不过丝毫不影响本应用的开发,它只是在没做动态壁纸的界面而已,系统还是... -
Android Studio 入门:(三) RecyclerView简单实现
2020-03-18 22:01:32(安卓直接连接数据库存在安全隐患) 一、实现效果 抖动手机,可以随机获取数据库里的某条数据。 二、编码思路 (1)手机抖动功能+本地模拟数据验证效果 (2)Python后台搭建 (3)OKhttp的知识了解与运用 三... -
Android Studio-手把手教你基于SQLLITE实现登录注册功能
2019-12-19 14:30:03其实安卓的登录注册,和JAVA是一样的,甚至于是极简版的JAVA登录注册,安卓太智能了,数据保存在sqllite中,完全不需要导包,而且还伴有可视化界面,简直无敌,安卓可以说是目前我们学过的最简单的语言,只是大家... -
安卓–Navigation的简单使用
2021-01-03 18:16:16上一篇文章记录了底部导航栏BottomNavigationBar的简单使用,这篇文章将会将BottomNavigationBar+Navigation结合使用,点击导航栏不同按钮显示不同的页面,这个功能实现也可以用ViewPager实现。想要使用navigation,... -
基于android Studio的安卓软件接入机智云
2020-01-28 18:26:29我使用的方法是:使用一个机智云的开源框架,(相当于是一个协议栈),对源码进行修改然后,和配置,在添加上自己的代码就可以实现简单的功能了。 当然做安卓的开发还是需要有一定的安卓基础的,不过如果你实在... -
20172328 暑假作业 之 实现安卓小程序Enjoy-all
2018-12-04 22:44:00本项目基于Java语言和Anroid Studio软件,实现了简单的冒泡、屏幕布局设计、多层次结构和一些实用功能。 使用说明: 使用本款app,可以使用日记本功能、账目计算功能以及打卡计划提醒功能,能使用户更好的管理时间... -
用android studio 完成简单计算器设计开发日志
2019-03-17 17:53:27简单计算器的设计是学习安卓的第一个APP的设计,我发现,其实安卓跟Java有很大的相似性,虽然界面的设计要用到前端的设计,但是功能的实现基本都是使用Java来实现的,但由于对Android studio和虚拟器的不熟悉以及对... -
安卓、服务器(servlet)、mysql数据库实现用户注册(一)
2020-08-16 20:43:48耗时半个月的摸索,在冷却一段时间后,今天终于突破这个小瓶颈,升级了之前的项目想法,可以实现三端的协调通信实现简单注册的功能(安卓、服务器、mysql)真它喵的不容易,这篇博客先将以下基础环境和操作。... -
CocosCreator之KUOKUO带你搞反射-简单的安卓交互
2020-01-15 23:02:23在使用 CocosCreator 打包的原生应用中,我们可以通过引擎封装好的反射机制调用 Java 的静态方法,从而实现提示、相册、支付跳转等功能。本次内容为环境介绍与简单的交互。 正文 先看效果 版本说明 CocosCreator ... -
安卓后台服务相关-实现工具AndroidstudioAndroid6.0在我们原有的AndroidManifest.xml声明权限的基础上又...
2019-07-29 16:15:38实现工具Android studio ,Android 6.0在我们原有的AndroidManifest.xml声明权限的基础上,又新增了运行时权限动态检测,以下权限都需要在运行时判断:身体传感器、日历、摄像头、通讯录、地理位置、麦克风、电话、... -
安卓学习笔记---扫描与生成二维码的实现
2016-07-13 15:00:24最近老大让实现一个扫描二维码的功能,正好看了慕课网的视频,于是就记录了下来,也应用到了自己的项目中,记录一下 效果如图: 扫描与生成二维码的效果基本就如上图所示了,需要用到第三方的zxing,代码还是很... -
安卓新闻APPNews.zip
2020-12-02 10:59:27Android Studio 实现的安卓新闻APP,主要功能是用于浏览新闻,使用天行数据的API接口接收新闻,课设的可以参考参考,比较简单的。 -
kotlin实现通知栏提醒功能示例代码
2021-01-04 04:31:17我在网上找了很久,几乎没找到使用kotlin实现通知栏提醒的合适的文章,于是就到安卓官网看文档,一边翻译一边研究,最终实现了一个简单的通知栏提醒。又研究了定时任务,但没有成功,还望看到的大佬给个锦囊。 二、... -
带你了解安卓学习的刚开始———UI安卓《手机信息页面》
2017-03-11 09:30:02今天小编带着大家简单编写一个安卓手机信息页面的过程,了解安卓的基本功能的实现。如下: 这是最后实现的效果 首先,打开Android Studio,创建一个项目,先给讲解一下初学经常使用的菜单栏打开项目下的APP,打开... -
Android Studio基于zxing的第三方库zxing-android-embedded实现生成二维码与扫描二维码
2020-01-10 23:08:11为了在APP中添加扫码功能,需要用到相关的开源库,最常见的是zxing库和zbar库,zbar很多年前就已经...主要参考了第三方ZXing库zxing-android-embedded使用及自定义与安卓Zxing的简单使用-(生成二维码与扫一扫)这两... -
Android--利用Bmob实现头像上传下载功能
2016-09-01 17:31:52本文使用Bmob作为云后台,实现一个简简单单的头像的选取、截取、上传、下载功能的实现。 编码环境:Android Studio2.1.1 运行环境:Miui8.6.8.18(安卓版本号6.0.1MMB29M) 手机型号:小米3 如有错误,欢迎指正! ... -
创建安卓键盘演示——“好不”
2020-02-24 06:22:48其中的一个副产品是一个安卓键盘, 功能很简单, 只能输入 yes 或者 no. 这里借用此想法, 原型实现比想象中的更简单. 实现 开发环境: Android Studio 3.5.3, JRE 1.8.0_202, SDK API 28. 创建项目, 选择"Phone and ... -
安卓大作业之音乐播放器
2020-07-04 23:52:15参考网上一部分源码整合成一个简单地音乐播放器,可实现播放、切换、显示歌词等功能。开发环境:Android Studio 3.6 -
Android代码-安卓五子棋游戏
2019-08-06 08:00:11滑稽与狗蛋——安卓五子棋游戏 一款充满快乐元素的Android 五子棋游戏,支持页面刷新,view 的存储与恢复等 功能: 两人对战的五子棋游戏 语言: java 开发环境: Android Studio Deepin(深度操作系统) 技术: * 1... -
安卓开发酒店点餐系统
2018-07-18 20:02:20在技术方面上,这次设计是基于Android平台的,用Java语言作为开发语言进行软件的开发,使用Android studio作为软件开发工具进行界面的设计及相关代码的编写,实现登录注册系统、点餐和管理菜单等功能,使用MySQL... -
安卓ShareSDK分享总结
2017-03-21 20:23:53几乎所有的Android应用都离不开分享这一个大功能,把自己的应用或者某条内容分享到各个社交平台对于宣传应用是非常必要的,市场上大部分的分享都是通过集成ShareSdk来实现的,这里就给大家总结下AndroidStudio集成...
-
java jtextfield 居中_如何使JTextField中输入的文字居中显示
-
NT68563_V2.0_20050701.pdf
-
JMETER 性能测试基础课程
-
地球重力场模型计算高程异常
-
java socket异常_Java Socket常见异常处理
-
DefenderControl.zip
-
朱老师C++课程第3部分-3.6智能指针与STL查漏补缺
-
零基础一小时极简以太坊智能合约开发环境搭建并开发部署
-
MySQL 管理利器 mysql-utilities
-
java socket多线程聊天室_Java学习之结合多线程技术,实现客户端和服务端任意通讯的“聊天室”功能...
-
基于Flink+Hudi构建企业亿级云上实时数据湖教程(PC、移动、小
-
java jtextfield 居中_java – 如何使JTextfield居中
-
Documenting.Software.Architectures --软件构架编档
-
UL 2743:2018 Standard for Portable Power Packs -完整英文版(93页)
-
NFS 网络文件系统
-
FTP 文件传输服务
-
java socket序列化_通过socket传递java对象(对象序列化)
-
java socket 输入输出_java网络编程中IO数据输入输出问题
-
java socket发送消息_Java Socket建立连接和发送消息
-
java eventsource_利用EventSource对象实现服务器推送(java servlet)