20189230楊 2018-2019-2 《移動平臺開發實踐》第12周學習總結

學習《Java和Android開發學習指南(第二版)》第4七、4八、4九、50章——

第47章服務
服務(service)是一種Android組件。服務沒有用戶界面,而且在後臺運行。它適用於長時間運行的操做。
47.1概覽
1.服務和在其中聲明服務的應用程序在相同的進程上運行,而且在應用程序的主線程上運行。
2.服務能夠採起兩種形式之一,它能夠是啓動的或綁定的。
若是一個組件啓動了服務,它就是啓動的。即使啓動服務的組件已經再也不接受服務或者被銷燬了,該服務還能夠在後臺無限期地運行。
若是應用程序組件綁定到服務,該服務就是綁定的。綁定的服務就像是客戶端-服務器關係中的一臺服務器,接受來自其餘應用程序組件的請求,而且返回結果。
3.術語可訪問性(accessibility),表示一個服務能夠是私有的或公有的。公有的服務器能夠由任何的應用程序調用,私有的服務器只可以由服務聲明所在的相同的應用程序之中的組件來訪問。
47.3聲明服務
1.服務必須在清單中的 之下使用service元素來聲明。
47.4服務示例
1.這個示例是一個Android應用程序,它容許你下載Web頁面並將其離線存儲,以便在不能鏈接到互聯網的時候能夠瀏覽它。這裏有兩個活動和一個服務。
2.代碼清單47.1清單
java

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.urlservice" >

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:name=".ViewActivity"
            android:parentActivityName=".MainActivity"
            android:label="@string/title_activity_view" >
        </activity>

        <service
            android:name=".URLService"
            android:exported="true" />

    </application>

</manifest>

3.代碼清單47.2主活動類android

package com.example.urlservice;

import android.content.Intent;
import android.os.Bundle;
import android.os.StrictMode;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.app.Activity;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        StrictMode.ThreadPolicy policy = new
                StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_view) {
            Intent intent = new Intent(this, ViewActivity.class);
            startActivity(intent);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    public void fetchWebPages(View view) {
        EditText editText = (EditText) findViewById(R.id.urlsEditText);
        Intent intent = new Intent(this, URLService.class);
        intent.putExtra("urls", editText.getText().toString());
        startService(intent);
    }
}

4.代碼清單47.3視圖活動類git

package com.example.urlservice;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.webkit.WebView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class ViewActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_view);
        Spinner spinner = (Spinner) findViewById(R.id.spinner);
        File saveDir = getFilesDir();

        if (saveDir.exists()) {
            File dir = new File(saveDir, "URLService");
            dir = saveDir;
            if (dir.exists()) {
                String[] files = dir.list();
                ArrayAdapter<String> dataAdapter =
                        new ArrayAdapter<String>(this,
                        android.R.layout.simple_spinner_item, files);
                dataAdapter.setDropDownViewResource(
                        android.R.layout.simple_spinner_dropdown_item);
                spinner.setAdapter(dataAdapter);
                spinner.setOnItemSelectedListener(
                        new AdapterView.OnItemSelectedListener() {
                    @Override
                    public void onItemSelected(AdapterView<?>
                                adapterView, View view, int pos, long id) {
                        //open file
                        Object itemAtPosition = adapterView
                                .getItemAtPosition(pos);
                        File file = new File(getFilesDir(),
                                itemAtPosition.toString());
                        FileReader fileReader = null;
                        BufferedReader bufferedReader = null;
                        try {
                            fileReader = new FileReader(file);
                            bufferedReader =
                                    new BufferedReader(fileReader);
                            StringBuilder sb = new StringBuilder();
                            String line = bufferedReader.readLine();
                            while (line != null) {
                                sb.append(line);
                                line = bufferedReader.readLine();
                            }
                            WebView webView = (WebView)
                                    findViewById(R.id.webview);
                            webView.loadData(sb.toString(),
                                    "text/html", "utf-8");
                        } catch (FileNotFoundException e) {
                        } catch (IOException e) {
                        }
                    }

                    @Override
                    public void onNothingSelected(AdapterView<?>
                            adapterView) {
                    }
                });
            }
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_view, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        return super.onOptionsItemSelected(item);
    }
}

5.代碼清單47.4服務類web

package com.example.urlservice;

import android.app.IntentService;
import android.content.Intent;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.StringTokenizer;

public class URLService extends IntentService {
    public URLService() {
        super("URLService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        String urls = intent.getStringExtra("urls");
        if (urls == null) {
            return;
        }
        StringTokenizer tokenizer = new StringTokenizer(urls);
        int tokenCount = tokenizer.countTokens();
        int index = 0;
        String[] targets = new String[tokenCount];
        while (tokenizer.hasMoreTokens()) {
            targets[index++] = tokenizer.nextToken();
        }
        File saveDir = getFilesDir();
        fetchPagesAndSave(saveDir, targets);
    }

    private void fetchPagesAndSave(File saveDir, String[] targets) {
        for (String target : targets) {
            URL url = null;
            try {
                url = new URL(target);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
            String fileName = target.replaceAll("/", "-")
                    .replaceAll(":", "-");

            File file = new File(saveDir, fileName);
            PrintWriter writer = null;
            BufferedReader reader = null;
            try {
                writer = new PrintWriter(file);
                reader = new BufferedReader(
                        new InputStreamReader(url.openStream()));
                String line;
                while ((line = reader.readLine()) != null) {
                    writer.write(line);
                }
            } catch (Exception e) {
            } finally {
                if (writer != null) {
                    try {
                        writer.close();
                    } catch (Exception e) {
                    }
                }
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (Exception e) {
                    }
                }
            }
        }
    }
}


47.5本章小結
服務是一個在後臺運行的應用程序組件。儘管服務器是在後臺運行的,但它並非一個進程,不會在一個單獨線程上運行。相反,服務和調用該服務的應用程序的主線程上運行。
能夠經過擴展android.app.Service或android.app.IntentService類來編寫一個程序。sql

第48章廣播接收器
Android系統老是會將在操做系統和應用程序運行期間發生的意圖進行廣播。此外,應用程序也能夠廣播用戶定義的意圖,能夠經過在應用程序中編寫廣播接收器來利用這些廣播。
48.1概覽
廣播接收器是一個應用程序組件,它監聽一個特定意圖廣播,相似於監聽事件的Java監聽器。
48.2基於時鐘的廣播接收器
1.代碼清單48.1MainActivity類數據庫

package com.example.broadcastreceiverdemo1;

import java.util.Calendar;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity {

    BroadcastReceiver receiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public void onResume() {
        super.onResume();
        setTime();
        receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                setTime();
            }
        };
        IntentFilter intentFilter = new IntentFilter(
                Intent.ACTION_TIME_TICK);
        this.registerReceiver(receiver, intentFilter);
    }

    public void onPause() {
        this.unregisterReceiver(receiver);
        super.onPause();
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    private void setTime() {
        Calendar calendar = Calendar.getInstance();
        CharSequence newTime = DateFormat.format(
                "kk:mm", calendar);
        TextView textView = (TextView) findViewById(
                R.id.textView1);
        textView.setText(newTime);
    }
}


48.3取消通知
1.代碼清單48.2主活動的佈局文件編程

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="setNotification"
        android:text="Set Notification" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="clearNotification"
        android:text="Clear Notification" />
</LinearLayout>

2.代碼清單48.3MainActivity類android-studio

package com.example.cancelnotificationdemo;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;


public class MainActivity extends Activity {
    private static final String CANCEL_NOTIFICATION_ACTION
            = "cancel_notification";
    int notificationId = 1002;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        BroadcastReceiver receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                NotificationManager notificationManager =
                        (NotificationManager) getSystemService(
                                NOTIFICATION_SERVICE);
                notificationManager.cancel(notificationId);
            }
        };
        IntentFilter filter = new IntentFilter();
        filter.addAction(CANCEL_NOTIFICATION_ACTION);
        this.registerReceiver(receiver, filter);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }


    public void setNotification(View view) {
        Intent cancelIntent = new Intent("cancel_notification");
        PendingIntent cancelPendingIntent =
                PendingIntent.getBroadcast(this, 100,
                        cancelIntent, 0);

        Notification notification  = new Notification.Builder(this)
                .setContentTitle("Stop Press")
                .setContentText(
                        "Everyone gets extra vacation week!")
                .setSmallIcon(android.R.drawable.star_on)
                .setAutoCancel(true)
                .addAction(android.R.drawable.btn_dialog,
                        "Dismiss", cancelPendingIntent)
                .build();

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(
                        NOTIFICATION_SERVICE);
        notificationManager.notify(notificationId, notification);
    }

    public void clearNotification(View view) {
        NotificationManager notificationManager =
                (NotificationManager) getSystemService(
                        NOTIFICATION_SERVICE);
        notificationManager.cancel(notificationId);
    }
}


48.4本章小結
廣播接收器是監聽意圖廣播的一個應用程序組件。要建立一個接收器,必須建立一個類來擴展android.content.BroadcastReceiver並實現其onReceive方法。要建立一個接收器,能夠在應用程序的清單文件中添加一個receiver元素,或者經過調用Context.registerReceiver()編程來作到這一點。在任何狀況下,都必須定義一個IntentFilter,它指定了哪一個意圖致使該接收器被觸發。服務器

第49章鬧鐘服務
49.2示例
1.代碼清單49.1清單

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.alarmmanagerdemo1" >

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category
                    android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

        <activity
            android:name=".WakeUpActivity"
            android:label="@string/title_activity_wake_up" >
        </activity>

    </application>

</manifest>

2.代碼清單49.2主活動的佈局文件

<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"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="5 Minute Alarm"
        android:id="@+id/button"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginTop="77dp"
        android:onClick="setAlarm"/>

</RelativeLayout>

3.代碼清單49.3 MainActivity類

package com.example.alarmmanagerdemo1;

import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;

import java.util.Calendar;
import java.util.Date;


public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    public void setAlarm(View view) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MINUTE, 5);
        Date fiveMinutesLater = calendar.getTime();
        Toast.makeText(this, "The alarm will set off at " +
                fiveMinutesLater, Toast.LENGTH_LONG).show();
        AlarmManager alarmMgr = (AlarmManager) getSystemService(
                Context.ALARM_SERVICE);
        Intent intent = new Intent(this, WakeUpActivity.class);
        PendingIntent sender = PendingIntent.getActivity(
                this, 0, intent, 0);
        alarmMgr.set(AlarmManager.RTC_WAKEUP,
                fiveMinutesLater.getTime(), sender);
    }
}

4.代碼清單49.4WakeUpActivity類

package com.example.alarmmanagerdemo1;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;


public class WakeUpActivity extends Activity {
    private final int NOTIFICATION_ID = 1004;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final Window window = getWindow();
        Log.d("wakeup", "called. oncreate");
        window.addFlags(
                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
        setContentView(R.layout.activity_wake_up);
        addNotification();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_wake_up, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    public void dismiss(View view) {
        NotificationManager notificationMgr = (NotificationManager)
                getSystemService(NOTIFICATION_SERVICE);
        notificationMgr.cancel(NOTIFICATION_ID);
        this.finish();
    }

    private void addNotification() {
        NotificationManager notificationMgr = (NotificationManager)
                getSystemService(NOTIFICATION_SERVICE);
        Notification notification  = new Notification.Builder(this)
                .setContentTitle("Wake up")
                .setSmallIcon(android.R.drawable.star_on)
                .setAutoCancel(false)
                .build();
        notification.defaults|= Notification.DEFAULT_SOUND;
        notification.defaults|= Notification.DEFAULT_LIGHTS;
        notification.defaults|= Notification.DEFAULT_VIBRATE;
        notification.flags |= Notification.FLAG_INSISTENT;
        notification.flags |= Notification.FLAG_AUTO_CANCEL;
        notificationMgr.notify(NOTIFICATION_ID, notification);
    }
}


49.3本章小結
鬧鐘服務是Android開發者所可以使用的一項內建的服務。使用它,能夠在隨後調度一個操做。能夠經過編程執行該操做,執行一次或重複地執行。

第50章內容提供者
內容提供者是用來封裝要和其餘應用程序共享的數據的一個Android組件。
50.1概覽
1.要建立一個內容提供者,你須要擴展android.content.ContentProvider類,這個類提供CRUD方法,也就是用於建立、訪問、更新和刪除數據的方法。
2.內容提供者中的數據,經過一個獨特的URI來引用。內容提供者的消費者,必須知道這個URL,纔可以訪問內容提供者的數據。
50.2ContentProvider類
50.2.1query方法(訪問底層的數據)
50.2.2insert方法(添加一個數據項)
50.2.3update方法(能夠使用u方法來更新一個數據項或一組數據項)
50.2.4delete方法(刪除一個數據項或一組數據項)
50.3 建立一個內容提供者
1.代碼清單50.1ContentProviderDemo1的清單

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.contentproviderdemo1" >

    <permission
        android:name="com.example.permission.READ_ELECTRIC_CARS"
        android:protectionLevel="normal"/>
    <permission
        android:name="com.example.permission.WRITE_ELECTRIC_CARS"
        android:protectionLevel="normal"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".activity.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".activity.AddElectricCarActivity"
            android:parentActivityName=".activity.MainActivity"
            android:label="@string/app_name" >
        </activity>
        <activity
            android:name=".activity.ShowElectricCarActivity"
            android:parentActivityName=".activity.MainActivity"
            android:label="@string/app_name" >
        </activity>

        <provider
            android:name=".provider.ElectricCarContentProvider"
            android:authorities="com.example.contentproviderdemo1"
            android:enabled="true"
            android:exported="true"
            android:readPermission="com.example.permission.READ_ELECTRIC_CARS"
            android:writePermission="com.example.permission.WRITE_ELECTRIC_CARS">
        </provider>
    </application>

</manifest>

2.代碼清單50.2 內容提供者

package com.example.contentproviderdemo1.provider;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;

public class ElectricCarContentProvider extends ContentProvider {

    public static final Uri CONTENT_URI =
            Uri.parse("content://com.example.contentproviderdemo1"
                    + "/electric_cars");

    public ElectricCarContentProvider() {
    }

    @Override
    public int delete(Uri uri, String selection,
                      String[] selectionArgs) {
        String id = uri.getPathSegments().get(1);
        return dbMgr.deleteElectricCar(id);
    }

    @Override
    public String getType(Uri uri) {
        throw new UnsupportedOperationException("Not implemented");
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        long id = getDatabaseManager().addElectricCar(values);
        return ContentUris.withAppendedId(CONTENT_URI, id);
    }

    @Override
    public boolean onCreate() {
        // initialize content provider on startup
        // for this example, nothing to do
        return true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection,
                        String selection,
                        String[] selectionArgs,
                        String sortOrder) {
        if (uri.equals(CONTENT_URI)) {
            return getDatabaseManager()
                    .getElectricCarsCursor(projection, selection,
                            selectionArgs, sortOrder);
        } else {
            return null;
        }
    }

    @Override
    public int update(Uri uri, ContentValues values,
                      String selection,
                      String[] selectionArgs) {
        String id = uri.getPathSegments().get(1);
        Log.d("provider", "update in CP. uri:"  + uri);
        DatabaseManager databaseManager = getDatabaseManager();
        String make = values.getAsString("make");
        String model = values.getAsString("model");
        return databaseManager.updateElectricCar(id, make, model);
    }

    private DatabaseManager dbMgr;
    private DatabaseManager getDatabaseManager() {
        if (dbMgr == null) {
            dbMgr = new DatabaseManager(getContext());
        }
        return dbMgr;
    }

3.代碼清單50.3 數據庫管理器

package com.example.contentproviderdemo1.provider;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class DatabaseManager extends SQLiteOpenHelper {
    public static final String TABLE_NAME = "electric_cars";
    public static final String ID_FIELD = "_id";
    public static final String MAKE_FIELD = "make";
    public static final String MODEL_FIELD = "model";
    public DatabaseManager(Context context) {
        super(context,
                /*db name=*/ "vehicles_db",
                /*cursorFactory=*/ null,
                /*db version=*/1);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        String sql = "CREATE TABLE " + TABLE_NAME
                + " (" + ID_FIELD + " INTEGER, "
                + MAKE_FIELD + " TEXT,"
                + MODEL_FIELD + " TEXT,"
                + " PRIMARY KEY (" + ID_FIELD + "));";
        db.execSQL(sql);

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int arg1,
                int arg2) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        // re-create the table
        onCreate(db);
    }

    public long addElectricCar(ContentValues values) {
        Log.d("db", "addElectricCar");
        SQLiteDatabase db = this.getWritableDatabase();
        return db.insert(TABLE_NAME, null, values);
    }

    // Obtains single ElectricCar
    ContentValues getElectricCar(long id) {
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.query(TABLE_NAME, new String[] {
                        ID_FIELD, MAKE_FIELD, MODEL_FIELD},
                        ID_FIELD + "=?",
                new String[] { String.valueOf(id) }, null,
                null, null, null);
        if (cursor != null) {
            cursor.moveToFirst();
            ContentValues values = new ContentValues();
            values.put("id", cursor.getLong(0));
            values.put("make", cursor.getString(1));
            values.put("model", cursor.getString(2));
            return values;
        }
        return null;
    }

    public Cursor getElectricCarsCursor(String[] projection,
            String selection,
            String[] selectionArgs, String sortOrder) {
        SQLiteDatabase db = this.getReadableDatabase();
        Log.d("provider:" , "projection:" +  projection);
        Log.d("provider:" , "selection:" +  selection);
        Log.d("provider:" , "selArgs:" +  selectionArgs);
        return db.query(TABLE_NAME, projection,
                selection,
                selectionArgs,
                sortOrder,
                null, null, null);
    }

    public int updateElectricCar(String id, String make,
            String model) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(MAKE_FIELD, make);
        values.put(MODEL_FIELD, model);
        return db.update(TABLE_NAME, values, ID_FIELD + " = ?",
                new String[] { id });
    }

    public int deleteElectricCar(String id) {
        SQLiteDatabase db = this.getWritableDatabase();
        return db.delete(TABLE_NAME, ID_FIELD + " = ?",
                new String[] { id });
    }
}

4.代碼清單50.4 Util類

package com.example.contentproviderdemo1;

import android.net.Uri;
public class Util {
    public static final Uri CONTENT_URI =
            Uri.parse("content://com.example.contentproviderdemo1" +
                    "/electric_cars");
    public static final String ID_FIELD = "_id";
    public static final String MAKE_FIELD = "make";
    public static final String MODEL_FIELD = "model";

}

5.代碼清單50.5 MainActivity類

package com.example.contentproviderdemo1.activity;

import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.CursorAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import com.example.contentproviderdemo1.R;
import com.example.contentproviderdemo1.Util;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ListView listView = (ListView) findViewById(
                R.id.listView);
        Cursor cursor = getContentResolver().query(
                Util.CONTENT_URI,
                /*projection=*/ new String[] {
                        Util.ID_FIELD, Util.MAKE_FIELD,
                        Util.MODEL_FIELD},
                /*selection=*/ null,
                /*selectionArgs=*/ null,
                /*sortOrder=*/ "make");
        startManagingCursor(cursor);
        ListAdapter adapter = new SimpleCursorAdapter(
                this,
                android.R.layout.two_line_list_item,
                cursor,
                new String[] {Util.MAKE_FIELD,
                        Util.MODEL_FIELD},
                new int[] {android.R.id.text1, android.R.id.text2},
                CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);

        listView.setAdapter(adapter);
        listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        listView.setOnItemClickListener(
                new OnItemClickListener() {
                    @Override
                    public void onItemClick(
                            AdapterView<?> adapterView,
                            View view, int position, long id) {
                        Intent intent = new Intent(
                                getApplicationContext(),
                                ShowElectricCarActivity.class);
                        intent.putExtra("id", id);
                        startActivity(intent);
                    }
                });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_add:
                startActivity(new Intent(this,
                        AddElectricCarActivity.class));
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
}

6.代碼清單50.6 AddElectricCarActivity類

package com.example.contentproviderdemo1.activity;
import android.app.Activity;
import android.content.ContentValues;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;

import com.example.contentproviderdemo1.provider.ElectricCarContentProvider;
import com.example.contentproviderdemo1.R;

public class AddElectricCarActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_electric_car);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.add_electric_car, menu);
        return true;
    }

    public void cancel(View view) {
        finish();
    }

    public void addElectricCar(View view) {
        String make = ((EditText) findViewById(
                R.id.make)).getText().toString();
        String model = ((EditText) findViewById(
                R.id.model)).getText().toString();
        ContentValues values = new ContentValues();
        values.put("make", make);
        values.put("model", model);
        getContentResolver().insert(
                ElectricCarContentProvider.CONTENT_URI, values);
        finish();
    }
}

7.代碼清單50.7 ShowElectricCarActivity類

package com.example.contentproviderdemo1.activity;
import android.app.Activity;
import android.content.ContentValues;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;

import com.example.contentproviderdemo1.provider.ElectricCarContentProvider;
import com.example.contentproviderdemo1.R;

public class AddElectricCarActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_electric_car);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.add_electric_car, menu);
        return true;
    }

    public void cancel(View view) {
        finish();
    }

    public void addElectricCar(View view) {
        String make = ((EditText) findViewById(
                R.id.make)).getText().toString();
        String model = ((EditText) findViewById(
                R.id.model)).getText().toString();
        ContentValues values = new ContentValues();
        values.put("make", make);
        values.put("model", model);
        getContentResolver().insert(
                ElectricCarContentProvider.CONTENT_URI, values);
        finish();
    }
}


50.4消費內容提供者
ContentResolveDemo1項目展現瞭如何從不一樣的應用程序訪問一個內容提供者,從同一程序和從一個外部應用程序訪問一個內容提供者惟一的區別在於,必須在外部應用程序的清單中,請求訪問提供者的許可。
1.代碼清單50.8ContentResolveDemo1的清單

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.contentresolverdemo1" >

    <uses-permission android:name="com.example.permission.READ_ELECTRIC_CARS"/>
    <uses-permission android:name="com.example.permission.WRITE_ELECTRIC_CARS"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.contentresolverdemo1.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest

教材學習中的問題和解決過程(^▽^)

  • 問題1:什麼是CRUD? CRUD的操做?
  • 問題解決方案1:
    CRUD是指在作計算處理時的增長(Create)、讀取查詢(Retrieve)、更新(Update)和刪除(Delete)幾個單詞的首字母簡寫。主要被用在描述軟件系統中DataBase或者持久層的基本操做功能。

[代碼託管]

https://gitee.com/EvelynYang/twelfth_weeks

statistics.sh腳本運行結果的截圖

在新建的AndroidProjects文件夾中運行腳本,第六週及以前都是在IdeaProjects文件夾裏運行。

學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積) 重要成長
目標 5000行 30篇 400小時
第一週 200/200 2/2 20/20
第二週 300/500 1/3 18/38
第三週 500/1000 1/4 38/76
第四周 1000/2000 1/5 20/96
第五週 1000/3000 1/6 25/121
第六週 1000/4000 1/7 25/146
第七週 1000/5000 1/8 25/171
第八週 1000/6000 1/9 15/186
第九周 1000/7000 1/10 20/206
第十週 1000/8000 1/11 20/226
第十一週 1000/9000 1/12 10/236
第十二週 1000/10000 1/13 15/251

參考資料

相關文章
相關標籤/搜索