Android开发从0开始(ContentProvider与数据)

内容提供者:ContentProvider

  为App存取内部数据提供外部接口,让不同应用共享数据。

①在配置里AndroidManifest.xml       

 <provider

            android:name=".UserInfoProvider"

            android:authorities="com.example.chapter07_server.provider.UserInfoProvider"

            android:enabled="true"

            android:exported="true"/>

危险权限表

运行时动态申请权限Lazy模式:

①检查是否开启指定权限:

public class PermissionUtil {

    //检查权限,返回true则已完全启用权限,返回false表示未完全启用权限

    public static boolean checkPermission(Activity act,String[] permissions,int requestCode)

    {

        int check = PackageManager.PERMISSION_GRANTED;

        //逐一将各个权限取出判断

        for(String permission: permissions){

            ContextCompat.checkSelfPermission(act,permission);

            check=ContextCompat.checkSelfPermission(act,permission);

            if(check!=PackageManager.PERMISSION_GRANTED){break;}

        }

  //②若有未开启的权限,则请求系统弹窗

        if (check!=PackageManager.PERMISSION_GRANTED){

            ActivityCompat.requestPermissions(act,permissions,requestCode);

            return false;

        }

            return true;   }  }

  ③判断用户的权限选择结果

    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        //判断用户是否授权

        switch (requestCode){

            case REQUEST_CODE_CONTACTS:

                if(PermissionUtil.checkGRant(grantResults)){

                    Log.d("ning","通讯录权限获取成功");

                }else

                {

                    Log.d("ning","获取通讯录读写权限失败");

                }

                break;

            case REQUEST_CODE_SMS:

                if (PermissionUtil.checkGRant(grantResults)){

                    Log.d("ning","收发短信权限获取成功");

                }else

                {

                    Log.d("ning","收发短信权限获取失败");

  jumpToSetting();

                }

                break;    }    }

    //跳转带应用设置界面

    private  void jumpToSetting(){

        Intent intent = new Intent();

        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);

        intent.setData(Uri.fromParts("package",getPackageName(),null));

        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        startActivity(intent);

    }

运行时动态申请权限Hunger模式:直接在onCreate中申请所有权限。

ContentResovler基本用法

添加联系人:

public void onClick(View view) {

        int id = view.getId();

        if (id == R.id.add) {//创建一个联系人对象

            Contact contact = new Contact();

            contact.name= et_name.getText().toString().trim();

            contact.email=et_email.getText().toString().trim();

            contact.phone=et_phone.getText().toString().trim();

            //方法一,使用ContentResolver多次写入.

            addContacts(getContentResolver(),contact);

        } else if (id == R.id.find) {

        }

}

    //往手机通讯录里添加一个联系人

    private void addContacts(ContentResolver resolver, Contact contact) {

        ContentValues values = new ContentValues();

        Uri uri= resolver.insert(ContactsContract.RawContacts.CONTENT_URI,values);

        long rawContactId = ContentUris.parseId(uri);

        ContentValues name = new ContentValues();

        //关联联系人编号

        name.put(Contacts.Data.RAW_CONTACT_ID,rawContactId);

        //"姓名"数据类型

        name.put(Contacts.Data.MIMETYPE,CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);

        //联系人的姓名

        name.put(Contacts.Data.DATA2,contact.name);

        //往提供器添加联系人姓名

        resolver.insert(ContactsContract.Data.CONTENT_URI,name);

        ContentValues phone = new ContentValues();

        //关联联系人编号

        phone.put(Contacts.Data.RAW_CONTACT_ID,rawContactId);

        //"电话号码"数据类型

        phone.put(Contacts.Data.MIMETYPE,CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);

        //联系人的电话号码

        phone.put(Contacts.Data.DATA2,contact.phone);

        phone.put(Contacts.Data.DATA2,CommonDataKinds.phone.TYPE_MOBILE);

        //往提供器添加联系人姓名电话号码

        resolver.insert(ContactsContract.Data.CONTENT_URI,phone);

        ContentValues email = new ContentValues();

        //关联联系人编号

        email.put(Contacts.Data.RAW_CONTACT_ID,rawContactId);

        //"邮箱"数据类型

        email.put(Contacts.Data.MIMETYPE,CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);

        //联系人的邮箱

        email.put(Contacts.Data.DATA2,contact.email);

        //往提供器添加联系人邮箱

        resolver.insert(ContactsContract.Data.CONTENT_URI,email);

    }

批量处理添加联系人:

private void addFullContacts(ContentResolver resolver , Contact contact){

        //构建一个插入联系人主记录的内容操作器

        ContentProviderOperation op_main=ContentProviderOperation

                .newInsert(ContactsContract.RawContacts.CONTENT_URI)

                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME,null)

                .build();

      //构建对于姓名的操作

      ContentProviderOperation op_name= ContentProviderOperation

              .newInsert(ContactsContract.RawContacts.CONTENT_URI)

              .withValueBackReference(Contacts.Data.RAW_CONTACT_ID,0)

              .withValue(Contacts.Data.MIMETYPE,CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)

              .withValue(Contacts.Data.DATA2,contact.name)

              .build();

        //构建对于电话号码操作

        ContentProviderOperation phone= ContentProviderOperation

                .newInsert(ContactsContract.RawContacts.CONTENT_URI)

                .withValueBackReference(Contacts.Data.RAW_CONTACT_ID,0)

                .withValue(Contacts.Data.MIMETYPE,CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)

                .withValue(Contacts.Data.DATA2,contact.phone)

                .build();

        //构建对于邮箱的操作

        ContentProviderOperation email= ContentProviderOperation

                .newInsert(ContactsContract.RawContacts.CONTENT_URI)

                .withValueBackReference(Contacts.Data.RAW_CONTACT_ID,0)

                .withValue(Contacts.Data.MIMETYPE,CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)

                .withValue(Contacts.Data.DATA2,contact.email)

                .build();

        //构建列表将三个操作放入

        ArrayList<ContentProviderOperation> operations=new ArrayList<>();

        operations.add(op_main);

        operations.add(op_name);

        operations.add(phone);

        operations.add(email);

        //批处理提交四个操作

        try {

            resolver.applyBatch(ContactsContract.AUTHORITY,operations);

        } catch (OperationApplicationException e) {

            throw new RuntimeException(e);

        } catch (RemoteException e) {

            throw new RuntimeException(e);      }    }

批量查询联系人:

     //查询通讯录信息

    @SuppressLint("Range")

    private void readPhoneContacts(ContentResolver resolver ) {

      Cursor cursor= resolver.query(ContactsContract.RawContacts.CONTENT_URI,new String[]{ContactsContract.RawContacts._ID},null,null,null,null);

      while (cursor.moveToNext()){

          int rawContactId = cursor.getInt(0);

          Uri uri = Uri.parse("content://com.android.contacts/contacts"+rawContactId+"/data");

        Cursor dataCursor=resolver.query(uri,new String[]{Contacts.Data.MIMETYPE,Contacts.Data.DATA1,Contacts.Data.DATA2},null,null,null);

        Contact contact = new Contact();

        while (dataCursor.moveToNext()){

           String data1= dataCursor.getString(dataCursor.getColumnIndex(Contacts.Data.DATA1));

           String mimeType=dataCursor.getString(dataCursor.getColumnIndex(Contacts.Data.MIMETYPE));

           switch (mimeType){

               case CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE:

                   contact.name=data1; break;

               case CommonDataKinds.Email.CONTENT_ITEM_TYPE:

                   contact.Email=data1; break;

               case CommonDataKinds.Phone.CONTENT_ITEM_TYPE:

                   contact.Phone=data1; break;

           }

        }

        dataCursor.close();

      }

      cursor.close();   }

ContentObserver监听短信:

  public class MonitorSmsActivity extends AppCompatActivity {

    private SmsGetObserver mObserver;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_monitor_sms);

        //指定一个注册内容观察器,一单数据发生变化,就触发OnChange方法

        Uri uri = Uri.parse("content://sms");

        mObserver = new SmsGetObserver(this);

        getContentResolver().registerContentObserver(uri,true,mObserver);

    }

    protected void onDestroy(){

        super.onDestroy();

        getContentResolver().unregisterContentObserver(mObserver);

    }

    private static class SmsGetObserver extends ContentObserver {

        private final Context mContext;

        public SmsGetObserver(Context context){

            super(new Handler(Looper.getMainLooper()));

            this.mContext=context;   }

public void onChange(boolean selfChange, @Nullable Uri uri){

            super.onChange(selfChange,uri);   

            if(uri==null){return;}

            if(uri.toString().contains("content://sms/raw")||uri.toString().equals("content://sms")) {return;}

            Cursor cursor = mContext.getContentResolver().query(uri, new String[]{"address", "body", "date"}, null, null, "date DESC");

            if(cursor.moveToNext()){

                //短信的发送号码

                @SuppressLint("Range")  String sender=cursor.getString(cursor.getColumnIndex("address"));

                @SuppressLint("Range")  String content=cursor.getString(cursor.getColumnIndex("body"));

                Log.d("ning",String.format("sender:%s,content:%s",sender,content));

            }

            cursor.close();

        }

    }   }

跳转选择图片:

  ①创建意图

  Intent intent = new Intent(Intent.ACTION_GET_CONTENT );

②设置图片内容类型与跳转

Intent.setType(image/*);

mResultLauncher.launch(intent );

FileProvider:

 继承于ContentProvider,对第三方应用暴露文件,并授权读写操作的权限。

①首先在AndroidManifest.xml文件中配置

        <provider

            android:authorities="@string/file_provider"

            android:name="androidx.core.content.FileProvider"

            android:grantUriPermissions="true">

        <!--配置哪些路径是可以通过FileProvider访问-->

            <meta-data android:name="android.support.FILE_PROVIDER_PATHS"

                android:resource="@xml/file_paths"/>

        </provider>

②其次在对应路径xml的文件夹中的file_paths中写配置文件。

③在代码中对应实现。  

访问其他程序中的数据:

  ①使用现有的内容提供器来读取和操作相应的程序数据

  ②创建自己的内容提供器给我们程序的数据提供外部访问接口。

Notification通知栏的使用:

   Notification notification = new Notification.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(NOTIFICATION_ID, notification); //通道号要提前创建

                       参数1:通道号  参数2:notification对象

PendingIntent延迟意图:

   方法1:getActivity()

   方法2:getBroadcast()

   方法3:getService()

以上均为三个参数:参1:Context 。参2:一般不用传0。参数3:意图

参数4:确定行为FLAG_ONESHOT,FLAG_NO_CREATE,FLAG_CANCEL,FLAG_UPDATE_CURRENT通常可以填0.

点击后图标消失:

①在后部分调用.setAutoCancel( true )方法

②在onCreate中

NotificationManager manager = (Notif icat ionManager) getSystemService

(NOTIFICATION_ SERVICE) ; //注册管理器

manager . cancel((NOTIFICATION_ID); . //注册取消。

调用摄像头

  ①创建File对象,用于存储。

  ②调用getExternalCacheDir( )方法获取目录。

  ③做版本适配

  ④用intent去启动摄像头。

注意调用都有权限注册。

播放音频:

一般使用MediaPlayer类实现,常用方法如下

调用播放视频

一般使用VideoView类的方法。

数据存储部分:

 共享参数-SharedPreferences:轻量级存储工具,Key-Value形式。

使用场景:

  ①简单且孤立的数据。

  ②文本形式数据。

  ③需要持久化存储的数据。

  ④App个性化配置信息,用户使用App行为信息。

  ⑤临时片段信息。

 getSharedPreferences("config", Context.MODE_PRIVATE);

①然后先ALT+ENTER声明成变量,再Ctrl+ALT+F变全局

private SharedPreferences preferences;

preferences = getSharedPreferences("config", Context.MODE_PRIVATE);

//在下面监听

public void onClick(View view) {

        String name = et_name.getText().toString();

        String age = et_age.getText().toString();

        String height = et_height.getText().toString();

        String weight = et_weight.getText().toString();

        //获取编辑器

        SharedPreferences.Editor editor = preferences.edit();

        editor.putString("name",name);

        editor.putInt("age", Integer.parseInt(age));

        editor.putFloat("height",Float.parseFloat(height));

        editor.putFloat("weight",Float.parseFloat(weight));

        editor.putBoolean("married",gr_married.isChecked());

        editor.commit();

}

②重新再取数据:(通过键值对取)

        String name= preferences.getString("name","");

SQLite

(1) 数据定义语言

CREATE TABLE IF NOT EXISTS 表名(

字段A PRIMARY KEY

字段B,

字段C

支持类型

NULL:表示空值。

INTEGER:表示整数,可以存储整数值。

REAL:表示浮点数,可以存储浮点数值。

TEXT:表示文本,可以存储字符串。

BLOB:表示二进制数据,可以存储任意二进制数据。

(2)删除表格:

 DROP TABLE IF EXISTS user_info

(3)修改表格:

ALTER TABLE user_info ADD COLUMN phone VARCHAR;

(只支持增加字段,不支持修改,删除字段)添加多列就分多次。

(4)数据操作语言与其他数据库相似

  1. SQLite Database 数据库管理器

  1,管理类:

  OpenDatabase():打开指定路径数据库。

  isOpen():判断数据库是否已经打开。

Close():关闭数据库。

getVersion():获取版本。

SetVersion():设置数据库版本。

  2,事务类:

beginTransaction:开始事物。

SetTransactionSuccessful:设置事务的成功标志.

endTransaction:结束事务。

创建数据库,删除数据库:

①首先在全局生命这个数据库名

private String mDataBaseName;

mDataBaseName = getFilesDir() + "/test.db";

    public void onClick(View view) {

      int id = view.getId();

      if (id == R.id.btn_database_create) {

            //打开数据库,参数1:数据库名地址+名字,参数2:打开模式,参数3:游标

SQLiteDatabase db = openOrCreateDatabase(mDataBaseName, Context.MODE_PRIVATE, null);

            //输出化语言:

String desc = String.format("数据库%s创建%s", db.getPath(), (db != null) ? "成功" : "失败");

            tv_database.setText(desc);}

else if (id == R.id.btn_database_delete) {

            //删除数据库

            boolean result = deleteDatabase(mDataBaseName);

String desc_fail = String.format("数据库%s删除%s", mDataBaseName, result ? "成功" : "失败");

tv_database.setText(desc_fail);   }    }

数据库所在路径:data->data->包名->file

页面与数据库交互SQLiteOpenhelper

两个抽象方法: onCreate ( ), onUpgrade ( )

两个重要实例方法getReadableDatabase( ), getWritableDatabase( )。均可创建或打开数据库。

(6)事务管理:(一致性,原子性)

  beginTransaction:开始事务.

  setTransactionSuccessful:设置事务的成功标志.

endTransaction:结束事务.

若事务失败泽会回滚操作,保证原子性。

  1. 外部存储空间

定义部分

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.File;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.nio.Buffer;

public class FileUtil {

    //把字符串保存到指定路径

    public static void saveText(String path,String txt){

        BufferedWriter os =null;  //创建一个os

        try {os = new BufferedWriter(new FileWriter(path));  //new一个对象,其中包含指定路径

            os.write(txt);                                  //将txt 写入该路径

        }catch (Exception e){

            e.printStackTrace();

        }finally {

            if (os!=null)

            {

                try {

                    os.close();

                }catch (IOException e){

                    e.printStackTrace();

                }

            }

        }

    }

    //从指定路径读取内容字符串

    public static String openText(String path){

        BufferedReader is=null;

        StringBuilder sb =new StringBuilder();

        try {

            is =new BufferedReader(new FileReader(path));

            String line = null;

            while ((line=is.readLine())!=null){

                sb.append(line);

            }

        }catch (Exception e){

            e.printStackTrace();

        }finally {

            if (is!=null)

            {

                try {

                    is.close();

                }catch (IOException e){

                    e.printStackTrace();

                }

            }

        }

        return sb.toString();

    }

}

引用部分:

      //外部存储的私有空间写入

  String directory = null; //创建一个字符串

  String fileName = System.currentTimeMillis()+".txt"; //创建一个当前时间的文件名

  directory = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString(); //获取路径

  path =directory + File.separatorChar+fileName;  //构建完整路径

                FileUtil.saveText(path,sb.toString());          //进行保存

                ToastUtil.show(this,"保存成功");

//外部存储的私有空间读出

tv_txt.setText(FileUtil.openText(path))

外部存储公有空间:还要手机获取权限

directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString();

(7)存储卡上读写图片文件

BitmapFactory工具用于读取各种来源的图片:相关方法如下:

decodeResource:该方法可从资源文件中读取图片信息。

DecodeFile:该方法可将指定路径的图片读取到Bitmap对象。

DecodeStream:该方法从输入流中读取位图数据。

①定义触发保存事件

    public void onClick(View view) {

        int id = view.getId();

        if (id == R.id.btn_save) {

            String fileName = System.currentTimeMillis() + ".jpeg";

            //获取当前App的私有下载目录

            path = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + File.separatorChar + fileName;

            //从指定资源文件获取位图像对象

            Bitmap b1 = BitmapFactory.decodeResource(getResources(), R.drawable.ting1);

            //将位图对象保存下来

            FileUtil.saveImage(path, b1);

            ToastUtil.show(this, "保存成功");

        } else if (id == R.id.btn_read) {

            Bitmap b2 = FileUtil.openImage(path);

            iv_content.setImageBitmap(b2);

         }    }

②对应保存

   //把位图数据保存到指定路径的图片文件

    public static void saveImage(String path, Bitmap b1) {

        FileOutputStream fos = null;

        try{

            fos=new FileOutputStream(path);

            //把位图数据压缩到文件流中

            b1.compress(Bitmap.CompressFormat.JPEG,100,fos);}

        catch (Exception e){ e.printStackTrace(); }finally {

            //关闭输入输出流

            if(fos!=null){

                try {   fos.close();   }catch (IOException e){

                    e.printStackTrace();  }  }   }   }

③读取相应位图

    //从指定路径读取位图数据

    public static Bitmap openImage(String path) {

            Bitmap bitmap=null;

            FileInputStream fis=null;

            try {

                fis =new FileInputStream(path);

                bitmap = BitmapFactory.decodeStream(fis);

            }catch (Exception e){

                e.printStackTrace();

            }finally {

                if (fis!=null){

                    try {

                        fis.close();

                    }catch (IOException e)

                    {

                        e.printStackTrace();

                    }      }     }  return bitmap; }

(8)Application生命周期

  在App运行过程中有且仅有一个Application对象,贯穿生命周期。

public class MyApplication extends Application {

    //在APP启动时调用

    @Override

    public void onCreate() {

        super.onCreate();

        Log.d("ning","onCreate");

    }

    //APP终止(在真实的产品不会回调)

    @Override

    public void onTerminate() {

        super.onTerminate();

        Log.d("ning","onTerminate");

    }

    //配置改变时调用

    @Override

    public void onConfigurationChanged(@NonNull Configuration newConfig) {

        super.onConfigurationChanged(newConfig);

    }

}

  1. Application全局变量

适用于会频繁读取的信息,如用户名,手机号。

不方便由意图传输的数据,例如位图对象,非字符串类型。

容易因频繁分配内存导致的内存泄漏的对象,Handler等。可以采用单例模式。

操作:

  • private static MyApplication mApp;  //定义一个私有静态的实例MyApplication名为app
  • public static MyApplication getInstance(){   return mApp; }//获取单例,返回mApp
  • public void onCreate() {

super.onCreate();   mApp = this; }//在oncreate里实例化,将this指针地址给mApp

④在外部再调用MyApplication.getInstance();

  1. JetPackRoom:

Room框架通过注解技术简化数据库操作

在build.gradle的dependencies中配置    

implementation 'androidx.room:room-runtime:2.2.5'// 导入 Room 依赖库

annotationProcessor 'androidx.room:room-compiler:2.2.5'// 导入注解处理器 ( Java )

编写一个表对应的实体类Bookinfo

package com.example.myapplication.enity;

import androidx.room.Entity;

import androidx.room.PrimaryKey;

@Entity

public class Bookinfo {

    @PrimaryKey(autoGenerate = true) //自动增长

    private int id;

    private String name;

    private String author;

    private String press;

    private  double price;

    public int getId() {

        return id;

    }

    public void setId(int id) {

        this.id = id;

    }

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public String getAuthor() {

        return author;

    }

    public void setAuthor(String author) {

        this.author = author;

    }

    public String getPress() {

        return press;

    }

    public void setPress(String press) {

        this.press = press;

    }

    public double getPrice() {

        return price;

    }

    public void setPrice(double price) {

        this.price = price;

    }

    @Override

    public String toString() {

        return "Bookinfo{" +

                "id=" + id +

                ", name='" + name + '\'' +

                ", author='" + author + '\'' +

                ", press='" + press + '\'' +

                ", price=" + price +

                '}';

    }

}

③编写一个表对应的持久化类BookDao的接口。会自动生产类。

package com.example.myapplication.dao;

import androidx.room.Dao;

import androidx.room.Delete;

import androidx.room.Insert;

import androidx.room.Query;

import androidx.room.Update;

import com.example.myapplication.enity.Bookinfo;

import java.util.List;

@Dao

public interface BookDao {

    @Insert

    void insert(Bookinfo... book);

    @Delete

    void delete(Bookinfo... book);

    @Query("DELETE FROM Bookinfo")

    void deleteAll();

    @Update

    int update(Bookinfo... book);

    @Query("SELECT * FROM bookinfo ")

    List<Bookinfo>queryAll();

    @Query("SELECT * FROM bookinfo WHERE name = :name ORDER BY id DESC limit 1")

    Bookinfo queryByName(String name);

}

④创建一个抽象类:BookDatabase

@Database(entities = {Bookinfo.class},version = 1,exportSchema = true)

public abstract class BookDatabase extends RoomDatabase {

    //获取该数据库中某张表的持久化对象

public abstract BookDao bookDao();   }

⑤在自定义的Application类中声明书籍数据库的唯一实例。

  public class RoomWriteActivity extends AppCompatActivity implements View.OnClickListener {

    private EditText shuming;

    private EditText zuozhe;

    private EditText chubanshe;

    private EditText jiage;

private BookDatabase bookDB;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_room_write);

        shuming = findViewById(R.id.shuming);

        zuozhe = findViewById(R.id.zuozhe);

        chubanshe = findViewById(R.id.chubanshe);

        jiage = findViewById(R.id.jiage);

        findViewById(R.id.btn_chaxun).setOnClickListener(this);

        findViewById(R.id.btn_shanchu).setOnClickListener(this);

        findViewById(R.id.btn_tianjia).setOnClickListener(this);

        findViewById(R.id.btn_xiugai).setOnClickListener(this);

        //从App实例中获取唯一的书籍持续化对象

        bookDB = MyApplication.getInstance().getBookDB();

    }

    @Override

    public void onClick(View view) {

        String  name=shuming.getText().toString();

        String  author=zuozhe.getText().toString();

        String  press=chubanshe.getText().toString();

        String  price=jiage.getText().toString();

        int id = view.getId();

        if (id == R.id.btn_tianjia) {

            Bookinfo b1 = new Bookinfo();

            b1.setName(name);

            b1.setAuthor(author);

            b1.setPress(press);

            b1.setPrice(Double.parseDouble(price));

            bookDao.insert(b1);

        } else if (id == R.id.btn_xiugai) {

            List<Bookinfo> list= bookDao.queryAll();

            for(Bookinfo b:list){

                Log.d("ning",b.toString());

            }

        } else if (id == R.id.btn_shanchu) {

        } else if (id == R.id.btn_chaxun) {

        }

    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/213686.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【华为数通HCIP | 网络工程师】821-IGP高频题、易错题之OSPF(4)

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

抖去推短视频矩阵系统saas源头技术开发搭建

四大核心功能同开&#xff1a; 一、剪辑技术开发 智能剪辑&#xff1a; 6种不同的剪辑方式&#xff0c;独家源头技术开发&#xff0c;目前剪辑完全是自己的核心技术数学建模自己开发&#xff0c;核心优势视频剪辑生成提速比较快&#xff0c;后台写了两套自动滤重算法&#xf…

如何用python画一个圣诞树

前言 距离圣诞节还有一个月啦。今天&#xff0c;我们给大家画一个圣诞树&#xff0c;我们一起来看看效果吧。 效果展示 我们先来看看最终的效果看看我们画的圣诞树怎么样吧。如果&#xff0c;感觉不错&#xff0c;我们一起来实现吧。 功能实现 功能模块 我们先看看&#x…

文旅虚拟人IP:数字时代的传统文化推荐官

近几年&#xff0c;随着文旅虚拟人频“上岗”&#xff0c;虚拟人逐渐成为了文旅品牌的一种新颖的传统文化传播思路。 文旅品牌定制化推出虚拟人&#xff0c;本质原因是2023旅游业全面复苏&#xff0c;各文旅玩法同质化现象严重&#xff0c;在这样的境遇下&#xff0c;文旅品牌开…

网络安全如何自学?

1.网络安全是什么 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高&#xff1b; 二、则是发展相对成熟…

内网穿透的应用-如何在本地安装Flask,以及将其web界面发布到公网上并进行远程访问

轻量级web开发框架&#xff1a;Flask本地部署及实现公网访问界面 文章目录 轻量级web开发框架&#xff1a;Flask本地部署及实现公网访问界面前言1. 安装部署Flask2. 安装Cpolar内网穿透3. 配置Flask的web界面公网访问地址4. 公网远程访问Flask的web界面 前言 本篇文章讲解如何…

短剧付费变现小程序源码系统+开通会员+在线充值 附带完整的搭建教程

大家好啊&#xff0c;今天小编来给大家分享一款短剧付费变现小程序源码系统。近年来&#xff0c;随着互联网技术的飞速发展&#xff0c;短剧成为了一个备受瞩目的领域。短剧以其简洁、紧凑的故事情节和制作周期短、传播速度快的特点&#xff0c;成为了越来越多人的选择。然而&a…

周转箱与工具柜的智能化应用

在当今制造业激烈竞争的市场中&#xff0c;6S管理方法作为提高企业竞争力的有力工具&#xff0c;与精益生产中的周转箱和工具柜相结合&#xff0c;将为企业带来更大的优势。通过实施6S管理方法&#xff0c;企业不仅能够提高生产效率、降低成本&#xff0c;还能够改善产品质量、…

云计算时代来临,传统运维怎样做才能不被“杀死”?

据Forrester Research的数据显示&#xff0c;2021年全球公有云基础设施市场将增长35%&#xff0c;达到1200亿美元&#xff0c;云计算将继续在疫情复苏的过程中“占据中心位置”。 全球用于云计算的IT支出占比将持续增长&#xff0c;企业对于云计算开发人才需求紧迫&#xff0c…

【力扣:421,2935】数组内最大异或对问题

思路&#xff1a;从最高位向低位构造&#xff0c;对每一位利用哈希表寻找是否存在可使此位为1的数 第一轮找1&#xff1a;清空哈希表&#xff0c;1&#xff0c;2存1&#xff0c;到3发现1^01&#xff0c;res|1<<3 第二轮找11&#xff1a;清空哈希表&#xff0c;1存10&…

水果编曲软件FL Studio21.2下载安装教程

简称FL&#xff0c;全称&#xff1a;Fruity Loops Studio&#xff0c;因此国人习惯叫它"水果"。目前最新版本(包括测试版本)是FL Studio21.2&#xff0c;它让你的计算机就像是全功能的录音室&#xff0c;大混音盘&#xff0c;非常先进的制作工具&#xff0c;让你的音…

【ChatGLM3-6B】Docker下部署及微调

【ChatGLM2-6B】小白入门及Docker下部署 注意&#xff1a;Docker基于镜像中网盘上上传的有已经做好的镜像&#xff0c;想要便捷使用的可以直接从Docker基于镜像安装看Docker从0安装前提下载启动访问 Docker基于镜像安装容器打包操作&#xff08;生成镜像时使用的命令&#xff0…