Android 4.4 以上添加系统信息数据

在Android4.4之前的版本,往短信箱插入信息很方便,所以这个对用户来说很有威胁的漏洞,在Android4.4得到了修复。Android4.4中只有手机默认的消息App才能处理和短信相关的操作,而手机默认的消息App一般就是手机里自带的官方App,当然用户可以在设置里面,手动地将自己信任的消息App设置为默认App,总的来说,短信的操作控制权掌握到用户自己的手中。


让你的应用成为默认短信

在Android 4.4上,只有一个应用能接收到新增的SMS_DELIVER_ACTION intent,这个intent是当系统接收到新短信时用来发送广播的。哪个应用接收这个广播取决于用户在系统设置里选择了哪个应用作为默认短信应用。同样的,也只有默认的短信应用能在系统接收到新彩信的时候接收到Android 4.4新增加的WAP_PUSH_DELIVER_ACTION intent。
defaultSmsApp.png

其他只想读取新信息的应用可以接收SMS_RECEIVED_ACTION广播,这个广播也是系统接收到新短信时发送的。但是只有接收到SMS_DELIVER_ACTION的应用(用户指定的默认短信应用)可以写入由android.provider.Telephony类和子类定义的SMS Provider。因此,尽快升级你的短信应用让它可以成为默认短信应用是很重要的,因为就算你现有的应用不会在Android 4.4的设备上crash,但它尝试写入SMS Provider的时候会在没有提示的情况下失败。

为了让你的应用在系统设置中作为一个可选的默认短信应用,你的manifest文件必须声明一些特定的内容。所以你必须为你的应用更新以下内容:

  • 在一个broadcast receiver中包含一个SMS_DELIVER_ACTION("android.provider.Telephony.SMS_DELIVER")的intent filter。这个broadcast receiver同样需要BROADCAST_SMS权限。

    这让你的应用可以直接接收到进来的短信。

  • 在一个broadcast receiver包含一个WAP_PUSH_DELIVER_ACTION("android.provider.Telephony.WAP_PUSH_DELIVER")的intent filter,MIME类型是"application/vnd.wap.mms-message"。这个broadcast receiver同样需要BROADCAST_WAP_PUSH权限。

    这让你的应用可以直接接收到进来的彩信。

  • 在你用来发送新信息的activity中包含一个ACTION_SENDTO("android.intent.action.SENDTO")的intent filter,schemas为sms:, smsto:, mms:, 和mmsto:。

    这让你的应用可以接收到其他想发送信息的应用请求的intent。

  • 在一个service里面包含一个ACTION_RESPONSE_VIA_MESSAGE("android.intent.action.RESPOND_VIA_MESSAGE")的intent filter,schemas是sms:, smsto:, mms:, 和 mmsto:。这个service同样需要SEND_RESPOND_VIA_MESSAGE权限。

    这让用户在来电的时候用你的应用进行即时的短信息回复。

例: Demo工程

manifest文件

<pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="tina.messagebox" >

    <!-- Adding -->
    <uses-permission android:name="android.permission.WRITE_SMS" />
    <uses-permission android:name="android.permission.READ_SMS" />

    <!-- End Adding -->
    <application
        android:allowBackup="true"
        android:icon="@mipmap/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" />

                <!-- Adding -->
                <action android:name="android.intent.action.SEND" />
                <action android:name="android.intent.action.SENDTO" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data android:scheme="sms" />
                <data android:scheme="smsto" />
                <data android:scheme="mms" />
                <data android:scheme="mmsto" />
                <!-- End Adding -->

            </intent-filter>
        </activity>

        <!-- Adding -->
        <!-- BroadcastReceiver that listens for incoming SMS messages -->
        <receiver
            android:name=".SmsReceiver"
            android:permission="android.permission.BROADCAST_SMS" >
            <intent-filter>
                <action android:name="android.provider.Telephony.SMS_DELIVER" />
            </intent-filter>
        </receiver>

        <!-- BroadcastReceiver that listens for incoming MMS messages -->
        <receiver
            android:name=".MmsReceiver"
            android:permission="android.permission.BROADCAST_WAP_PUSH" >
            <intent-filter>
                <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />

                <data android:mimeType="application/vnd.wap.mms-message" />
            </intent-filter>
        </receiver>

        <!-- Service that delivers messages from the phone "quick response" -->
        <service
            android:name=".SmsSendService"
            android:exported="true"
            android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE" >
            <intent-filter>
                <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />

                <category android:name="android.intent.category.DEFAULT" />

                <data android:scheme="sms" />
                <data android:scheme="smsto" />
                <data android:scheme="mms" />
                <data android:scheme="mmsto" />
            </intent-filter>
        </service>
        <!-- End Adding -->
    </application>

</manifest>


 

MainActivity.java

package tina.messagebox;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.provider.Telephony;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.text.method.MovementMethod;
import android.text.method.ScrollingMovementMethod;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.text.SimpleDateFormat;
import java.util.Date;


public class MainActivity extends ActionBarActivity {
    private String defaultSmsPkg;
    private String mySmsPkg;
    private TextView mMessageView=null;
    private EditText mPhoneNumber=null;
    private EditText mMsg=null;

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

        mPhoneNumber=(EditText)findViewById(R.id.editText);
        mMsg=(EditText)findViewById(R.id.editText2);
        mMessageView=(TextView)findViewById(R.id.textView3);
        mMessageView.setMovementMethod(ScrollingMovementMethod.getInstance()); //设置滚动
        defaultSmsPkg= Telephony.Sms.getDefaultSmsPackage(this);
        mySmsPkg= this.getPackageName();

        if(!defaultSmsPkg.equals(mySmsPkg)){
//            如果这个App不是默认的Sms App,则修改成默认的SMS APP
//            因为从Android 4.4开始,只有默认的SMS APP才能对SMS数据库进行处理
            Intent intent=new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
            intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME,mySmsPkg);
            startActivity(intent);
        }

        Button button=(Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mySmsPkg.equals(Telephony.Sms.getDefaultSmsPackage(MainActivity.this))){
                    if(mPhoneNumber.getText().toString().isEmpty()){
                        Toast.makeText(MainActivity.this,"Phone number cannot be empty!",Toast.LENGTH_LONG).show();
                        return;
                    }
                    if(mMsg.getText().toString().isEmpty()){
                        Toast.makeText(MainActivity.this,"Message cannot be empty!",Toast.LENGTH_LONG).show();
                        return;
                    }
                    System.out.println("My App is default SMS App.");
                    //        对短信数据库进行处理
                    ContentResolver resolver=getContentResolver();

                    ContentValues values=new ContentValues();
                    values.put(Telephony.Sms.ADDRESS,mPhoneNumber.getText().toString());
                    values.put(Telephony.Sms.DATE, System.currentTimeMillis());
                    long dateSent=System.currentTimeMillis()-5000;
                    values.put(Telephony.Sms.DATE_SENT,dateSent);
                    values.put(Telephony.Sms.READ,false);
                    values.put(Telephony.Sms.SEEN,false);
                    values.put(Telephony.Sms.STATUS, Telephony.Sms.STATUS_COMPLETE);
                    values.put(Telephony.Sms.BODY, mMsg.getText().toString());
                    values.put(Telephony.Sms.TYPE, Telephony.Sms.MESSAGE_TYPE_INBOX);

                    Uri uri=resolver.insert(Telephony.Sms.CONTENT_URI,values);
                    if(uri!=null){
                        long uriId= ContentUris.parseId(uri);
                        System.out.println("uriId "+uriId);
                    }

                    Toast.makeText(MainActivity.this, "Insert a short Message.",
                            Toast.LENGTH_LONG).show();

//            对短信数据库处理结束后,恢复原来的默认SMS APP
                    Intent intent=new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
                    intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME,defaultSmsPkg);
                    startActivity(intent);
                    System.out.println("Recover default SMS App");

//                    打印出收件箱里的最新5条短信
                    Cursor cursor=getContentResolver().query(Telephony.Sms.CONTENT_URI,null,null,null,null);
                    String msg="";
                    while ((cursor.moveToNext()) &&
                            (cursor.getPosition()<5)){
                        int dateColumn=cursor.getColumnIndex("date");
                        int phoneColumn=cursor.getColumnIndex("address");
                        int smsColumn=cursor.getColumnIndex("body");

                        System.out.println("count "+cursor.getCount()+" position "+cursor.getPosition());
//                        把从短信中获取的时间戳换成一定格式的时间
                        SimpleDateFormat sfd=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                        Date date=new Date(Long.parseLong(cursor.getString(dateColumn)));
                        String time=sfd.format(date);
                        msg=msg+time+" "+cursor.getString(phoneColumn)+":"+cursor.getString(smsColumn)+"\n";
                        mMessageView.setText(msg);
                    }

                }
                else{
                    Toast.makeText(MainActivity.this,"Sorry,the App is not default Sms App.",
                            Toast.LENGTH_LONG).show();
                }
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

MmsReceiver.java

package tina.messagebox;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

/**
 * Created by Tina on 2015/8/11.
 */
public class MmsReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {

    }
}

SmsReceiver.java

package tina.messagebox;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

/**
 * Created by Tina on 2015/8/11.
 */
public class SmsReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {

    }
}

SmsSendService.java

package tina.messagebox;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class SmsSendService extends Service {
    public SmsSendService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return null;
    }
}


效果如下:


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果在Android 4.4系统中无法通过反射找到StorageManager中的format方法,您可以尝试使用Android提供的另一种方式来格式化外置SD卡。以下是一种可行的方法: 1. 在AndroidManifest.xml文件中添加以下权限: ```xml <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ``` 2. 在您的Activity或Fragment中使用以下代码进行格式化: ```java import android.content.Intent; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.provider.Settings; public class MainActivity extends AppCompatActivity { private static final int REQUEST_CODE_FORMAT_SD_CARD = 100; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); formatSdCard(); } private void formatSdCard() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { Intent intent = new Intent(Settings.ACTION_MEMORY_CARD_SETTINGS); startActivityForResult(intent, REQUEST_CODE_FORMAT_SD_CARD); } else { Uri uri = Uri.parse("file:///mnt/sdcard"); Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED, uri); sendBroadcast(intent); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_FORMAT_SD_CARD) { // 处理格式化完成后的操作 } } } ``` 3. 当您的应用程序运行时,它将打开设备的存储设置页面,供用户手动格式化SD卡。当用户完成格式化后,您可以在onActivityResult方法中处理格式化完成后的操作。 请注意,这种方法依赖于设备的存储设置页面,因此在不同的设备上可能会有所不同。确保在进行格式化之前备份重要数据,并测试代码以确保其在目标设备上正常工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值