Android KitKat Development

In this post I will cover Android KitKat developmnet including the main items like

– Printing Framework

– SMS Provider

– Animations using Transition Manager

– The New Sensor Manager

Printing Framework

PrintManager pManager = (PrintManager) this.getSystemService(Context.PRINT_SERVICE);
String job_name = this.getString(R.string.app_name) + " Document";
pManager.print(job_name, pda, null);

PrintDocumentAdapter pda = new PrintDocumentAdapter(){

@Override
public void onWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback){
InputStream input = null;
OutputStream output = null;

try {

input = new FileInputStream(file to print);
output = new FileOutputStream(destination.getFileDescriptor());

byte[] buf = new byte[1024];
int bytesRead;

while ((bytesRead = input.read(buf)) > 0) {
output.write(buf, 0, bytesRead);
}

callback.onWriteFinished(new PageRange[]{PageRange.ALL_PAGES});

} catch (FileNotFoundException ee){
//Catch exception
} catch (Exception e) {
//Catch exception
} finally {
try {
input.close();
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

@Override
public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras){

if (cancellationSignal.isCanceled()) {
callback.onLayoutCancelled();
return;
}

int pages = computePageCount(newAttributes);

PrintDocumentInfo pdi = new PrintDocumentInfo.Builder("Name of file").setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).build();

callback.onLayoutFinished(pdi, true);
}
};

 

You can check what printers are supported HERE on the Google’s page

SMS Provider

The Manifest

<manifest>
...
<application>
<!-- 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>

<!-- Activity that allows the user to send new SMS/MMS messages -->
<activity android:name=".ComposeSmsActivity" >
<intent-filter>
<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" />
</intent-filter>
</activity>

<!-- Service that delivers messages from the phone "quick response" -->
<service android:name=".HeadlessSmsSendService"
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
android:exported="true" >
<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>
</application>
</manifest>

 

Activity should behave like below:

public class ComposeSmsActivity extends Activity {

@Override
protected void onResume() {
super.onResume();

final String myPackageName = getPackageName();
if (!Telephony.Sms.getDefaultSmsPackage(this).equals(myPackageName)) {
View viewGroup = findViewById(R.id.not_default_app);
viewGroup.setVisibility(View.VISIBLE);

Button button = (Button) findViewById(R.id.change_default_app);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent =
new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, 
myPackageName);
startActivity(intent);
}
});
} else {
View viewGroup = findViewById(R.id.not_default_app);
viewGroup.setVisibility(View.GONE);
}
}
}

 

String defaultSmsApp = Telephony.Sms.getDefaultSmsPackage(context);
Intent intent = new Intent(context, Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Sms.Intents.EXTRA_PACKAGE_NAME, context.getPackageName());
startActivity(intent);
Intent intent = new Intent(context, Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Sms.Intents.EXTRA_PACKAGE_NAME, defaultSmsApp);
startActivity(intent);

 

Animations using Transition Manager

public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_transition_scene_1,
container, false);
final Scene scene = Scene.getSceneForLayout(container,
R.layout.fragment_transition_scene_2, getActivity());
Button goButton = (Button)rootView.findViewById(R.id.goButton);
goButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TransitionManager.go(scene);
}
});
return rootView;
}

 

The New Sensor Manager

private SensorManager sensorManager;
private TextView count;
boolean activityRunning;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
count = (TextView) findViewById(R.id.count);

sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
}

@Override
protected void onResume() {
super.onResume();
activityRunning = true;
Sensor countSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
if (countSensor != null) {
sensorManager.registerListener(this, countSensor, SensorManager.SENSOR_DELAY_UI);
} else {
Toast.makeText(this, "Count sensor not available!", Toast.LENGTH_LONG).show();
}

}

@Override
protected void onPause() {
super.onPause();
activityRunning = false;
// if you unregister the last listener, the hardware will stop detecting step events
// sensorManager.unregisterListener(this); 
}

@Override
public void onSensorChanged(SensorEvent event) {
if (activityRunning) {
count.setText(String.valueOf(event.values[0]));
}

}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}

 

Device Features
The following are new device features introduced in KitKat that can be declared with the <uses-feature> tag. These features declare your app requirements and enable filtering on Google Play or check for at runtime:

FEATURE_CONSUMER_IR

FEATURE_DEVICE_ADMIN

FEATURE_NFC_HOST_CARD_EMULATION

FEATURE_SENSOR_STEP_COUNTER

FEATURE_SENSOR_STEP_DETECTOR

App Permissions

The following are new permissions can be added in the manifest which your app must request with the <uses-permission> tag to use certain new APIs:

INSTALL_SHORTCUT
UNINSTALL_SHORTCUT
TRANSMIT_IR

Leave a Comment: