参考书籍:Android第一行代码(第二版).郭霖著

1、通知

Notification是Android中较有特色的功能,当应用程序希望向用户发出提示信息但不在前台运行时可使用(手机顶部显示通知图标,下拉后看到详细内容)。

(1)基本用法
可在活动(较少,一般进入后台才需要)、广播接收器、服务里创建。

步骤:
a、获取NotificationManager实例:

NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
//调用Context的getSystemService()方法,参数用于确定获取系统哪个服务

b、使用Builder构造器创建Notification对象。由于Android每个版本API不稳定,使用support库中的兼容API(support-4v中提供NotificationCompat类),保证程序在所有Android系统版本上正常工作:

Notification notification = new NotificationCompat.Builder(context).setContentTitle("This is content title").setContentText("This is content text").setWhen(System.currentTimeMillis()).setSmallIcon(R.drawable.small_icon).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.large_icon)).build();//可在build()方法之前连缀任意多设置方法来创建丰富的Notification对象

上述调用的五个设置方法:指定通知的标题内容(下拉时可见)、指定通知的正文内容(下拉时可见)、指定通知被创建的时间(毫秒,下拉时显示在通知上)、设置通知小图标(只能用纯alpha甑图片,显示在系统状态栏上)、设置通知大图标(下拉时显示)。

c、调用NotificationManager的notify()方法显示通知。

manager.notify(1, notification);//第一个参数为id(保证为每个通知指定的都不同)

例:新建NotificationTest项目,修改布局文件,添加一个用于发送通知的按钮即可。修改主程序:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button sendNotice = (Button) findViewById(R.id.send_notice);sendNotice.setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()){case R.id.send_notice:NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);Notification notification = new NotificationCompat.Builder(this).setContentTitle("This is content title").setContentText("This is content text").setWhen(System.currentTimeMillis()).setSmallIcon(R.mipmap.ic_launcher).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)).build();manager.notify(1, notification);break;default:break;}}
}

运行程序,点击按钮。

通知现在点击无反应。需使用PendingIntent(与Intent(更倾向于立即执行某个动作)类似,但更倾向于在某个合适的时机去执行某个动作)。它主要提供几个静态方法用于获取PendingIntent实例:getActivity()/getBroadcast()/getService()(参数相同:第一个是Context, 第二个一般用不到(传入0即可),第三个是Intent对象(可通过其构建PendingIntent的“意图”),第四个用于确定PendingIntent的行为(FLAG_ONE_SHOT/FLAG_NO_CREATE/FLAG_CANCLE_CURRENT/FLAG_UPDATE_CURRENT四种值可选,通常传入0))。

NotificationCompat.Builder还可再连缀一个SetContent()方法(参数正是PendingIntent对象)。

优化NotificationTest项目。需准备另一个活动NotificationActivity,布局文件notification_layout,修改其中代码:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><TextView
        android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:textSize="24sp"android:text="This is notification layout"/></RelativeLayout>

修改MainActivity:

...
public void onClick(View v) {switch (v.getId()){case R.id.send_notice:**Intent intent = new Intent(this, NotificationActivity.class);PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);**NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);Notification notification = new NotificationCompat.Builder(this).setContentTitle("This is content title").setContentText("This is content text").setWhen(System.currentTimeMillis()).setSmallIcon(R.mipmap.ic_launcher).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))**.setContentIntent(pi)**.build();manager.notify(1, notification);break;default:break;}}...

重新运行程序,点击按钮,点击通知,就会看到NotificationActivity活动界面。

此时发现系统状态上的通知图标没消失(代码中没取消)。两种方法可解决:NotificationCompat.Builder连缀setAutoCancel()方法(设置为true),显式调用NotificationManager的cancel()方法。第二种方法如下,在NotificationActivity中修改:

public class NotificationActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.notification_layout);NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);manager.cancel(1);//参数为通知的id}
}

运行程序:

(2)进阶技巧

NotificationCompat.Builder中提供了丰富的API。常用的:

setSound():在通知发出时播放一段音频。每个手机的/system/media/audio/ringtones目录下都有很多音频文件。例:

Notification notification = new NotificationCompat.Builder(this)....setSound(Uri.fromFile(new File("/system/media/audio/ringtones/Luna.ogg"))).build();

setVibrate:让手机振动,接收长整型数组(设置手机静止和振动时长,毫秒,下标为0的值表静止时长,下标为1的表振动时长,下标为2表静止,依次交替)。例:

Notification notification = new NotificationCompat.Builder(this)....setVibrate(new long[]{0, 1000, 1000, 1000})//通知来到时立即振动1秒,后静止1秒,再振动1秒.build();

控制振动需声明权限:

<uses-permission android:name="android.permission.VIBRATE"/>

setLights:控制手机前置的LED灯。接收三个参数:指定LED灯颜色,指定亮起时长(毫秒),指定暗去时长(毫秒)。例:

Notification notification = new NotificationCompat.Builder(this)....setLights(Color.GREEN, 1000, 1000).build();

以上方法具体参数需根据手机做适当修改。

也可直接使用通知的默认效果setDefaults。例:

Notification notification = new NotificationCompat.Builder(this)....setDefaults(NotificationCompat.DEFAULT_ALL).build();

(3)高级功能

NotificationCompat.Builder中更强大的API方法。
setStyle():允许构建富文本的通知内容(除文字和图标外,还有更多元素,如长文字、图片等)。接收NotificationCompat.Style()参数,例:

Notification notification = new NotificationCompat.Builder(this)....seSyle(new NotificationCompat.BigTextStyle().bigTest("Learn how to buid notifications, send and sync data, and use voice actions.Get the official Android IDE and developer tools to build apps for Android.")).build();

还可显示一张大图:

Notification notification = new NotificationCompat.Builder(this)....seSyle(new NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(getResources(), R.drawable.big_image))).build();

setPriority():设置通知的重要程度。5个常量值可选:PRIORITY_DEFAULT(默认,跟不设置一样)、PRIORITY_MIN(最低,可能只会在特定场景显示,如下拉状态栏时)、PRIORITY_LOW(较低,可能会缩小或改变显示顺序在更重要通知之后)、PRIORITY_HIGH(较高,能能会放大或排在比较靠前位置)、PRIORITY_MAX(最高,必须让用户立即看到并做出响应)。例:

Notification notification = new NotificationCompat.Builder(this)....sePriority(NotificationCompat.PRIORITY_MAX).build();

运行效果如下:

2、摄像头和相册

(1)调用摄像头拍照

在应用程序里调用手机摄像头进行拍照。新建CameraAlbumTest项目,修改布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><Button
        android:id="@+id/take_photo"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Take Photo"/><ImageView
        android:id="@+id/picture"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal" />
</LinearLayout>

一个用于拍照,一个用于显示。修改MainActivity:

public class MainActivity extends AppCompatActivity {public static final int TAKE_PHOTO = 1;private ImageView picture;private Uri imageUri;/*** ATTENTION: This was auto-generated to implement the App Indexing API.* See https://g.co/AppIndexing/AndroidStudio for more information.*/private GoogleApiClient client;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button takePhoto = (Button) findViewById(R.id.take_photo);picture = (ImageView) findViewById(R.id.picture);takePhoto.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//创建File对象,用于存储拍照后的图片,// 存放在手机SD卡的应用关联缓存目录(SD卡中专门用于存放当前应用缓存数据的位置)下,getExternalCacheDir()方法可得到//具体路径是/sdcard/Android/data/<package name>/cache//Android6.0开始,读写SD卡被列为危险权限,如果存放在SD卡其他目录需进行运行时权限处理,使用此目录则不用File outputImage = new File(getExternalCacheDir(), "output_image.jpg");try {if (outputImage.exists()) {outputImage.delete();}outputImage.createNewFile();} catch (IOException e) {e.printStackTrace();}if (Build.VERSION.SDK_INT >= 24) {//如果运行设备的系统版本等于或高于Android7.0imageUri = FileProvider.getUriForFile(MainActivity.this, "com.example.jojo.cameraalbumtest.fileprovider", outputImage);//将File对象转换成一个封装过的Uri对象。三个参数:Context对象,任意唯一字符串,File对象//Android7.0后,直接访问本地真实路径的Uri被认为不安全,会抛出异常,// 而FileProvider是一种特殊的内容提供器(使用和内容提供器类似的机制保护数据),可选择性地将封装过的Uri共享给外部,提高应用安全} else {//如果运行设备的系统版本低于Android7.0,此Uri对象标识着output_image.jpg图片的本地真实路径imageUri = Uri.fromFile(outputImage);}//启动相机程序Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//指定图片输出地址为刚刚得到的Uri对象startActivityForResult(intent, TAKE_PHOTO);}});}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {switch (requestCode){case TAKE_PHOTO:if (resultCode == RESULT_OK){try {//将照片显示出来Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));picture.setImageBitmap(bitmap);} catch (FileNotFoundException e) {e.printStackTrace();}}break;default:break;}}

还需注册内容提供器:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.jojo.cameraalbumtest"><!--android4.4系统之前,访问SD卡的应用关联目录要声明权限--><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><application
        android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><!-- ATTENTION: This was auto-generated to add Google Play services to your project forApp Indexing.  See https://g.co/AppIndexing/AndroidStudio for more information. --><meta-data
            android:name="com.google.android.gms.version"android:value="@integer/google_play_services_version" /><!--其中,name属性固定,authorities值必须与FileProvider.getUriForFile()中第二个参数一致,内部使用<meta-data>来指定Uri的共享路径,并引用了@xml/file_paths资源(res->New->Directory创建)--><provider
            android:authorities="com.example.jojo.cameraalbumtest.fileprovider"android:name="android.support.v4.content.FileProvider"android:exported="false"android:grantUriPermissions="true"><meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths"/></provider></application></manifest>

在xml文件夹下创建file_paths.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android"><!--指定Uri共享,name属性值随便填,path的值表示共享的具体路径,空值表示将整个SD卡进行共享--><external-path name="my_images" path=""/>
</paths>

将程序运行到手机上,点击按钮进行拍照,完成后返回。

(2)从相册中选择照片

编辑activity_main.xml文件,添加一个选择照片的按钮,修改主程序:

public class MainActivity extends AppCompatActivity {...public static final int CHOOSE_PHOTO = 2;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button takePhoto = (Button) findViewById(R.id.take_photo);picture = (ImageView) findViewById(R.id.picture);...Button chooseFromAlbum = (Button)findViewById(R.id.choose_from_album);chooseFromAlbum.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){//相册中的照片都是存储在SD卡上的,需要申请运行时权限,WRITE_EXTERNAL_STORAGE是危险权限,表示同时授予程序对SD卡的读和写的能力ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);}else {openAlbum();}}});}private void openAlbum(){Intent intent = new Intent("android.intent.action.GET_CONTENT");intent.setType("image/*");startActivityForResult(intent,CHOOSE_PHOTO);//打开相册}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {switch (requestCode){case 1:if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){openAlbum();}else {Toast.makeText(this, "You denied the permission", Toast.LENGTH_SHORT).show();}break;default:}}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {switch (requestCode){...case CHOOSE_PHOTO:if (resultCode == RESULT_OK){//判断手机系统版本号if (Build.VERSION.SDK_INT >= 19){//4.4及以上系统使用此方法处理图片(此版本开始,选取相册中的图片不再返回图片的真实Uri,而是封装过的Uri)handleImageOnKitKat(data);}else {//4.4以下系统使用此方法处理图片handleImageBeforeKitKat(data);}}break;default:break;}}@TargetApi(Build.VERSION_CODES.KITKAT)private void handleImageOnKitKat(Intent data){String imagePath = null;Uri uri = data.getData();if (DocumentsContract.isDocumentUri(this, uri)){//如果是document类型的Uri,则通过document id处理String docId = DocumentsContract.getDocumentId(uri);if ("com.android.providers.media.documents".equals(uri.getAuthority())){//如果Uri的authority是media格式的话,id还需再进行一次解析String id = docId.split(":")[1];//字符串分割解析出数字格式的id(字符串后半部分才是真正的数字id)String selection = MediaStore.Images.Media._ID + "=" + id;//构建新的Uri和条件语句imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);//获得图片真实路径}else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())){Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId));imagePath = getImagePath(contentUri, null);}else if ("content".equalsIgnoreCase(uri.getScheme())){//如果是content类型的Uri,则使用普通方式处理imagePath = getImagePath(uri, null);}else if ("file".equalsIgnoreCase(uri.getScheme())){//如果是file类型的Uri,直接获取图片路径即可imagePath = uri.getPath();}displayImage(imagePath);//根据图片路径显示图片}}private void handleImageBeforeKitKat(Intent data){Uri uri = data.getData();String imagePath = getImagePath(uri, null);displayImage(imagePath);}private String getImagePath(Uri uri, String selection){String path = null;//通过Uri和selection来获取真实的图片路径Cursor cursor = getContentResolver().query(uri, null, selection,null,null);if (cursor != null){if (cursor.moveToFirst()){path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));}cursor.close();}return path;}private void displayImage(String imagePath){if (imagePath != null){Bitmap bitmap = BitmapFactory.decodeFile(imagePath);picture.setImageBitmap(bitmap);}else {Toast.makeText(this, "failed to get image",Toast.LENGTH_SHORT).show();}}

将程序重新运行,授予权限后,随意选择一张照片回到程序界面。(手机如没有SD卡,选择图片后返回没任何图片显示,也没Toast弹出,这里是模拟器的效果)


3、播放多媒体文件

(1)音频

一般使用MediaPlayer类实现,常用的控制方法如下:

工作流程:创建MediaPlayer对象;调用setDataSource()设置音频文件路径;
调用prepare()进入到准备状态;调用start()开始播放音频;调用pause()暂停播放;
调用reset()停止播放。

新建PlayAudioTest项目,修改布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:id="@+id/play"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Play" /><Buttonandroid:id="@+id/pause"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Pause" /><Buttonandroid:id="@+id/stop"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Stop" /></LinearLayout>

修改MainActivity:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{private MediaPlayer mediaPlayer = new MediaPlayer();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button play = (Button) findViewById(R.id.play);Button pause = (Button) findViewById(R.id.pause);Button stop = (Button) findViewById(R.id.stop);play.setOnClickListener(this);pause.setOnClickListener(this);stop.setOnClickListener(this);if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(MainActivity.this, new  String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);}else {initMediaPlayer();}}private void initMediaPlayer(){try {File file = new File(Environment.getExternalStorageDirectory(), "music.mp3");//SD下,音乐文件夹下的音乐mediaPlayer.setDataSource(file.getPath());//指定音频文件路径mediaPlayer.prepare();//让MediaPlayer进入准备状态} catch (Exception e) {e.printStackTrace();}}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {switch (requestCode){case 1:if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){initMediaPlayer();}else {Toast.makeText(this, "拒绝权限将无法使用程序", Toast.LENGTH_SHORT).show();finish();}break;default:}}@Overridepublic void onClick(View v) {switch (v.getId()){case R.id.play:if (! mediaPlayer.isPlaying()){mediaPlayer.start();//开始播放}break;case R.id.pause:if (mediaPlayer.isPlaying()){mediaPlayer.pause();//暂停播放}break;case R.id.stop:if (mediaPlayer.isPlaying()){mediaPlayer.reset();//停止播放initMediaPlayer();}break;default:break;}}@Overrideprotected void onDestroy() {super.onDestroy();if (mediaPlayer != null){mediaPlayer.stop();mediaPlayer.release();//释放资源}}
}

还需声明权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

在手机上运行程序,正常。

(2)视频

主要使用VideoView类实现,其将视频的显示和控制集于一身。常用方法如下:

新建PlayVideoTest项目,修改布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayout
        android:layout_width="match_parent"android:layout_height="wrap_content"><Button
            android:id="@+id/play"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="Play"/><Button
            android:id="@+id/pause"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="Pause"/><Button
            android:id="@+id/replay"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="Replay"/></LinearLayout><VideoView
        android:id="@+id/video_view"android:layout_width="match_parent"android:layout_height="wrap_content" />
</LinearLayout>

修改MainActivity:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{private VideoView videoView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);videoView = (VideoView)findViewById(R.id.video_view);Button play = (Button) findViewById(R.id.play);Button pause = (Button) findViewById(R.id.pause);Button replay = (Button) findViewById(R.id.replay);if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);}else {initVideoPath();}}private void initVideoPath(){File file = new File(Environment.getExternalStorageDirectory(), "/movie.mp4");videoView.setVideoPath(file.getPath());//指定视频文件路径}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {switch (requestCode){case 1:if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){initVideoPath();}else {Toast.makeText(this, "拒绝权限将无法使用程序", Toast.LENGTH_SHORT).show();finish();}break;default:}}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.play:if (!videoView.isPlaying()) {videoView.start();//开始播放}break;case R.id.pause:if (videoView.isPlaying()) {videoView.pause();//暂停播放}break;case R.id.replay:if (videoView.isPlaying()) {videoView.resume();//重新播放}break;default:break;}}@Overrideprotected void onDestroy() {super.onDestroy();if (videoView != null){videoView.suspend();}}
}

同样声明权限。在手机上运行程序。
VideoView只是做了很好的封装,背后仍是使用MediaPlayer对视频文件进行控制的。但VideoView在视频格式的支持及播放效率方面有较大不足,只用于播放一些游戏片头动画或视频宣传还是够的。

Android学习笔记——手机多媒体运用相关推荐

  1. Android学习-运用手机多媒体-通知使用技巧、调用摄像头拍照、从相册中选取照片、播放音频和视频文件(MediaPlayer、VideoView)

    android提供了一系列的API,使得我们可以在程序中调用很多的多媒体资源,从而编写出更加丰富多彩的应用程序. 使用通知 通知(Notification)是Android系统中比较有特色的一个功能, ...

  2. Android学习(运用手机多媒体)

    一.使用通知Notification: 当某个应用程序希望向用户发出一些提示信息,而该程序又不在前台运行时,就可以借助通知来实现. 1.通知的基本用法: 通知可以在活动.在广播接收器或在服务里创建. ...

  3. android学习笔记---手机拍照功能的实现,及原理

    45_拍照 ------------------------------------------------------------------- 在main.xml布局文件添加用于显示取景画面的Su ...

  4. Android学习笔记07---查看Android虚拟机输出的错误信息与如何部署应用到自己的真实手机

    Android学习笔记07---查看Android虚拟机输出的错误信息

  5. Android学习笔记36:使用SQLite方式存储数据

    在Android中一共提供了5种数据存储方式,分别为: (1)Files:通过FileInputStream和FileOutputStream对文件进行操作.具体使用方法可以参阅博文<Andro ...

  6. Pro Android学习笔记(二九):用户界面和控制(17):include和merge

    xml控件代码重用:include 如果我们定义一个控件,需要在不同的layout中重复使用,或者在同一个layout中重复使用,可以采用include的方式.例如定义my_button.xml如下 ...

  7. 【转】 Pro Android学习笔记(二九):用户界面和控制(17):include和merge

    目录(?)[-] xml控件代码重用include xml控件代码重用merge 横屏和竖屏landsacpe portrait xml控件代码重用:include 如果我们定义一个控件,需要在不同的 ...

  8. Android学习笔记之AndroidManifest.xml文件解析(摘自皮狼的博客)

    Android学习笔记之AndroidManifest.xml文件解析 一.关于AndroidManifest.xml AndroidManifest.xml 是每个android程序中必须的文件.它 ...

  9. Android学习笔记:Android基础知识点(不断更新中)

    1.Android学习笔记:OkHttp 2.Android学习笔记:更新UI的方法(UI线程和非UI线程) 3.Android学习笔记:Volley 4.Android学习笔记:Handler 5. ...

最新文章

  1. nginx+keepalived双机热备
  2. 桌面虚拟化最佳实践4—存储规划(下)
  3. LeetCode 333. 最大 BST 子树(递归)*
  4. python制作中文词云_Python如何生成词云(详解)
  5. 【script】数据处理的瑞士军刀 pandas
  6. UnhandledPromiseRejectionWarning报错send()的处理
  7. 2017.8.15 数据库
  8. Android-广播
  9. 题解 P4147 【玉蟾宫】
  10. 【Xilinx】Zynq\MPSoc\Versal不同速度等级下的ARM主频
  11. Java中开根号,你还记得吗
  12. 动态加载Animator和AnimatorController
  13. oracle大于字符串时间,Oracle
  14. 在python中对文件操作的一般步骤是_python中对文件的操作
  15. Kinect入门介绍---Kinect V2开发学习(1)
  16. vlan(三种模式)实验
  17. 使用printf函数输出
  18. Android 蓝牙APP设计
  19. 使用ImageMagick操作gif图
  20. 多测师_Python 介绍

热门文章

  1. Ansoft HFSS v15.0 win32_64 Full-ISO 2DVD(三维结构电磁场仿真软件)
  2. 中国的生存法则变了,你再不懂就晚了
  3. NSIS ERROR NSIS病毒新型变种 解决办法
  4. Chrome扩展学习Demo(三):将浏览器地址栏的网址转换为二维码
  5. Codeforces 196 E. Tricky and Cleve Password
  6. 九款能将PowerPoint转换成PDF的免费软件
  7. bugku-PWN-瑞士军刀解析过程
  8. 小光棍数(同余定理)
  9. Tello:无人机新姿势识别(小创实验)
  10. 【PMP】项目章程总结