-
类
- view: 位于android.view包中 View的子类位于android.widget包中
- 属性
- id
- background
- padding 内边距 上下左右
- 属性
- viewGroup 控制view如何拜访
- layoutParams
- layout_height match_pa rent 与容器相同 wrap_content与内容为主
- layout_width
- marginLayoutParams 外边距
- layout_marginTop
- layout_marginBottom
- layout_marginStart
- layout_marginEnd
- layoutParams
- view: 位于android.view包中 View的子类位于android.widget包中
-
布局管理器
- 相对布局管理器RelativeLayout
- 布局管理器属性
- gravity子组件摆放
- ignoregravity:[组件id] 无视
- 子组件属性
- layout_above[组件id] 组件相对于参考位置
- layout_alignParentBottom [bool] 组件相对于父容器
- layout_alingnBottom [组件id] 组件相对于参考位置的边界
- layout_centerHorizontal 位于布局管理器的位置
- 布局管理器属性
- 线性布局管理器LinearLayout
- 布局管理器的属性
- orientation
- vertical 垂直
- horizontal 水平
- gravity 显示效果 center,right|bottom
- orientation
- 组件属性
- layout_weight:
- 布局管理器的属性
- 帧布局管理器FrameLayout
- 布局管理器的属性
- foreground 最前端图片
- foregroundGravity前端图片位置
- 布局管理器的属性
- 表格布局管理器TableLayout [可跨列]
- 布局管理器的属性
- TableRow 行
- collapseColumns 隐藏列
- stretchColumns 允许被拉伸
- shrinkColumns 允许被收缩
- 布局管理器的属性
- 网格布局管理器GridLayout [可跨行列]
- 布局管理器的属性
- columnCount 列数
- orientation 水平或垂直排列
- rowCount 行数
- 组件属性
- layout_column 指定位于第几列
- layout_columnSpan 指定横向跨几列
- layout_columnWeight 水平方向权重
- layout_gravity 方式
- layout_row 指定位于第几行
- layout_rowSpan 指定跨几行
- layout_rowWeight 指定垂直方向权重
- 布局管理器的属性
- 相对布局管理器RelativeLayout
-
组件
-
文本框组件textView
- text [string values]
- textSize [sp]
- textColor
- singleLine 单行文本框
-
编辑框组件EditText
- hint 提示文本
- inputType 输入类型 [textMutline]
- drawableLeft/drawableStart/drawableEnd/drawableBottom/drawablePadding
- lines
- getText()获取编辑框内容
-
按钮Button
- Text 内容
- 监听器
- 匿名内部类
- xml中指定
-
图片按钮 ImageButton
-
单选框radioButton
- radioGroup 遍历getChildAt 获取单个radioButton
- radioGroup onCheckedChangeListener checkedId–>radioButton
-
复选框checkBox
-
时间dataPicker
- init() 初始化
- onDataChange 事件
-
TimePicker时钟
-
计时器Chronometer
- setBase 设置起始时间
- setFormat 设置显示时间格式
- start 指定开始计时
- stop 指定停止计时
- onChrometerTick
-
进度条progressBar
- style
- style="?android:attr/progressBarStyleHorizontal"
- style="@android:style/Widget.ProgressBar.Horizontal
- style="@android:style/Widget.ProgressBar.Inverse
- max 最大值
- progress 当前值
- style
-
拖动条SeekBar
-
星级评分条
- numstarts 星星总数
- rating 点亮个数
- stepSize
- isIndicator 是否不可更改
-
图像视图 ImageView
- scaleType
- center 保持图像大小 以ImageView为中心 图像大截取
- centerInside 原图大按照比例缩放 原图小 居中显示
- centerCrop 原图大按比例缩放 原图小 按宽高比例放大
- matrix 原图大小显示在左上角
- fitXy 填充
- fitStart 以ImageView的高度放大缩小 显示在上方
- fitCenter 以ImageView的高度放大缩小 显示在中间
- fitEnd 以ImageView的高度放大缩小 显示在下方
- adjustViewBounds 是否调整
- maxHeight
- maxWidth
- scaleType
-
GridView视图管理器
- numColumn 几列
- columnWidth 每列宽度
- verticalSpace 横向空隙
- Adapter 适配器
- BaseAdapter
public class ImageAdapter extends BaseAdapter { private Context imageContext; public ImageAdapter(Context c) { imageContext = c; } @Override public int getCount() { return imageResource.length; } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView; if (convertView == null) { imageView = new ImageView(imageContext); imageView.setLayoutParams(new GridView.LayoutParams(300, 150)); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); } else { imageView = (ImageView) convertView; } imageView.setImageResource(imageResource[position]); return imageView; } }
- SimpleAdapter
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); for (int i = 0; i < imageResource.length; i++) { Map<String, Object> map = new HashMap<>(); map.put("img", imageResource[i]); list.add(map); } SimpleAdapter simpleAdapter = new SimpleAdapter(this, list, R.layout.cell, new String[]{"img"}, new int[]{R.id.image}); gridView.setAdapter(simpleAdapter);
- ArrayAdapter
- SimpleCursorAdapter
- BaseAdapter
-
Spinner 下拉列表
- setOnItemSelectedListener 选中监听器
- entries 数组资源
-
ScrollView 滚动条
- 向下滚动条
- 横向滚动条HorizontalScrollView
-
选项卡
- TabHost
- TabWidget
- TabContent
<?xml version="1.0" encoding="utf-8"?> <TabHost xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@android:id/tabhost" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TabWidget android:id="@android:id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content"></TabWidget> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> </TabHost>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/left1" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="Hello World" android:textSize="30sp" /> </LinearLayout>
package com.example.tabhost; import android.os.Bundle; import android.view.LayoutInflater; import android.widget.TabHost; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TabHost tabHost = findViewById(android.R.id.tabhost); //初始化 tabHost.setup(); LayoutInflater layoutInflater = LayoutInflater.from(this); layoutInflater.inflate(R.layout.tab1, tabHost.getTabContentView()); layoutInflater.inflate(R.layout.tab2, tabHost.getTabContentView()); layoutInflater.inflate(R.layout.tab3, tabHost.getTabContentView()); tabHost.addTab(tabHost.newTabSpec("tab1").setIndicator("测试1").setContent(R.id.left1)); tabHost.addTab(tabHost.newTabSpec("tab2").setIndicator("测试2").setContent(R.id.right)); tabHost.addTab(tabHost.newTabSpec("tab3").setIndicator("测试3").setContent(R.id.left3)); } }
-
-
activity
-
概述 代表手机屏幕的一屏
-
4种状态度
- 运行
- 暂停
- 停止
- 销毁
-
生命周期
- onCreate
- onStart
- onResume
- onPause
- onStop
- onDestory
- onRestart
-
创建并配置
- 创建类
- 继承Activity
- 重写onCreate方法
- setContent
-
启动与关闭
- startActivity(Intent)
- finish()
package com.example.activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = findViewById(R.id.bt); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "测试", Toast.LENGTH_SHORT).show(); Log.i("测试", "测试"); Intent intent = new Intent(MainActivity.this, MyActivity.class); startActivity(intent); } }); Button button1 = findViewById(R.id.bt1); button1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); }
}
``` -
多个Activity交换数据
-
储存值
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = findViewById(R.id.save); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //获取数据 String name = ((EditText) (findViewById(R.id.name))).getText().toString(); String phone = ((EditText) (findViewById(R.id.phone))).getText().toString(); String adress = ((EditText) (findViewById(R.id.adress))).getText().toString(); String deatilAdress = ((EditText) findViewById(R.id.deatilAdress)).getText().toString(); //验证 if (!"".equals(name) && !"".equals(phone) && !"".equals(adress) && !"".equals(deatilAdress)) { //创建intent Intent intent = new Intent(MainActivity.this, Main2Activity.class); Bundle bundle = new Bundle(); //储存值 bundle.putCharSequence("name", name); bundle.putCharSequence("phone", phone); bundle.putCharSequence("adress", adress); bundle.putCharSequence("deatilAdress", deatilAdress); intent.putExtras(bundle); startActivity(intent); } else { Toast.makeText(MainActivity.this, "请将收货地址填写完整!!", Toast.LENGTH_SHORT).show(); } } }); }
-
获取值
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); Bundle bundle = getIntent().getExtras(); String name = bundle.getString("name"); String phone = bundle.getString("phone"); String adress = bundle.getString("adress"); String deatilAdress = bundle.getString("deatilAdress"); ((TextView) findViewById(R.id.name)).setText(name); ((TextView) findViewById(R.id.phone)).setText(phone); ((TextView) findViewById(R.id.adress)).setText(adress + deatilAdress); } }
-
-
切换Activity返回结果
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); //返回后的操作 if (requestCode == 0x1234 && resultCode == 0x1234) { //获取数据包 Bundle bundle = data.getExtras(); int imageId = bundle.getInt("imageId"); //设置头像 ImageView imageView = findViewById(R.id.image); imageView.setImageResource(imageId); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = findViewById(R.id.choose); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, Main2Activity.class); startActivityForResult(intent, 0x1234); } }); }
private int[] imageResource = new int[]{ R.drawable.img1, R.drawable.img1, R.drawable.img1, R.drawable.img1, R.drawable.img1, R.drawable.img1 }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); GridView gridView = findViewById(R.id.gridView); List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); for (int i = 0; i < imageResource.length; i++) { Map<String, Object> map = new HashMap<>(); map.put("image", imageResource[i]); list.add(map); } SimpleAdapter simpleAdapter = new SimpleAdapter(this, list, R.layout.model, new String[]{"image"}, new int[]{R.id.img}); gridView.setAdapter(simpleAdapter); gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent intent = getIntent(); Bundle bundle = new Bundle(); bundle.putInt("imageId", imageResource[position]); intent.putExtras(bundle); setResult(0x1234, intent); finish(); } }); }
-
Fragment
- 生命周期
- Fragment的创建
- 在Activity中添加Fragment
- 实例代码
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <LinearLayout android:id="@+id/test" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"></LinearLayout> <!--按钮--> <GridLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:columnCount="6" android:paddingBottom="5dp"> <TextView android:layout_width="20dp" android:layout_height="wrap_content" android:layout_column="0" /> <ImageButton android:id="@+id/message" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="1" android:layout_columnWeight="1" android:layout_marginStart="20dp" android:background="#00FFFFFF" android:scaleType="center" android:src="@drawable/message" /> <ImageButton android:id="@+id/contact" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="2" android:layout_columnWeight="1" android:background="#00FFFFFF" android:scaleType="center" android:src="@drawable/contact" /> <ImageButton android:id="@+id/discovery" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="3" android:layout_columnWeight="1" android:layout_gravity="center" android:background="#00FFFFFF" android:src="@drawable/discovery" /> <ImageButton android:id="@+id/my" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="4" android:layout_columnWeight="1" android:background="#00FFFFFF" android:scaleType="center" android:src="@drawable/my" /> <TextView android:layout_width="20dp" android:layout_height="wrap_content" android:layout_column="5" /> </GridLayout> </RelativeLayout>
package com.example.test; import android.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.annotation.Nullable; /** 创建Fragment */ public class ContactFrament extends Fragment { @Nullable @Override public View onCreateView( LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.contact, container, false); return view; } }
package com.example.test; import android.app.Fragment; import android.app.FragmentTransaction; import android.os.Bundle; import android.view.View; import android.widget.ImageButton; import androidx.appcompat.app.AppCompatActivity; /** * 使用与切换Fragment */ public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ImageButton messageButton = findViewById(R.id.message); View.OnClickListener onClickListener = new View.OnClickListener() { @Override public void onClick(View v) { FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); Fragment f = null; switch (v.getId()) { case R.id.message: f = new MessageFragment(); break; case R.id.contact: f = new ContactFrament(); break; case R.id.discovery: f = new DiscoveryFragment(); break; case R.id.my: f = new MyFragment(); break; default: break; } fragmentTransaction.replace(R.id.test, f); fragmentTransaction.commit(); } }; messageButton.setOnClickListener(onClickListener); ImageButton contactButton = findViewById(R.id.contact); contactButton.setOnClickListener(onClickListener); findViewById(R.id.discovery).setOnClickListener(onClickListener); findViewById(R.id.my).setOnClickListener(onClickListener); } }
-
Intent对象
-
属性
- Component name
- Action与Data
<uses-permission android:name="android.permission.SEND_SMS" /> <uses-permission android:name="android.permission.CALL_PHONE" />
ImageButton telButton = findViewById(R.id.tel); ImageButton messageButton = findViewById(R.id.message); View.OnClickListener onClickListener = new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); switch (v.getId()) { case R.id.tel: intent.setAction(Intent.ACTION_DIAL); intent.setData(Uri.parse("tel:1383838438")); startActivity(intent); break; case R.id.message: intent.setAction(Intent.ACTION_SENDTO); intent.setData(Uri.parse("smsto:10086")); intent.putExtra("sms_body", "测试"); startActivity(intent); default: break; } } }; telButton.setOnClickListener(onClickListener); messageButton.setOnClickListener(onClickListener);
-
Extras属性 存放和获取数据
-
Flag属性 FLAG_ACTIVITY_NO_HISTORY
-
Intent种类
- 显示Intent
- 隐式Intent
-
-
-
事件和手势
- 单击事件
- 长按事件
//注册事件 findViewById(R.id.button) .setOnLongClickListener( new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { registerForContextMenu(v); openContextMenu(v); return true; } }); //创建菜单 @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); menu.add("收藏"); menu.add("举报"); }
- 物理按键事件
//按键事件 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { //判断按键 if (keyCode == KeyEvent.KEYCODE_BACK) { exit(); return true; } return false; } //退出 private void exit() { if (System.currentTimeMillis() - exitTime >= 2000) { Toast.makeText(MainActivity.this, "再按一次返回键退出", Toast.LENGTH_SHORT).show(); exitTime = System.currentTimeMillis(); } else { finish(); System.exit(0); } }
- 触摸事件
final Hat hat = new Hat(this); hat.setOnTouchListener( new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { Toast.makeText(MainActivity.this, String.valueOf(hat.hatX), Toast.LENGTH_SHORT).show(); Toast.makeText(MainActivity.this, String.valueOf(event.getX()), Toast.LENGTH_SHORT) .show(); hat.hatX = event.getX() - 310; hat.hatY = event.getY() - 200; hat.invalidate(); return true; } }); ((FrameLayout) findViewById(R.id.frameLayout)).addView(hat);
package com.jamin.event; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.view.View; /** * @author Jamin <br> * @date 2019 /10/2 16:19 <br> * @desc 帽子 <br> */ public class Hat extends View { public float hatX; public float hatY; public Hat(Context context) { super(context); hatX = 100; hatY = 100; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint paint = new Paint(); Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.hat); canvas.drawBitmap(bitmap, hatX, hatY, paint); if (bitmap.isRecycled()) { bitmap.recycle(); } } }
- 单击事件与触摸事件的区别
- 单击事件只触发一次
- 触摸事件触发两次
- 先触发单击事件的按下再抬起 如果返回true结束,返回false会再触发单击事件
- 手势检测 [查看相册的实例]
package com.jamin.event; import android.os.Bundle; import android.view.GestureDetector; import android.view.MotionEvent; import android.widget.ImageView; import android.widget.ViewFlipper; import androidx.appcompat.app.AppCompatActivity; public class Main2Activity extends AppCompatActivity implements GestureDetector.OnGestureListener { final int DISTANCE = 50; private int[] imageResource = new int[] { R.mipmap.img1, R.mipmap.img2, R.mipmap.img3, R.mipmap.img4, R.mipmap.img5, R.mipmap.img6 }; private GestureDetector detector; private ViewFlipper viewFlipper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); detector = new GestureDetector(Main2Activity.this, this); viewFlipper = findViewById(R.id.viewFlipper); for (int i = 0; i < imageResource.length; i++) { ImageView imageView = new ImageView(Main2Activity.this); imageView.setImageResource(imageResource[i]); viewFlipper.addView(imageView); } } @Override public boolean onDown(MotionEvent e) { return false; } @Override public void onShowPress(MotionEvent e) {} @Override public boolean onSingleTapUp(MotionEvent e) { return false; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return false; } @Override public void onLongPress(MotionEvent e) {} @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // 向右边划 if (e1.getX() - e2.getX() > DISTANCE) { viewFlipper.showPrevious(); return true; } else if (e2.getX() - e1.getX() > DISTANCE) { viewFlipper.showNext(); return true; } return false; } @Override public boolean onTouchEvent(MotionEvent event) { return detector.onTouchEvent(event); } }
-
android应用的资源
-
字符串资源
-
颜色资源
-
尺寸资源dimans
-
drawable资源
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="#f60" android:state_focused="true" /> <item android:color="#0a0" android:state_focused="false" /> </selector>
-
mipmap资源
-
主题资源 Theme按钮,自定义style
-
菜单资源文件
- 选项菜单
- 重写onCreateOptionsMenu()方法 getMenuInflater().inflate();new Intent(),startActivity()}
- 重写onOptionsItemSelected()方法switch (item.getItemId()) {new Intent(),startActivity()}
- 上下文菜单
- 重写onCreateContextMenu() getMenuInflater().inflate(R.menu.menu, menu);
- 重写onContextItemSelected() switch(item.getItemId())
- 选项菜单
-
android 国际化
- values-en-rUS
- values-Zh-rCN
- values-zh-rTW
-
-
ActionBar
未完成
- 显示与关闭ActionBar
- 使用theme
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
- 使用theme
- ActionBar Tab
- 层级式导航
//开启返回按钮 if (NavUtils.getParentActivityName(Main2Activity.this) != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); }
- 显示与关闭ActionBar
-
消息,通知
- 提示Toast
- 对话框AlertDialog
- 确定取消对话框
@Override public void onClick(View v) { AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create(); alertDialog.setIcon(R.drawable.ic_launcher_background); alertDialog.setTitle("标题"); alertDialog.setMessage("内容"); alertDialog.setButton( DialogInterface.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(MainActivity.this, "您点击了取消按钮", Toast.LENGTH_SHORT).show(); } }); alertDialog.setButton( DialogInterface.BUTTON_POSITIVE, "确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(MainActivity.this, "您点击了确定按钮", Toast.LENGTH_SHORT).show(); } }); alertDialog.show(); }
- 列表对话框
@Override public void onClick(View v) { AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setIcon(R.drawable.ic_launcher_background); builder.setTitle("请选择"); builder.setItems( strings, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText( MainActivity.this, "您选择的是" + strings[which], Toast.LENGTH_SHORT) .show(); } }); builder.create().show(); }
- 单选对话框
@Override public void onClick(View v) { AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setTitle("测试"); builder.setSingleChoiceItems( strings, 0, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText( MainActivity.this, "您选择的是" + strings[which], Toast.LENGTH_SHORT) .show(); } }); builder.setPositiveButton("确认", null); builder.create().show(); }
- 多选对话框
@Override public void onClick(View v) { AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setTitle("测试"); final boolean[] booleans = new boolean[] {true, false, false, true}; builder.setMultiChoiceItems( strings, booleans, new DialogInterface.OnMultiChoiceClickListener() { @Override public void onClick(DialogInterface dialog, int which, boolean isChecked) { Toast.makeText( MainActivity.this, "您选择的是" + booleans[which], Toast.LENGTH_SHORT) .show(); } }); builder.setPositiveButton("确认", null); builder.create().show(); }
- 确定取消对话框
- 通知Notification
// 通知管理器 NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); // 通知对象 Notification.Builder notification = new Notification.Builder(MainActivity.this); // 打开后自动关闭 notification.setAutoCancel(true); // 标题 notification.setContentTitle("通知标题"); // 内容 notification.setContentText("通知内容"); // 图标 notification.setSmallIcon(R.mipmap.ic_launcher); // 通知发送时间 notification.setWhen(System.currentTimeMillis()); // 设置声音和振动 notification.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE); // 创建一个启动的Intent Intent intent = new Intent(MainActivity.this, Main2Activity.class); PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 0, intent, 0); notification.setContentIntent(pendingIntent); notificationManager.notify(NOTIFYID, notification.build());
- 广播
// 发送广播 Intent intent = new Intent(); intent.setAction("ceshi"); sendBroadcast(intent);
package com.jamin.boardcastreceiver; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.view.WindowManager; import android.widget.Toast; /** * @author Jamin <br> * @date 2019/10/8 10:45 <br> * @desc 接收广播 <br> */ public class Receiver extends BroadcastReceiver { private static final String ACTION1 = "ceshi"; @Override public void onReceive(final Context context, Intent intent) { // 收到广播回复 if (intent.getAction().equals(ACTION1)) { AlertDialog alertDialog = new AlertDialog.Builder(context).create(); alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST); alertDialog.setIcon(R.mipmap.ic_launcher); alertDialog.setTitle("测试"); alertDialog.setMessage("测试内容"); alertDialog.setButton( DialogInterface.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(context, "收到测试信息", Toast.LENGTH_SHORT).show(); } }); alertDialog.setButton( DialogInterface.BUTTON_POSITIVE, "确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(context, "收到测试信息", Toast.LENGTH_SHORT).show(); } }); alertDialog.show(); } } }
- 设置闹钟
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final TimePicker timePicker = findViewById(R.id.timePicker); timePicker.setIs24HourView(true); findViewById(R.id.setting) .setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { // 创建intent对象 Intent intent = new Intent(MainActivity.this, AlarmActivity.class); // 获取显示闹钟的pendingIntent对象 PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 0, intent, 0); // 获取AlarmManager对象 AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); // 设置闹钟时间 Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, timePicker.getCurrentHour()); calendar.set(Calendar.MINUTE, timePicker.getCurrentMinute()); calendar.set(Calendar.SECOND, 0); // 设置一个闹钟 alarmManager.set( AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent); Toast.makeText(MainActivity.this, "设置成功", Toast.LENGTH_SHORT).show(); } }); }
-
画图与动画
- 绘制矩形
Paint paint = new Paint(); paint.setColor(0xFFFF0000); paint.setAntiAlias(true); paint.setTextAlign(Paint.Align.LEFT); paint.setTextSize(30); canvas.drawText("测试", 105, 102, paint);
- 绘制文字
Paint paint = new Paint(); String path = Environment.getExternalStorageDirectory() + "/1.jpg"; Bitmap bitmap = BitmapFactory.decodeFile(path); canvas.drawBitmap(bitmap, 0, 0, paint);
- 绘制图片
Paint paint = new Paint(); String path = Environment.getExternalStorageDirectory() + "/1.jpg"; Bitmap bitmap = BitmapFactory.decodeFile(path); canvas.drawBitmap(bitmap, 0, 0, paint);
- 绘制路径
Paint paint = new Paint(); paint.setColor(0xFF000000); paint.setAntiAlias(true); paint.setStrokeWidth(1); paint.setTextSize(30); paint.setStyle(Paint.Style.STROKE); Path path = new Path(); path.addCircle(100, 200, 60, Path.Direction.CW); // canvas.drawPath(path, paint);canvas.drawPath(path, paint); canvas.drawTextOnPath("中华人民共和国", path, 100, 200, paint);
- 逐帧动画
<?xml version="1.0" encoding="utf-8"?> <!--逐帧动画资源文件--> <animation-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@mipmap/img1" android:duration="60" /> <item android:drawable="@mipmap/img2" android:duration="60" /> <item android:drawable="@mipmap/img3" android:duration="60" /> <item android:drawable="@mipmap/img4" android:duration="60" /> </animation-list>
<!--使用动画资源--> android:background="@drawable/anim"
- 补间动画
- 透明度渐变动画
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 持续时间 完全透明到完全不透明--> <alpha android:duration="2000" android:fromAlpha="0" android:toAlpha="1" /> </set>
// 使用动画资源 Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.anim4); imageView.startAnimation(animation);
- 透明度渐变动画
- 旋转动画
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <!--开始角度 最终角度 xy轴 持续时间--> <rotate android:duration="2000" android:fromDegrees="0" android:pivotX="50%" android:pivotY="50%" android:toDegrees="360" /> </set>
- 缩放动画
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <!--持续时间 从xy的0.5到1 中心点--> <scale android:duration="2000" android:fromXScale="0.5" android:fromYScale="0.5" android:pivotX="50%" android:pivotY="50%" android:toXScale="1" android:toYScale="1" /> </set>
- 平移动画
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <!--起始点到终点 持续时间--> <translate android:duration="2000" android:fromXDelta="0" android:fromYDelta="0" android:toXDelta="300" android:toYDelta="0" /> </set>
- 绘制矩形
-
音频视频
- 音频
package com.example.musicvideo; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.View; import android.widget.ImageButton; import androidx.appcompat.app.AppCompatActivity; /** * @author Jamin * @date 2019/10/9 * @desc 使用mediaPlayer简易播放器 */ public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final MediaPlayer mediaPlayer = MediaPlayer.create(MainActivity.this, R.raw.mp31); findViewById(R.id.start) .setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { // 音频播放 mediaPlayer.start(); } }); findViewById(R.id.pause) .setOnClickListener( new View.OnClickListener() { // 音频暂停 @Override public void onClick(View v) { mediaPlayer.pause(); } }); findViewById(R.id.stop) .setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { // 音频停止 mediaPlayer.pause(); mediaPlayer.seekTo(0); } }); String path = Environment.getExternalStorageDirectory() + "/mp31.mp3"; Log.i("测试", path); final MediaPlayer mediaPlayer1 = MediaPlayer.create(MainActivity.this, Uri.parse(path)); final ImageButton playPause = findViewById(R.id.play); playPause.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { if (mediaPlayer1.isPlaying()) { mediaPlayer1.pause(); ((ImageButton) v).setImageDrawable(getResources().getDrawable(R.mipmap.start)); } else { mediaPlayer1.start(); ((ImageButton) v).setImageDrawable(getResources().getDrawable(R.mipmap.pause)); } } }); ImageButton stop = findViewById(R.id.stop2); stop.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { mediaPlayer1.pause(); mediaPlayer1.seekTo(0); playPause.setImageDrawable(getResources().getDrawable(R.mipmap.start)); } }); } }
ListView listView = findViewById(R.id.listView); // 音频属性,使用场景 音效类型 AudioAttributes audioAttributes = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build(); // 创建soundPool对象 配置相关参数 final SoundPool soundPool = new SoundPool.Builder().setAudioAttributes(audioAttributes).setMaxStreams(10).build(); // 将音频资源放入hashMap中 final HashMap<Integer, Integer> hashMap = new HashMap<>(); // 加载音频,优先权 值越大优先权越高 hashMap.put(0, soundPool.load(MainActivity.this, R.raw.nomatter, 1)); hashMap.put(1, soundPool.load(MainActivity.this, R.raw.nextofkin, 1)); hashMap.put(2, soundPool.load(MainActivity.this, R.raw.makingmefeel, 1)); listView.setOnItemClickListener( new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // 资源文件,左声道音量0-1,右声道音量,优先级值越大优先级越高,循环,速率0.5-2 soundPool.play(hashMap.get(position), 1, 1, 0, 0, 1); } });
- MediaPlayer与SoundPool区别
- MediaPlayer 延迟长,占用资源多,不支持同时播放多个音频
- SoundPool延迟短,占用资源少,支持多音频播放
-
视频
package com.example.musicvideo; import android.media.MediaPlayer; import android .os.Bundle; import android.os.Environment; import android.util.Log; import android.widget.MediaController; import android.widget.Toast; import android.widget.VideoView; import androidx.appcompat.app.AppCompatActivity; import java.io.File; public class Main2Activity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); VideoView videoView = findViewById(R.id.videoView); // 控制组件 videoView.setMediaController(new MediaController(Main2Activity.this)); String path = Environment.getExternalStorageDirectory() + "/mp41.mp4"; Log.i("测试", path); File file = new File(path); if (file.exists()) { videoView.setVideoPath(file.getAbsolutePath()); Toast.makeText(Main2Activity.this, "文件存在", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(Main2Activity.this, "文件不存在", Toast.LENGTH_SHORT).show(); } // 获取焦点 videoView.requestFocus(); videoView.start(); // 播放完毕触发事件 videoView.setOnCompletionListener( new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { Toast.makeText(Main2Activity.this, "播放完毕", Toast.LENGTH_SHORT).show(); } }); } }
package com.example.musicvideo; import android.media.AudioManager; import android.media.MediaPlayer; import android.os.Bundle; import android.os.Environment; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.ImageButton; import androidx.appcompat.app.AppCompatActivity; import java.io.IOException; /** * @author Jamin * @date 2019/10/10 * @desc 使用mediaPlayer+surfaceView实现播放视频 */ public class Main3Activity extends AppCompatActivity { private boolean isPause = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main3); SurfaceView surfaceView = findViewById(R.id.surfaceView); final SurfaceHolder surfaceHolder = surfaceView.getHolder(); final MediaPlayer mediaPlayer = new MediaPlayer(); // 设置多媒体类型 mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); try { mediaPlayer.setDataSource(Environment.getExternalStorageDirectory() + "/mp41.mp4"); // 预加载 mediaPlayer.prepare(); } catch (IOException e) { e.printStackTrace(); } final ImageButton playButton = findViewById(R.id.start3); playButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { if (mediaPlayer.isPlaying()) { mediaPlayer.pause(); playButton.setImageDrawable(getResources().getDrawable(R.mipmap.start)); } else { // 将视频输出到surfaceView mediaPlayer.setDisplay(surfaceHolder); mediaPlayer.start(); playButton.setImageDrawable(getResources().getDrawable(R.mipmap.pause)); } } }); findViewById(R.id.stop3) .setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { mediaPlayer.pause(); mediaPlayer.seekTo(0); playButton.setImageDrawable(getResources().getDrawable(R.mipmap.start)); } }); } }
-
控制相机
package com.example.musicvideo; import android.Manifest; import android.app.Activity; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.PixelFormat; import android.hardware.Camera; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.Window; import android.widget.ImageButton; import android.widget.Toast; import androidx.core.content.ContextCompat; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; /** * @author Jamin * @date 2019/10/10 * @desc 拍照与录像 */ public class Main4Activity extends Activity implements SurfaceHolder.Callback { private Camera camera; private SurfaceView surfaceView; private SurfaceHolder surfaceViewHolder; private int cameraId = 0; private ImageButton takePhoto; private Camera.PictureCallback pictureCallback = new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { // 根据拍照数据创建位图 Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); // 停止预览 camera.stopPreview(); File dir = new File(Environment.getExternalStorageDirectory() + "/DCIM/Camera/"); if (!dir.exists()) { // 创建文件夹 dir.mkdir(); } String fileName = System.currentTimeMillis() + ".jpeg"; File file = new File(dir, fileName); try { FileOutputStream fileOutputStream = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream); fileOutputStream.flush(); fileOutputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // 将图片添加到系统图库 try { MediaStore.Images.Media.insertImage( Main4Activity.this.getContentResolver(), file.getAbsolutePath(), fileName, null); } catch (FileNotFoundException e) { e.printStackTrace(); } // 通知图库更新 Main4Activity.this.sendBroadcast( new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + ""))); // 保存图片 Toast.makeText(Main4Activity.this, "照片保存至" + file, Toast.LENGTH_SHORT).show(); camera.startPreview(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main4); this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); initView(); initButton(); } private void initButton() { takePhoto = findViewById(R.id.imgbt1); takePhoto.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { camera.takePicture(null, null, pictureCallback); } }); } private void initView() { surfaceView = findViewById(R.id.surface); surfaceViewHolder = surfaceView.getHolder(); surfaceViewHolder.addCallback(this); } @Override public void surfaceCreated(SurfaceHolder holder) { if (ContextCompat.checkSelfPermission(Main4Activity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { Toast.makeText(Main4Activity.this, "请先打开权限", Toast.LENGTH_LONG).show(); } else { cameraOpen(); } } private void cameraOpen() { try { // 打开相机 camera = Camera.open(cameraId); // 反转 camera.setDisplayOrientation(90); camera.setPreviewDisplay(surfaceViewHolder); camera.startPreview(); // 自动对焦 camera.autoFocus(null); } catch (IOException e) { e.printStackTrace(); camera.release(); camera = null; Toast.makeText(Main4Activity.this, "不能打开摄像机", Toast.LENGTH_SHORT).show(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // 设置参数 Camera.Parameters parameters = camera.getParameters(); parameters.setPictureFormat(PixelFormat.JPEG); parameters.set("jpeg-quality", 80); camera.setParameters(parameters); camera.startPreview(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { camera.stopPreview(); camera.release(); camera = null; } @Override protected void onPause() { super.onPause(); // 释放资源 if (camera != null) { camera.stopPreview(); camera.release(); } } }
package com.example.musicvideo; import android.Manifest; import android.content.pm.PackageManager; import android.hardware.Camera; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Environment; import android.os.SystemClock; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.Chronometer; import android.widget.ImageButton; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.ContextCompat; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; /** * @author Jamin * @date 2019/10/11 * @desc 视频录制 */ public class Main5Activity extends AppCompatActivity implements SurfaceHolder.Callback { private File videoFile; private MediaRecorder mediaRecorder; private Camera camera; private SurfaceView surfaceView; private SurfaceHolder surfaceHolder; private int cameraId = 0; private Camera.Parameters parameters; private Chronometer chronometer; private ImageButton stopVideo; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main5); surfaceView = findViewById(R.id.surface2); surfaceHolder = surfaceView.getHolder(); surfaceHolder.addCallback(this); chronometer = findViewById(R.id.chronometer); final ImageButton videoButton = findViewById(R.id.imgbt2); videoButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { record(); // 开始录像后开始按钮不可点击 videoButton.setEnabled(false); // 停止按钮可点击 stopVideo.setEnabled(true); } }); stopVideo = findViewById(R.id.imgbt3); // 设置停止按钮不可点击 stopVideo.setEnabled(false); stopVideo.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { mediaRecorder.stop(); chronometer.stop(); chronometer.setBase(SystemClock.elapsedRealtime()); Toast.makeText( Main5Activity.this, "视频保存至" + videoFile.getAbsolutePath(), Toast.LENGTH_SHORT) .show(); // 录像结束后开始按钮可点击 videoButton.setEnabled(true); stopVideo.setEnabled(false); } }); } @Override protected void onResume() { super.onResume(); camera = Camera.open(); } @Override protected void onPause() { super.onPause(); camera.stopPreview(); camera.release(); } /** 开始录制 */ private void record() { settingMediaRecorder(); // 准备录像 try { mediaRecorder.prepare(); } catch (IOException e) { e.printStackTrace(); } // 开始录像 mediaRecorder.start(); chronometer.setBase(SystemClock.elapsedRealtime()); chronometer.start(); } /** 录像配置 */ public void settingMediaRecorder() { File path = new File(Environment.getExternalStorageDirectory() + "/MyVideo"); if (!path.exists()) { path.mkdir(); } SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM-dd HH:mm:ss"); String fileName = simpleDateFormat.format(new Date()) + ".mp4"; videoFile = new File(path, fileName); mediaRecorder = new MediaRecorder(); // camera.setDisplayOrientation(90); // 解锁相机 camera.unlock(); // 使用相机 mediaRecorder.setCamera(camera); mediaRecorder.reset(); // 使用麦克风和相机获取视频音频 mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 输出格式 mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); // 编码格式 mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); // 设置比特率 mediaRecorder.setVideoEncodingBitRate(1080 * 1920); // 设置分辨率 List<Camera.Size> supportedVideoSizes = parameters.getSupportedVideoSizes(); for (Camera.Size size : supportedVideoSizes) { if (size.width / 16 == size.height / 9) { mediaRecorder.setVideoSize(size.width, size.height); Log.d("setPictureSize", "SET width:" + size.width + " height " + size.height); break; } } // 设置帧率 mediaRecorder.setVideoFrameRate(24); // 输出路径 mediaRecorder.setOutputFile(videoFile.getAbsolutePath()); // 预览 mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface()); // 调整角度 mediaRecorder.setOrientationHint(90); } /** * 权限检测 * * @param holder */ @Override public void surfaceCreated(SurfaceHolder holder) { if (ContextCompat.checkSelfPermission(Main5Activity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(Main5Activity.this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { Toast.makeText(Main5Activity.this, "请先打开权限", Toast.LENGTH_LONG).show(); } else { cameraOpen(); } } /** 打开相机 */ private void cameraOpen() { try { // 打开相机 camera = Camera.open(cameraId); // 反转 camera.setDisplayOrientation(90); camera.setPreviewDisplay(surfaceHolder); camera.startPreview(); } catch (IOException e) { e.printStackTrace(); camera.release(); camera = null; Toast.makeText(Main5Activity.this, "不能打开摄像机", Toast.LENGTH_SHORT).show(); } } /** * 设置相机参数 * * @param holder * @param format * @param width * @param height */ @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { parameters = camera.getParameters(); parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); camera.setParameters(parameters); camera.startPreview(); } /** * 销毁操作 * * @param holder */ @Override public void surfaceDestroyed(SurfaceHolder holder) { if (camera != null) { camera.release(); camera = null; } } }
- 音频
-
数据存储
- sharePreferences: Android提供用来以最原生的方式对数据进行永久保存的方法,保存文件格式为xml,储存在data/data/包名/shared_prefs
- 获取sharePreferences对象
- getSharedPreferences(String name,int mode)
- name 文件名
- mode MODE_PRIVATE 被本应用读写
- MODE_MULTI_PROCESS 跨应用读写
- getPerences(int mode)
- getSharedPreferences(String name,int mode)
- 获取SharedPreferences.Editor对象 edit()
- 向SharedPreferences.Editor对象添加数据 putBoolean(),putString(),putInt()
- 提交数据commit()
- 使用对象SharedPreferences类提供的getxx()方法获取数据
package com.jamin.datastorage; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.EditText; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { private static final String account = "user"; private static final String pwd = "123456"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final EditText editAccount = findViewById(R.id.account); final EditText editPwd = findViewById(R.id.pwd); final SharedPreferences sharedPreferences = getSharedPreferences("userInfo", MODE_PRIVATE); final SharedPreferences.Editor editor = sharedPreferences.edit(); String user = sharedPreferences.getString("user", null); String password = sharedPreferences.getString("pwd", null); // 判断本地是否有数据 if (user != null && pwd != null && user.equals(account) && password.equals(pwd)) { Intent intent = new Intent(MainActivity.this, Main2Activity.class); startActivity(intent); } findViewById(R.id.login) .setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { String editAccountText = editAccount.getText().toString(); String editPwdText = editPwd.getText().toString(); // 验证 if (editAccountText.equals(account) && editPwdText.equals(pwd)) { Toast.makeText(MainActivity.this, "login success", Toast.LENGTH_SHORT).show(); // 储存数据 editor.putString("user", editAccountText); editor.putString("pwd", editPwdText); editor.commit(); Intent intent = new Intent(MainActivity.this, Main2Activity.class); startActivity(intent); } else { Toast.makeText(MainActivity.this, "login failed", Toast.LENGTH_SHORT).show(); Log.i("账号", editAccountText); Log.i("密码", editPwdText); editAccount.setText(""); editPwd.setText(""); } } }); } }
- 获取sharePreferences对象
- 内部存储 应用的data/data/包名/files/内部储存文件
package com.jamin.datastorage; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; /** * @author Jamin * @date 2019/10/11 * @desc 使用内部储存 * */ public class Main3Activity extends AppCompatActivity { private FileOutputStream fos = null; private FileInputStream fis = null; private byte[] buffer = null; private EditText editText2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main3); final EditText editText = findViewById(R.id.editText); editText2 = findViewById(R.id.editText2); // 保存文件 findViewById(R.id.saveButton) .setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { String content = editText.getText().toString(); try { fos = openFileOutput("test", MODE_PRIVATE); fos.write(content.getBytes()); fos.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (fos != null) { try { fos.close(); Toast.makeText(Main3Activity.this, "保存成功", Toast.LENGTH_SHORT).show(); } catch (IOException e) { e.printStackTrace(); } } } } }); Button cancelButton = findViewById(R.id.cancelButton); cancelButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); // 打开保存的文件 Button openButton = findViewById(R.id.openButton); openButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { try { fis = openFileInput("test"); buffer = new byte[fis.available()]; fis.read(buffer); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (fis != null) { try { fis.close(); String data = new String(buffer); editText2.setText(data); } catch (IOException e) { e.printStackTrace(); } } } } }); } }
- 使用外部存储
package com.jamin.datastorage; import android.os.Bundle; import android.os.Environment; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; /** * @author Jamin * @date 2019/1012 * @desc 外部存储 */ public class Main5Activity extends AppCompatActivity { private EditText editText3; private EditText editText4; private Button saveButton; private Button cancelButton; private Button openButton; private FileInputStream fis; private FileOutputStream fos; private byte[] buffer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main5); editText3 = findViewById(R.id.editText3); editText4 = findViewById(R.id.editText4); saveButton = findViewById(R.id.saveButton2); cancelButton = findViewById(R.id.cancelButton2); openButton = findViewById(R.id.openButton2); saveButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { String content = editText3.getText().toString(); File file = new File(Environment.getExternalStorageDirectory(), "/test.txt"); try { fos = new FileOutputStream(file); fos.write(content.getBytes()); fos.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (fos != null) { try { fos.close(); Toast.makeText(Main5Activity.this, "保存成功", Toast.LENGTH_SHORT).show(); } catch (IOException e) { e.printStackTrace(); } } } } }); openButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { try { fis = new FileInputStream(Environment.getExternalStorageDirectory() + "/test.txt"); buffer = new byte[fis.available()]; fis.read(buffer); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (fis != null) { try { fis.close(); String content = new String(buffer); editText4.setText(content); } catch (IOException e) { e.printStackTrace(); } } } } }); } }
- 使用sqlite数据库
- 在内部储存下新建文件夹dataBase,创建数据库,建表
- 实例代码
package com.jamin.datastorage; import android.content.ContentValues; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; /** * @author Jamin * @date 2019/10/12 * @desc 使用sqlite数据库进行添加 */ public class Main7Activity extends AppCompatActivity {; private DBOpenHelper dbOpenHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main7); // 初始化对象 dbOpenHelper = new DBOpenHelper(Main7Activity.this, "db_dict", null, 1); final EditText eeditText = findViewById(R.id.eeditText); final EditText ceditText = findViewById(R.id.ceditText); findViewById(R.id.add) .setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { String en = eeditText.getText().toString(); String cn = ceditText.getText().toString(); // 保存数据 ContentValues contentValues = new ContentValues(); contentValues.put("word", en); contentValues.put("deatil", cn); dbOpenHelper.getReadableDatabase().insert("t_dictionary", null, contentValues); Toast.makeText(Main7Activity.this, "add success", Toast.LENGTH_SHORT).show(); } }); } @Override protected void onDestroy() { super.onDestroy(); if (dbOpenHelper != null) { dbOpenHelper.close(); } } }
package com.jamin.datastorage; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author Jamin * @date 2019/10/12 * @desc 使用sqlite数据库进行查询 */ public class Main6Activity extends AppCompatActivity { private DBOpenHelper dbOpenHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main6); // 实例化dbOpenHelper对象 上下文对象,数据库名,游标工厂,版本号 dbOpenHelper = new DBOpenHelper(Main6Activity.this, "db_dict", null, 1); final ListView listView = findViewById(R.id.listView); final EditText trEditText = findViewById(R.id.treditText); Button translationButton = findViewById(R.id.translation); Button newWordsButton = findViewById(R.id.newWords); // 跳转添加生词 newWordsButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(Main6Activity.this, Main7Activity.class)); } }); // 查询操作 translationButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { Log.d("test", "in"); String en = trEditText.getText().toString(); // 查询 Cursor cursor = dbOpenHelper .getReadableDatabase() .query("t_dictionary", null, "word=?", new String[] {en}, null, null, null); List<Map<String, String>> maps = new ArrayList<>(); // 遍历放入集合 while (cursor.moveToNext()) { HashMap<String, String> map = new HashMap<>(); map.put("word", cursor.getString(1)); map.put("deatil", cursor.getString(2)); // Toast.makeText(Main6Activity.this, map.toString(), // Toast.LENGTH_SHORT).show(); Log.d("test", map.toString()); maps.add(map); } if (maps == null || maps.size() == 0) { Toast.makeText(Main6Activity.this, "没有查询到数据", Toast.LENGTH_SHORT).show(); } SimpleAdapter simpleAdapter = new SimpleAdapter( Main6Activity.this, maps, R.layout.result_main, new String[] {"word", "deatil"}, new int[] {R.id.result_en, R.id.result_cn}); // 适配器输出 listView.setAdapter(simpleAdapter); } }); } @Override protected void onDestroy() { super.onDestroy(); if (dbOpenHelper != null) { dbOpenHelper.close(); } } }
- 使用contentProvider 在不同应用程序间实现数据共享
- URI与URL
- URL: https://me.csdn.net/weixin_43891731 URL协议/网站域名/网站资源
- URI: content://com.jamin.test/person/oo1 Android规定/权限(类名)/路径
package com.jamin.datastorage; import android.content.ContentResolver; import android.database.Cursor; import android.os.Bundle; import android.provider.ContactsContract; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; /** * @author Jamin * @date 2019/10/12 * @desc contentProvider */ public class Main8Activity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main8); StringBuilder stringBuilder = new StringBuilder(); ContentResolver contentResolver = getContentResolver(); // 查询 Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null); int columnIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME); // 遍历查询结果 for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { String cursorString = cursor.getString(columnIndex); stringBuilder.append(cursorString + "\n"); } TextView textView = findViewById(R.id.textView); textView.setText(stringBuilder.toString()); } }
- URI与URL
- sharePreferences: Android提供用来以最原生的方式对数据进行永久保存的方法,保存文件格式为xml,储存在data/data/包名/shared_prefs
-
Handler消息处理
- 安卓中的多线程
- 进程
- 进程: 一个android应用就是一个进程
- 线程
- 线程: 比进程更小的独立运行的基本单位,一个进程可以包含多个进程
- 实例代码
- 进程
- Handler对象
package com.jaminhandlermessage; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.Button; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final TextView textView = findViewById(R.id.textView); final Handler handler = new Handler() { @Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); // 判断消息 if (msg.what == 0x1234) { // 执行操作 textView.setText("测试2"); } } }; Button button = findViewById(R.id.bt1); button.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { Thread thread = new Thread( new Runnable() { @Override public void run() { // 发送消息 handler.sendEmptyMessage(0x1234); } }); thread.start(); } }); } }
package com.jamin.handlermessage; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.widget.ProgressBar; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.jaminhandlermessage.R; /** * @author Jamin * @date 2019/10/13 * @desc 使用Handler实现进度条 */ public class Main2Activity extends AppCompatActivity { final int MSG = 0x1234; final int MSG2 = 0x1243; private int progress = 0; private int progress2 = 60; private ProgressBar progressBar; private ProgressBar progressBar2; Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what == MSG) { if (progress < 100) { progressBar.setProgress(++progress); handler.sendEmptyMessageDelayed(MSG, 1000); } else { Toast.makeText(Main2Activity.this, "加载完成", Toast.LENGTH_SHORT).show(); } } else if (msg.what == MSG2) { if (progress2 > 0) { progressBar2.setProgress(--progress2); handler.sendEmptyMessageDelayed(MSG2, 1000); } else { Toast.makeText(Main2Activity.this, "游戏结束!!", Toast.LENGTH_SHORT).show(); } } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); progressBar = findViewById(R.id.progressBar); handler.sendEmptyMessage(MSG); progressBar2 = findViewById(R.id.progressBar2); handler.sendEmptyMessage(MSG2); } }
- Message对象
- 属性
- arg1 arg2 整形
- obj Object类型
- replyTo 发送到何处
- what 自定义消息代码
- 创建
- Mesage.obtain()
- Handler.obtainMessage()
- 属性
- Looper对象
package com.jamin.handlermessage; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.util.Log; import androidx.annotation.NonNull; /** * @author Jamin <br> * @date 2019/10/13 18:02 <br> * @desc Loop <br> */ public class LooperThread extends Thread { private final int MSG = 0x1234; private Handler handler; @Override public void run() { super.run(); Looper.prepare(); handler = new Handler() { @Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); Log.e("looper", "test" + String.valueOf(MSG)); } }; Message message = handler.obtainMessage(); message.what = MSG; handler.sendMessage(message); Looper.loop(); } }
package com.jamin.handlermessage; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import com.jaminhandlermessage.R; public class Main4Activity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main4); LooperThread looperThread = new LooperThread(); looperThread.start(); } }
- 安卓中的多线程
-
Service
- 概述: 能够在后台长时间运行,并且没有用户界面的应用程序组件
- 分类
- started service:Activity使用startService通知服务启动才启动 生命周期onCreate->onStartCommand()–>Service运行–>stopSelf()/stopService–>service停止–>onDestory()–>service被关闭
- boundService: bindService()与Activity同生共死 生命周期 onCrate()–> onBind()–>绑定到Service–>unbindService()–>解绑Service()–>onUnbind()–>onDestory()–>service关闭()
- StartedService
package com.jamin.service; import android.app.ActivityManager; import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.IBinder; import android.util.Log; import java.util.ArrayList; /** * @author Jamin * @date 2019/10/13 * @desc 后台打印 */ public class MyService extends Service { private int i = 0; public MyService() {} @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @Override public void onCreate() { super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { new Thread( new Runnable() { @Override public void run() { while (isRunning()) { Log.d("CESHI", String.valueOf(++i)); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }) .start(); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); } public boolean isRunning() { ActivityManager systemService = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); // 获取正在运行的服务 ArrayList<ActivityManager.RunningServiceInfo> runningServiceInfos = (ArrayList<ActivityManager.RunningServiceInfo>) systemService.getRunningServices(100); for (ActivityManager.RunningServiceInfo runningServiceInfo : runningServiceInfos) { // 判断是否是当前服务 if (runningServiceInfo .service .getClassName() .toString() .equals("com.jamin.service.MyService")) { return true; } } return false; } }
package com.jamin.service; import android.content.Intent; import android.os.Bundle; import android.view.View; import androidx.appcompat.app.AppCompatActivity; public class ServiceActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_service); final Intent intent = new Intent(ServiceActivity.this, MyService.class); findViewById(R.id.open) .setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { startService(intent); } }); findViewById(R.id.close) .setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { stopService(intent); } }); } }
package com.jamin.service; import android.app.Service; import android.content.Intent; import android.media.MediaPlayer; import android.os.IBinder; /** * @author Jamin * @date 2019/10/13 * @desc 后台音乐播放 */ public class MusicService extends Service { private MediaPlayer mediaPlayer; public MusicService() {} @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @Override public void onCreate() { mediaPlayer = MediaPlayer.create(this, R.raw.mp31); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (mediaPlayer.isPlaying()) { mediaPlayer.pause(); } else { mediaPlayer.start(); } return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { // 停止播放 mediaPlayer.pause(); mediaPlayer.seekTo(0); // 释放资源 mediaPlayer.release(); super.onDestroy(); } }
package com.jamin.service; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import androidx.appcompat.app.AppCompatActivity; /** * @author Jamin * @date 2019/10/13 * @desc 后台播放音乐 */ public class BackgroundSoundActivity extends AppCompatActivity { private Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_background_sound); button = findViewById(R.id.openClose); final Intent intent = new Intent(BackgroundSoundActivity.this, MusicService.class); button.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { /* MediaPlayer mediaPlayer = MediaPlayer.create(BackgroundSoundActivity.this, R.raw.mp31); mediaPlayer.start();*/ startService(intent); } }); } }
- BoundService
package com.jamin.service; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import java.util.ArrayList; import java.util.List; import java.util.Random; /** * @author Jamin * @date 2019/10/14 BinderService */ public class BinderService extends Service { public BinderService() {} // 销毁 @Override public void onDestroy() { super.onDestroy(); } @Override public IBinder onBind(Intent intent) { return new MyBinder(); } /** 产生随机数的方法 */ public List<String> randomNumber() { List list = new ArrayList<String>(); String s = ""; for (int i = 0; i < 7; i++) { int j = new Random().nextInt(33) + 1; if (j >= 10) { s = String.valueOf(j); } else { s = "0" + String.valueOf(j); } list.add(s); } return list; } /** 创建MyBinder内部类 */ public class MyBinder extends Binder { // 创建获取Service的方法 public BinderService getBinderService() { return BinderService.this; } } }
package com.jamin.service; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.view.View; import android.widget.Button; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import java.util.List; /** * @author Jamin * @date 2019/10/14 */ public class Main2Activity extends AppCompatActivity { private BinderService binderService; /** textView的id */ private int[] textViewArr = new int[] {R.id.t0, R.id.t1, R.id.t2, R.id.t3, R.id.t4, R.id.t5, R.id.t6}; private Button button; /** service连接对象 */ private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { binderService = ((BinderService.MyBinder) service).getBinderService(); } @Override public void onServiceDisconnected(ComponentName name) {} }; @Override protected void onStart() { super.onStart(); Intent intent = new Intent(Main2Activity.this, BinderService.class); // 绑定Service bindService(intent, serviceConnection, BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); // 解绑service unbindService(serviceConnection); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); button = findViewById(R.id.bt0); button.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { List<String> list = binderService.randomNumber(); for (int i = 0; i < list.size(); i++) { TextView textView = findViewById(textViewArr[i]); textView.setText(list.get(i)); } } }); } }
- IntantService 普通service不能自动开启线程,自动销毁,IntentService可以
package com.jamin.service; import android.app.IntentService; import android.content.Intent; import android.util.Log; import androidx.annotation.Nullable; /** * @author Jamin <br> * @date 2019/10/14 16:53 <br> * @desc IntentService <br> */ public class MyIntentService extends IntentService { /** * Creates an IntentService. Invoked by your subclass's constructor. * * @param name Used to name the worker thread, important only for debugging. */ public MyIntentService(String name) { super(name); } public MyIntentService() { super("MyIntentService"); } @Override protected void onHandleIntent(@Nullable Intent intent) { Log.d("intentService", "开始"); long endTime = System.currentTimeMillis() + 20 * 1000; while (System.currentTimeMillis() < endTime) { synchronized (this) { try { wait(endTime - System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } } } } @Override public void onDestroy() { super.onDestroy(); Log.d("service", "jieshu"); } }
package com.jamin.service; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; /** * @author Jamin * @date 2019/10/14 * @desc 普通Service */ public class MyService2 extends Service { public MyService2() {} @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("service", "开始"); long endTime = System.currentTimeMillis() + 20 * 1000; while (System.currentTimeMillis() < endTime) { synchronized (this) { try { wait(endTime - System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } } } return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); Log.d("service", "jieshu"); } }
-
传感器
- 分类
- 光线传感器
- 磁场传感器
- 加速传感器
- 方向传感器
- 光线传感器实例代码
package com.jamin.sensor; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Bundle; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; /** * @author Jamin * @date 2019/10/14 * @desc 光线传感器 */ public class LightActivity extends AppCompatActivity implements SensorEventListener { private SensorManager sensorManager; private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_light); // 获取传感器管理器 sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); textView = findViewById(R.id.textView); } @Override protected void onResume() { super.onResume(); // 注册监听器 sensorManager.registerListener( this, sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT), SensorManager.SENSOR_DELAY_GAME); } @Override protected void onPause() { super.onPause(); // 取消注册监听器 sensorManager.unregisterListener(this); } @Override public void onSensorChanged(SensorEvent event) { float[] values = event.values; int type = event.sensor.getType(); if (type == Sensor.TYPE_LIGHT) { textView.setText("光线传感器:" + values[0]); } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) {} }
- 磁场传感器实例代码
package com.jamin.sensor; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.util.AttributeSet; import android.view.View; import androidx.annotation.Nullable; /** * @author Jamin <br> * @date 2019/10/14 21:28 <br> * @desc 指针 <br> */ public class PointView extends View implements SensorEventListener { private SensorManager sensorManager; private Bitmap bitmap; private float[] value; private float floatX; private float floatY; public PointView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); // 监听器 sensorManager.registerListener( this, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_NORMAL); // 加载资源 bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.compass); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (bitmap != null) { // 设置画布选择角度 canvas.translate(super.getWidth() / 2, super.getWidth() / 2); if (floatY == 0 && floatX > 0) { canvas.rotate(90); } else if (floatY == 0 && floatX < 0) { canvas.rotate(-90); } else { if (floatY > 0) { canvas.rotate((float) Math.tanh(floatX / floatY) * 90); } else { canvas.rotate((float) (180 + Math.tanh(floatX / floatY) * 90)); } } } canvas.drawBitmap(bitmap, -bitmap.getWidth() / 2, -bitmap.getHeight() / 2, new Paint()); } @Override public void onSensorChanged(SensorEvent event) { float[] values = event.values; int type = event.sensor.getType(); if (type == Sensor.TYPE_MAGNETIC_FIELD) { floatX = values[0]; floatY = values[1]; super.postInvalidate(); } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) {} }
- 方向传感器
- 实例代码
package com.jamin.sensor; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.util.AttributeSet; import android.util.Log; import android.view.View; import androidx.annotation.Nullable; /** * @author Jamin <br> * @date 2019/10/15 19:55 <br> * @desc 水平仪 <br> */ public class LevelView extends View implements SensorEventListener { /** 最大倾斜角度 */ private final int MAX_ANGLE = 30; private SensorManager sensorManager; /** 加速度传感器的值 */ private float[] accelerometerValues; /** 磁场传感器的值 */ private float[] magnticValues; /** 小球X坐标 */ private float bubbleX; /** 小球Y坐标 */ private float bubbleY; /** 小球 */ private Bitmap bubble; /** * @param context * @param attrs */ public LevelView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); // 注册磁场监听器 sensorManager.registerListener( this, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_GAME); // 注册加速度监听器 sensorManager.registerListener( this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_GAME); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawBitmap(bubble, bubble.getWidth() / 2, bubble.getHeight() / 2, new Paint()); } @Override public void onSensorChanged(SensorEvent event) { // 获取手机触发event的传感器的类型 int sensorType = event.sensor.getType(); switch (sensorType) { case Sensor.TYPE_ACCELEROMETER: accelerometerValues = event.values.clone(); Log.d("磁场传感器", accelerometerValues.toString()); break; case Sensor.TYPE_MAGNETIC_FIELD: magnticValues = event.values.clone(); Log.d("加速度传感器", magnticValues.toString()); break; default: break; } float[] R = new float[9]; float[] values = new float[3]; SensorManager.getRotationMatrix(R, null, accelerometerValues, magnticValues); SensorManager.getOrientation(R, values); // 手机沿着x轴倾斜 顶部0到-180 底部0-180 float xAngle = (float) Math.toDegrees(values[1]); // 手机沿着y轴倾斜 左侧是0-到-90 右侧是0-90 float yAngle = (float) Math.toDegrees(values[2]); getPostion(xAngle, yAngle); super.postInvalidate(); } private void getPostion(float xAngle, float yAngle) { // 获取小球x,y位于中间位置的x,y坐标 int x = (super.getWidth() - bubble.getWidth()) / 2; int y = (super.getHeight() - bubble.getHeight()) / 2; if (Math.abs(yAngle) <= MAX_ANGLE) { // y轴倾斜角度越大 小球x坐标越大 int i = (int) ((super.getWidth() - bubble.getWidth()) / 2 * xAngle / MAX_ANGLE); x += i; } else if (yAngle > MAX_ANGLE) { // 正的倾斜角度超出放在最左边 x = 0; } else { // 负的倾斜角度超出放在最右边 x = super.getWidth() - bubble.getWidth(); } if (Math.abs(xAngle) <= y) { // x轴倾斜角度越大小球x坐标越大 int i = (int) ((super.getHeight() - bubble.getHeight()) / 2 * yAngle / MAX_ANGLE); y -= i; } else if (xAngle > MAX_ANGLE) { y = 0; } else { y = super.getHeight() - bubble.getHeight(); } bubbleX = x; bubbleY = y; } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) {} }
- 实例代码
- 分类
-
位置服务
- LocationProvider
package com.jamin.locationprovider; import android.location.Criteria; import android.location.LocationManager; import android.location.LocationProvider; import android.os.Bundle; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import java.util.Iterator; import java.util.List; public class Main2Activity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); // 获取位置服务 LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); // 获取所有位置服务的提供 List<String> allProviders = locationManager.getAllProviders(); StringBuilder stringBuilder = new StringBuilder(); for (Iterator<String> iterator = allProviders.iterator(); iterator.hasNext(); ) { stringBuilder.append(iterator.next() + "\n"); } TextView textView = findViewById(R.id.tv0); textView.setText(stringBuilder.toString()); LocationProvider provider = locationManager.getProvider(LocationManager.GPS_PROVIDER); TextView textView1 = findViewById(R.id.tv1); textView1.setText(provider.getName()); // 创建过滤条件对象 Criteria criteria = new Criteria(); // 不收费 criteria.setCostAllowed(false); // 精度最精确 criteria.setAccuracy(Criteria.ACCURACY_FINE); // 耗电量最低 criteria.setPowerRequirement(Criteria.POWER_LOW); // 获取最佳位置服务 String bestProvider = locationManager.getBestProvider(criteria, true); TextView textView2 = findViewById(R.id.tv2); textView2.setText(bestProvider); } }
- 获取经纬度
package com.jamin.locationprovider; import android.Manifest; import android.content.pm.PackageManager; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; public class Main3Activity extends AppCompatActivity { private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main3); LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); textView = findViewById(R.id.lcoation); // 检查权限 if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // TODO: Consider calling // Activity#requestPermissions // here to request the missing permissions, and then overriding // public void onRequestPermissionsResult(int requestCode, String[] permissions, // int[] grantResults) // to handle the case where the user grants the permission. See the documentation // for Activity#requestPermissions for more details. return; } locationManager.requestLocationUpdates( // 使用GPS LocationManager.GPS_PROVIDER, // 间隔时间1s 1000, // 位置间隔1米 1, // 位置更新监听器 new LocationListener() { @Override public void onLocationChanged(Location location) {} @Override public void onStatusChanged(String provider, int status, Bundle extras) {} @Override public void onProviderEnabled(String provider) {} @Override public void onProviderDisabled(String provider) {} }); Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); locationUpdate(lastKnownLocation); } private void locationUpdate(Location location) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("经度" + location.getLongitude()); stringBuilder.append("纬度" + location.getLatitude()); textView.setText(stringBuilder.toString()); } }
- 百度地图的应用
package com.jamin.baidumap; import android.location.Location; import android.os.Bundle; import android.util.Log; import androidx.appcompat.app.AppCompatActivity; import com.baidu.location.BDLocation; import com.baidu.location.BDLocationListener; import com.baidu.location.LocationClient; import com.baidu.location.LocationClientOption; import com.baidu.mapapi.CoordType; import com.baidu.mapapi.SDKInitializer; import com.baidu.mapapi.map.BaiduMap; import com.baidu.mapapi.map.BitmapDescriptor; import com.baidu.mapapi.map.BitmapDescriptorFactory; import com.baidu.mapapi.map.MapStatus; import com.baidu.mapapi.map.MapStatusUpdateFactory; import com.baidu.mapapi.map.MapView; import com.baidu.mapapi.map.MarkerOptions; import com.baidu.mapapi.map.MyLocationData; import com.baidu.mapapi.map.OverlayOptions; import com.baidu.mapapi.model.LatLng; /** * @author Jamin * @date 2019/10/23 * @desc 初始化地图并配置生命周期 */ public class MainActivity extends AppCompatActivity implements BDLocationListener { private MapView mapView; private BaiduMap baiduMap; // 防止每次定位都重新设置中心点和marker private boolean isFirstLocation = true; // 初始化LocationClient定位类 private LocationClient mLocationClient = null; // 经纬度 private double lat; private double lon; private boolean isFirst = true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 初始化sdk SDKInitializer.initialize(getApplicationContext()); // 设置经纬度类型 SDKInitializer.setCoordType(CoordType.GCJ02); setContentView(R.layout.activity_main); mapView = findViewById(R.id.bmapView); // 获取百度地图对象 baiduMap = mapView.getMap(); // 声明LocationClient类 mLocationClient = new LocationClient(this); // 注册监听函数 mLocationClient.registerLocationListener(this); initLocation(); // 开始定位 mLocationClient.start(); } private void locationUpdate(Location location) { if (location != null) { LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); Log.d("经纬度", location.getLatitude() + "--------" + location.getLongitude()); if (isFirst) { MapStatus mapStatus = new MapStatus.Builder().target(latLng).zoom(18f).build(); // 设置地图位置 baiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(mapStatus)); isFirst = false; // 构造定位数据 MyLocationData myLocationData = new MyLocationData.Builder() // 准确性 .accuracy(location.getAccuracy()) // 方向 .direction(100) // 纬度 .latitude(location.getLatitude()) // 经度 .longitude(location.getLongitude()) .build(); // 设置定位数据 baiduMap.setMyLocationData(myLocationData); // 设置图标 BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.drawable.icon_geo); // 构建Marker图标 BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(R.drawable.icon_geo); // 构建MarkerOption,用于在地图上添加Marker OverlayOptions option = new MarkerOptions().position(latLng).icon(bitmap); // 在地图上添加Marker,并显示 baiduMap.addOverlay(option); } } else { Log.d("经纬度", "无法获取"); } } @Override protected void onStart() { super.onStart(); baiduMap.setMyLocationEnabled(true); } @Override protected void onStop() { super.onStop(); baiduMap.setMyLocationEnabled(false); } @Override protected void onPause() { super.onPause(); mapView.onPause(); } @Override protected void onDestroy() { super.onDestroy(); mapView.onDestroy(); mapView = null; } @Override protected void onResume() { super.onResume(); mapView.onResume(); } @Override public void onReceiveLocation(BDLocation bdLocation) { if (isFirst) { isFirst = false; // 设置并显示中心点 MyLocationData locData = new MyLocationData.Builder() .accuracy(bdLocation.getRadius()) .direction(bdLocation.getRadius()) .latitude(bdLocation.getLatitude()) .longitude(bdLocation.getLongitude()) .build(); baiduMap.setMyLocationData(locData); LatLng ll = new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude()); MapStatus.Builder builder = new MapStatus.Builder(); builder.target(ll).zoom(18.0f); baiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build())); } } /** 配置定位参数 */ private void initLocation() { LocationClientOption option = new LocationClientOption(); // 可选,默认高精度,设置定位模式,高精度,低功耗,仅设备 option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy); // 可选,默认gcj02,设置返回的定位结果坐标系 option.setCoorType("bd09ll"); // 可选,默认0,即仅定位一次,设置发起定位请求的间隔需要大于等于1000ms才是有效的 int span = 5000; option.setScanSpan(span); // 可选,设置是否需要地址信息,默认不需要 option.setIsNeedAddress(true); // 可选,默认false,设置是否使用gps option.setOpenGps(true); // 可选,默认false,设置是否当GPS有效时按照1S/1次频率输出GPS结果 option.setLocationNotify(true); // 可选,默认false,设置是否需要位置语义化结果,可以在BDLocation.getLocationDescribe里得到,结果类似于“在北京天安门附近” option.setIsNeedLocationDescribe(true); // 可选,默认false,设置是否需要POI结果,可以在BDLocation.getPoiList里得到 option.setIsNeedLocationPoiList(true); // 可选,默认true,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认不杀死 option.setIgnoreKillProcess(false); // 可选,默认false,设置是否收集CRASH信息,默认收集 option.SetIgnoreCacheException(false); // 可选,默认false,设置是否需要过滤GPS仿真结果,默认需要 option.setEnableSimulateGps(false); mLocationClient.setLocOption(option); } /** * 设置中心点和添加marker * * @param map * @param bdLocation * @param isShowLoc */ public void setPosition2Center(BaiduMap map, BDLocation bdLocation, Boolean isShowLoc) { MyLocationData locData = new MyLocationData.Builder() .accuracy(bdLocation.getRadius()) .direction(bdLocation.getRadius()) .latitude(bdLocation.getLatitude()) .longitude(bdLocation.getLongitude()) .build(); map.setMyLocationData(locData); if (isShowLoc) { LatLng ll = new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude()); MapStatus.Builder builder = new MapStatus.Builder(); builder.target(ll).zoom(18.0f); map.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build())); } } }
// 将jar和so文件放在libs文件夹下 导入jar包 sourceSets { main { jniLibs.srcDirs = ['libs'] } }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <!--百度地图的view--> <com.baidu.mapapi.map.MapView android:id="@+id/bmapView" android:layout_width="match_parent" android:layout_height="match_parent" android:clickable="true" /> </LinearLayout>
- LocationProvider
Android入门
最新推荐文章于 2020-11-12 16:51:57 发布